Get a number in an interval [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I would like to get a number between 5 and 250 from two variables according to the following pseudo-code:
arg[1-19] * something = [5 - 250]
arg will contain values (whole numbers) in the interval [1 - 19]; something could be any whole number.
The problem is that I obtain the same result using different combinations of arg and something:
arg: 1, something: 10 => result 10
arg: 2, something: 5 => result 10
How can I make sure that the result is different for any different pair of arg and something?
Is there a mathematical function or a function in java to do this?

I don't think you have a problem with programming. Instead, I think you should go one step back and try to understand your problem at mathematical level. Consider the equation
(1) a * b = C
for any (arbitrarily chosen) C, with a, b and C being whole numbers.
Unless a and b are both prime, there will at least be one pair of other a, b which also satisfy the equation. The proof is very simple if you think about it for a minute:
Suppose that a is not prime (the proof would be the same for b being not prime). Then there must be at least two whole numbers p and a' (p not being one by definition) so that
(2) a = p * a'
Now define that
(3) b' = p * b
Using equations (2) and (3), you can re-arrange equation (1) like that:
(4) C = a * b = (p * a') * b = a' * (p * b) = a' * b'
q.e.d
Here, since p != 1 (by definition - see above), a != a' and b != b'.
This means that you must have both factors a, b prime if you want to guarantee that every different pair (a, b) will give a different result a * b.
You did not tell us what you are actually trying to achieve, but probably there is a better solution than multiplying two whole numbers.
For example, if we knew that your something is always less than ten (i.e. is 0, 1, ..., 9), you could do (arg * 10) + something (this is only an example to show the principle; it would give values between 10 and 199 considering the restriction for arg you have mentioned, so it is actually not a solution to your problem; I have chosen that numbers because our decimal system basically works that way :-) and thus you already know about it).
And finally, so trivial that it possibly doesn't come to mind, remember that a * b = b * a (multiplication is commutative at least for our whole, real and irrational numbers and some more which I don't dare to mention). Applied to your problem: arg * something = something * arg. Of course, this is still true even if arg and something are both prime. It is inevitable that you get the same result if you exchange the values of arg and something. This might or might not be acceptable for whatever you are trying to achieve.

If something can take more than 12 values, this is not possible, as your input space will have a size of at least 19 * 13 = 247 whereas your output space has a size of 245.
If something takes less than 12 values, you can simply do: 19 *$something + arg + 4 assuming you map the values of something to the interval [0,n]

If your goal is to given an "arg" number you return a "something" number such that the result of arg*something is insiade a given interval, try this :
public static void main (String[] args) throws java.lang.Exception
{
System.out.println(findNumber(2, 5, 250));
}
public static int findNumber(int arg, int min, int max) {
Random rand = new Random();
int randMin;
int randMax;
if(min%arg == 0){
randMin = min/arg;
} else {
randMin = (min / arg) + 1;
}
randMax = max/arg;
int result = rand.nextInt(randMax+1-randMin);
result = result + randMin;
return result;
}

Related

