Reputation: 53
While attempting a question, I was required to split a number 'n' into 2 parts, each part falling within a given range (inclusive).
There can be more than one solution obviously, only one is required.
Example - n = 5 and Range = 2 to 4
Solutions would be (2,3) (3,2)
It's easy in the head but unable to derive a quick logic. Thank you
Language - C++
Upvotes: 0
Views: 208
Reputation: 11
#include<bits/stdc++.h>
using namespace std;
int main(){
int l,r,s;
cin>>l>>r>>s; //here l & r are range & s is sum that we want to split
if(2 * r < s){
cout<<0<<endl;
return 0;
}
int start,end;
start = s - l;
if(start > r){
start -= r;
start += l;
}
end = s-start;
int count = abs(end - start) + 1;
cout<<count<<endl;
return 0;
}
Upvotes: 1
Reputation: 3826
For each part to fall "within a given range (inclusive)", the solutions for n = 5 and Range = 2 to 4
would be (2,3), (3,2)
.
The most trivial solution is like this:
for i = range_min to range_max:
if range_min <= n - i <= range_max:
print (i, n-i)
Update. A deeper analysis:
a = range_min
b = range_max
a <= i <= b
a <= n - i <= b
a - n <= -i <= b - n
-a + n >= i >= -b + n
n - b <= i <= n - a
max(a, n-b) <= i <= min(b, n-a)
for i = max(a, n-b) to min(b, n-a):
print (i, n-i)
There is nothing more efficient possible, as anyway you need to loop through all the matching pairs at least to print them, and here there is only printing.
Update 2. Only one pair (if exists) and in C++:
#include <iostream>
#include <algorithm> // min, max
using namespace std;
int main()
{
int n, a, b;
cin >> n >> a >> b;
int lo = max(a, n-b);
int hi = min(b, n-a);
if (lo <= hi) {
cout << "(" << lo << ", " << n - lo << ")" << endl;
} else {
cout << "nope" << endl;
}
return 0;
}
Upvotes: 0
Reputation: 186668
I suggest enumeration instead of splitting:
to >= from
, value >= 2 * from
, value <= 2 * to
value - to
or from
[from..to]
range Sample C# 6.0 solution
public static IEnumerable<Tuple<int, int>> Ranges(int value, int from, int to) {
if (to < from) // empty range
yield break;
else if (value < 2 * from || value > 2 * to) // value is too small or too big
yield break;
// start either from left border or from minumum possible value within the range
int start = value - to >= from ? value - to : from;
// both i and value - i should be in [to..from] range
for (int i = start; i <= to && value - i >= from; ++i)
yield return new Tuple<int, int>(i, value - i); // (i, value - i) pair
}
Test:
var result = Ranges(5, 2, 4)
.Select(range => $"({range.Item1},{range.Item2})");
Console.Write(string.Join(" ", result));
Outcome:
(3,4) (4,3)
Upvotes: 0
Reputation: 10714
You haven't specified a language to use, so here's a very basic implementation with JavaScript:
var n = 5;
for (var i = 0; i < n-1; i++) {
var first = i + 1;
var second = n-i-1;
console.log('(' + first + ',' + second + ')' + ' ' + '(' + second + ',' + first + ')' );
}
Hope that helps!
Upvotes: 0