I have an algorithm but don't know how or why does it work [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
The task goes as such:
Two friends have one set of chocolate slabs each. The sizes of the respective slabs are provided as arrays of element type int. Since the two are very good friends, they plan to exchange a single slab such that both overall possess an equal amount of chocolate.
Your method should return an array of length 2. The first and second elements record the sizes of slabs of the first and second friend, respectively, to achieve this goal.
If there are several possible solutions, you may return any of these.
Fair Friends: Example 1 No results
Parameter: A = {1,1}, B = {2,2}
Return value: {1,2}
Fair Friends: Example 2 No results
Parameter: A = {1,2}, B = {2,3}
Return value: {1,2}
Fair Friends: Example 3 No results
Parameter: A = {2}, B = {1,3}
Return value: {2,3}
Faire Freunde: Beispiel 4 No results
Parameter: A = {1,2,5}, B = {2,4}
Return value: {5,4}
and this is the code:
public static int arraySum(int[] a){
int result = 0;
for(int i = 0; i<a.length; i++){
result+=a[i];
}
return result;
}
public static int[] fairFriends(int[] arr, int[] arr2) {
int[] result = new int[2];
int sum1 = arraySum(arr);
int sum2 = arraySum(arr2);
int sub = sum1 - sum2;
for(int i = 0; i<arr.length; i++){
for(int j = 0; j < arr2.length; j++){
if(sub/2 == arr[i] - arr2[j]){
result[0] = arr[i];
result[1] = arr2[j];
}
}
}
return result;
}
This was sent to me by my groupmate. I tried to think through the code but I really don't get the idea in the calculations why does this work.... I just want an explanation.
A = {2}, B = {1,3} Return value: {2,3}
Let's first pull this example apart.
before the exchange, A's total amount of chocolate is 2, and B has 4 (1+3).
Then, an exchange happens: A transfers their 2-sized slab over (subtract 2 from A's and add 2 to B's, so they are now at {0, 6}, and then B transfers their 3-sized slab, so subtract 3 from B and add 3 to A: {3, 3}, which is in balance, therefore {2, 3} is the right answer.
Clearly then, one rather inefficient strategy is to simulate the exchange of every single slab A has vs. every single last slab B has, and return the moment we just so happen to stumble upon an exchange that results in the end result being balanced.
And that's exactly what your algorithm does: It exchanges every possible slab for both A and B until it finds a hit:
int sum1 = arraySum(arr);
sum1 is the size of A's chocolate hoard, pre-exchange. In our example, 2.
int sum2 = arraySum(arr2);
sum2 is the size of B's chocolate hoard, pre-exchange. In our example, 4.
int sub = sum1 - sum2;
The difference between how much chocolate A has vs. how much B has (-2 means: B has 2 more chocolate than A). This means that half this number needs to 'flow' from A to B for balance (in this example, the desired flow is -1: a net of 1 chocolate needs to go from B to A, then we have balance). The 'half' part comes later, though - it would have been easier to read and more efficient to do the /2 here.
for(int i = 0; i<arr.length; i++){
for(int j = 0; j < arr2.length; j++){
A double nested loop; i/j will cover every potential exchange. This grows FAST. If A has 10 slabs of chocolate and B has 20 slabs, then there are 200 possible exchanges, and this construct will consider them all.
if(sub/2 == arr[i] - arr2[j]){
We have selected one of A's slabs to give away to B (the i-th slab), and one of B's slabs to give to A (the j-th slab). So, let's get the size of A's i-th slab (arr[i]) and the size of B's j-th slab (arr2[j]), and check the difference. In our example (remember, it was A={2}, B={1,3} to start), the right exchange is i=0 (A's 2-sized slab) and j=1 (B's 3-sized slab). 2-3 is -1, as in, this is a net 'flow' of chocolate where 1 flows from B to A (if it was positive, it would be from A to B). It's what we wanted, and here the /2 shows up. Our sub value was -2, it is divided by 2, so that makes for -1, and that is equal to arr[i] - arr2[j]. If this if block succeeds, we found an exchange that'll work: The code then sets the values of result, otherwise, do nothing, and notably, keep going, even though we already have an answer - that's just this particular algorithm being bad.
Then, result is returned, incidentally that also means the algorithm returns "A should exchange their first slab with B's first slab" if there is no exchange possible, i.e. the code just straight up is wrong if no exchange is possible. I guess the exercise does not care that your code fails by giving a wrong answer if no exchange is possible.
There are more efficient ways of doing this, but they'd involve writing more code. For example, you can sort A's slabs and B's slabs by size first (that's 2 O(nlogn) operations), then loop through A's slabs (O(n)), and for each slab calculate how large B's slab would have to be to make the exchange perfect. If it's negative, continue; immediately to A's next slab. Otherwise, use binary search to check if B has a slab of this desired size. binary search is O(logn). If yes, return the right result, if not, move on to A's next slab.
That's 2*O(n logn) (O(n) * O(log n)), which boils down to O(nlogn), whereas your algorithm is O(n^2).
That means, if you graph the performance of these 2 algorithms by graphing '# of slabs that the 2 friends have' against 'how much time it takes for the algorithm to finish calculating the result', your algorithm looks like y=x^2, and the above looks like y=x * log(x), and therefore 'my' algorithm will eventually be faster, and significantly so, given large enough inputs.
Usually with algorithm exercises like this, the point is to find the most efficient algorithm, and correct code that nevertheless takes too long for the (generally quite large) test inputs is still deemed a failure.
That may not be the case here, but, it seemed pertinent to tell you about a more efficient algorithm.

Algorithm for adding two numbers to reach a value

I have a homework assignment that asks of me to check, for any three numbers, a,b,c such that 0<=a,b,c<=10^16, if I can reach c by adding a and b to each other. The trick is, with every addition, their value changes, so if we add a to b, we would then have the numbers a and a+b, instead of a and b. Because of this, I realized it's not a simple linear equation.
In order for this to be possible, the target number c, must be able to be represented in the form:
c = xa + yb
Through some testing, I figured out that the values of x and y, can't be equal, nor can both of them be even, in order for me to be able to reach the number c. Keeping this in mind, along with some special cases involving a,b or c to be equal to zero.
Any ideas?
EDIT:
It's not Euclid's Algorithm, it's not a diophantine equation, maybe I have mislead you with the statement that c = xa + yc. Even though they should satisfy this statement, it's not enough for the assignment at hand.
Take a=2, b=3, c=10 for example. In order to reach c, you would need to add a to b or b to a in the first step, and then in the second step you'd get either : a = 2, b = 5 or a = 5, b = 3, and if you keep doing this, you will never reach c. Euclid's algorithm will provide the output yes, but it's clear that you can't reach 10, by adding 2 and 3 to one another.
Note: To restate the problem, as I understand it: Suppose you're given nonnegative integers a, b, and c. Is it possible, by performing a sequence of zero or more operations a = a + b or b = b + a, to reach a point where a + b == c?
OK, after looking into this further, I think you can make a small change to the statement you made in your question:
In order for this to be possible, the target number c, must be able to
be represented in the form:
c = xa + yb
where GCD(x,y) = 1.
(Also, x and y need to be nonnegative; I'm not sure if they may be 0 or not.)
Your original observation, that x may not equal y (unless they're both 1) and that x and y cannot both be even, are implied by the new condition GCD(x,y) = 1; so those observations were correct, but not strong enough.
If you use this in your program instead of the test you already have, it may make the tests pass. (I'm not guaranteeing anything.) For a faster algorithm, you can use Extended Euclid's Algorithm as suggested in the comments (and Henry's answer) to find one x0 and y0; but if GCD(x0,y0) ≠ 1, you'd have to try other possibilities x = x0 + nb, y = y0 - na, for some n (which may be negative).
I don't have a rigorous proof. Suppose we constructed the set S of all pairs (x,y) such that (1,1) is in S, and if (x,y) is in S then (x,x+y) and (x+y,y) are in S. It's obvious that (1,n) and (n,1) are in S for all n > 1. Then we can try to figure out, for some m and n > 1, how could the pair (m,n) get into S? If m < n, this is possible only if (m, n-m) was already in S. If m > n, it's possible only if (m-n, n) was already in S. Either way, when you keep subtracting the smaller number from the larger, what you get is essentially Euclid's algorithm, which means you'll hit a point where your pair is (g,g) where g = GCD(m,n); and that pair is in S only if g = 1. It appears to me that the possible values for x and y in the above equation for the target number c are exactly those which are in S. Still, this is partly based on intuition; more work would be needed to make it rigorous.
If we forget for a moment that x and y should be positive, the equation c = xa + yb has either no or infinitely many solutions. When c is not a multiple of gcd(a,b) there is no solution.
Otherwise, calling gcd(a,b) = t use the extended euclidean algorithm to find d and e such that t = da + eb. One solution is then given by c = dc/t a + ec/t b.
It is clear that 0 = b/t a - a/t b so more solutions can be found by adding a multiple f of that to the equation:
c = (dc + fb)/t a + (ec - af)/t b
When we now reintroduce the restriction that x and y must be positive or zero, the question becomes to find values of f that make x = (dc + fb)/t and y = (ec - af)/t both positive or zero.
If dc < 0 try the smallest f that makes dc + fb >= 0 and see if ec - af is also >=0.
Otherwise try the largest f (a negative number) that makes ec - af >= 0 and check if dc + fb >= 0.
import java.util.*;
import java.math.BigInteger;
public class Main
{
private static boolean result(long a, long b, long c)
{
long M=c%(a+b);
return (M%b == 0) || (M%a == 0);
}
}
Idea:c=xa+by, because either x or y is bigger we can write the latter equation in one of two forms:
c=x(a+b)+(y-x)b,
c=y(a+b)+(x-y)a
depending on who is bigger, so by reducing c by a+b each time, c eventually becomes:
c=(y-x)b or c=(x-y)b, so c%b or c%a will evaluate to 0.

Finding all Logical Combinations of a Set

I am writing to ask if anyone knows how to go about this. I do not need the code, I would just like the logic behind doing this. So I have a set {A,B,C,D,E}. Now I want to find all combinations of and or OR operators amongst the values in the set.
Some examples below.
A and B and C and D and E
A and B and C and D or E
A and B and C or D and E
From what I know there is 2^n-1 possibilities in the case above. So in the specific example above we would have 8 combinations.
In addition to the Above the values in the set can have two possibilities. For simplicities sake lets say A can be True or False. Likewise B,C,D and E. So what we would potentially have is something like the following :
A=True and B=True and C=True and D=True and E=True
A=True and B=True and C=True and D=True and E=False
A=True and B=True and C=True and D=True or E=True
and so on. So taking this into account we would have 2^(2 * n-1) combinations. So in our specific example above again we would have 16 combinations for a set of 4.
Is there an algorithm that already does this? If not would anyone have some logic to implement this in Java
Thanks,
I think you're saying you want to enumerate (perhaps print) all the distinct expressions of the forms you have described, for some set size n. Since each one can be characterized by a set of flags (=True vs =False at positions 1 ... n, and And vs Or at positions 1 ... n - 1), you can represent each expression as an integer, with each flag corresponding to one (binary) bit. If n has a value for which you could hope to explicitly enumerate all the possibilities, such an integer will be well within the range of a Java long. For comfortably being able to enumerate all the possibilities, such an integer will be within the range of a Java int.
One way to proceed, therefore, would be to write a method to decode in-range integers into expressions according to their bit patterns. You can then iterate over all the appropriate integers (i.e. 0 ... (1 << (2 * n)) - 1), and decode each one into the corresponding expression.
If you have to get possible combination of five boolean values, you can do one thing -
Iterate a loop from zero to binary value "11111".
In each iteration you will get a unique combination of 0 and 1.
Convert 1 to true and 0 to false.
I hope below code will be helpful :
import java.util.ArrayList;
public class Test{
public static void main (String[] args)
{
ArrayList<boolean[]> result = new ArrayList<boolean[]>();
int max_num = Integer.parseInt("11111", 2);
for(int i=max_num; i>=0; i--)
{
String val = String.format("%5s", Integer.toBinaryString(i)).replace(' ', '0');
boolean[] arr = new boolean[5];
char[] charArray = val.toCharArray();
for(int j=0; j<charArray.length;j++)
{
if(charArray[j]=='1')
{
arr[j]=true;
}
else
{
arr[j]=false;
}
}
result.add(arr);
arr=null;
val=null;
}
for(int i=0;i<result.size();i++)
{
for(boolean b: result.get(i))
{
System.out.print(b+" ");
}
System.out.println();
}
}
}
To change the variable count :
Replace same count of 1 with "11111". e.g. if variable count is 6, it should be "111111"
Change "%5s" accordingly. e.g. if variable count is 6, it should be "%6s".
Initialize array "arr" with same count.

Number Guessing Game Over Intervals

I have just started my long path to becoming a better coder on CodeChef. People begin with the problems marked 'Easy' and I have done the same.
The Problem
The problem statement defines the following -:
n, where 1 <= n <= 10^9. This is the integer which Johnny is keeping secret.
k, where 1 <= k <= 10^5. For each test case or instance of the game, Johnny provides exactly k hints to Alice.
A hint is of the form op num Yes/No, where -
op is an operator from <, >, =.
num is an integer, again satisfying 1 <= num <= 10^9.
Yes or No are answers to the question: Does the relation n op num hold?
If the answer to the question is correct, Johnny has uttered a truth. Otherwise, he is lying.
Each hint is fed to the program and the program determines whether it is the truth or possibly a lie. My job is to find the minimum possible number of lies.
Now CodeChef's Editorial answer uses the concept of segment trees, which I cannot wrap my head around at all. I was wondering if there is an alternative data structure or method to solve this question, maybe a simpler one, considering it is in the 'Easy' category.
This is what I tried -:
class Solution //Represents a test case.
{
HashSet<SolutionObj> set = new HashSet<SolutionObj>(); //To prevent duplicates.
BigInteger max = new BigInteger("100000000"); //Max range.
BigInteger min = new BigInteger("1"); //Min range.
int lies = 0; //Lies counter.
void addHint(String s)
{
String[] vals = s.split(" ");
set.add(new SolutionObj(vals[0], vals[1], vals[2]));
}
void testHints()
{
for(SolutionObj obj : set)
{
//Given number is not in range. Lie.
if(obj.bg.compareTo(min) == -1 || obj.bg.compareTo(max) == 1)
{
lies++;
continue;
}
if(obj.yesno)
{
if(obj.operator.equals("<"))
{
max = new BigInteger(obj.bg.toString()); //Change max value
}
else if(obj.operator.equals(">"))
{
min = new BigInteger(obj.bg.toString()); //Change min value
}
}
else
{
//Still to think of this portion.
}
}
}
}
class SolutionObj //Represents a single hint.
{
String operator;
BigInteger bg;
boolean yesno;
SolutionObj(String op, String integer, String yesno)
{
operator = op;
bg = new BigInteger(integer);
if(yesno.toLowerCase().equals("yes"))
this.yesno = true;
else
this.yesno = false;
}
#Override
public boolean equals(Object o)
{
if(o instanceof SolutionObj)
{
SolutionObj s = (SolutionObj) o; //Make the cast
if(this.yesno == s.yesno && this.bg.equals(s.bg)
&& this.operator.equals(s.operator))
return true;
}
return false;
}
#Override
public int hashCode()
{
return this.bg.intValue();
}
}
Obviously this partial solution is incorrect, save for the range check that I have done before entering the if(obj.yesno) portion. I was thinking of updating the range according to the hints provided, but that approach has not borne fruit. How should I be approaching this problem, apart from using segment trees?
Consider the following approach, which may be easier to understand. Picture the 1d axis of integers, and place on it the k hints. Every hint can be regarded as '(' or ')' or '=' (greater than, less than or equal, respectively).
Example:
-----(---)-------(--=-----)-----------)
Now, the true value is somewhere on one of the 40 values of this axis, but actually only 8 segments are interesting to check, since anywhere inside a segment the number of true/false hints remains the same.
That means you can scan the hints according to their ordering on the axis, and maintain a counter of the true hints at that point.
In the example above it goes like this:
segment counter
-----------------------
-----( 3
--- 4
)-------( 3
-- 4
= 5 <---maximum
----- 4
)----------- 3
) 2
This algorithm only requires to sort the k hints and then scan them. It's near linear in k (O(k*log k), with no dependance on n), therefore it should have a reasonable running time.
Notes:
1) In practice the hints may have non-distinct positions, so you'll have to handle all hints of the same type on the same position together.
2) If you need to return the minimum set of lies, then you should maintain a set rather than a counter. That shouldn't have an effect on the time complexity if you use a hash set.
Calculate the number of lies if the target number = 1 (store this in a variable lies).
Let target = 1.
Sort and group the statements by their respective values.
Iterate through the statements.
Update target to the current statement group's value. Update lies according to how many of those statements would become either true or false.
Then update target to that value + 1 (Why do this? Consider when you have > 5 and < 7 - 6 may be the best value) and update lies appropriately (skip this step if the next statement group's value is this value).
Return the minimum value for lies.
Running time:
O(k) for the initial calculation.
O(k log k) for the sort.
O(k) for the iteration.
O(k log k) total.
My idea for this problem is similar to how Eyal Schneider view it. Denoting '>' as greater, '<' as less than and '=' as equals, we can sort all the 'hints' by their num and scan through all the interesting points one by one.
For each point, we keep in all the number of '<' and '=' from 0 to that point (in one array called int[]lessAndEqual), number of '>' and '=' from that point onward (in one array called int[]greaterAndEqual). We can easily see that the number of lies in a particular point i is equal to
lessAndEqual[i] + greaterAndEqual[i + 1]
We can easily fill the lessAndEqual and greaterAndEqual arrays by two scan in O(n) and sort all the hints in O(nlogn), which result the time complexity is O(nlogn)
Note: special treatment should be taken for the case when the num in hint is equals. Also notice that the range for num is 10^9, which require us to have some forms of point compression to fit the array into the memory

Recursion to get the number of different combinations of n people and k groups

I'm practicing recursion using Java and I've hit a problem. I'm trying to make a method which I'm calling "groups" which takes a number of people and how many groups there are and returns the number of different combinations there are of people and groups. Also, the ordering of people in the groups does not matter, nor does the ordering of the groups.
The code I have so far is:
public long groups(int n, int k) {
if(k==1) return 1;
if(k==n) return 1;
else return groups(n-1, k) + groups(n-1, k-1);
}
However it returns the wrong values. The first two lines are the base cases, which say if there is 1 group, then there is only one way to split the people up, makes sense. The other is when there are just as many people as there are groups, in which case theres only one way to split them up, one person into each group. The last statement is where I think I'm having problems, I would think that each time it does a recursive call, one person has to be taken out (n is the number of people, so n-1) and that person can ether join a group (k) or make their own group (k-1).
I'm just having a little trouble figuring out how recursion works and could use a little help.
These are the values I'm expecting:
groups(2,1) = 1
groups(2,2) = 1
groups(3,2) = 3
groups(4,2) = 7
groups(4,3) = 6
groups(5,3) = 25
There is something missing in the implementation of that part
... and that person can ether join a group (k) ...
I think the person can join 'k' groups, so the code must be
public long groups(int n, int k) {
if(k==1) return 1;
if(k==n) return 1;
else return k * groups(n-1, k) + groups(n-1, k-1);
}
(was missing multiplication by k)
There's a much easier (faster) way to compute combinations -- that's the binomial coefficient. While I can understand that your teacher may want you write a recursive function this way to become familiar with recursion, you can use this formula as a check.
In your case, you're reporting the wrong expected values here. What you want is
groups(2,1) = 2
groups(2,2) = 1
groups(3,2) = 3
groups(4,2) = 6
groups(4,3) = 4
groups(5,3) = 10
and the code you've posted is correct if the values above are what it's supposed to return.
(If not, perhaps you can better clarify the problem by explaining more clearly how the problem you're solving differs from the binomial coefficient.)

Categories