My friend sent me a simple java math task to find if any 2 numbers of 3 inserted are even. I did it but then could not understand how it worked.
I sum all three numbers and then find remainder of division of their sum. It works but if all numbers are odd it shows true anyway. So I needed one more condition.
And I wondered why only multiplication works here, why there is no way to add numbers and change the condition to get the correct result.
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
int firstNumber = scanner.nextInt();
int secondNumber = scanner.nextInt();
int thirdNumber = scanner.nextInt();
int sumOfNumbers = firstNumber + secondNumber + thirdNumber;
boolean if2NumbersEven = sumOfNumbers % 2 != 0 &&
// Why is only multiplication needed here, addition does not work
firstNumber * secondNumber % 2 == 0;
System.out.println(if2NumbersEven);
}
P.S. I understand how dumb the question is, I have spent hours learning java today and my brain really stopped working.
You can just sum the rest of the division by 2 of the 3 numbers. If it returns 1, it means that exactly 2 of the 3 numbers are even. Like this:
int restsOfDivisionsBy2 = (firstNumber % 2) + (secondNumber % 2) + (thirdNumber % 2);
boolean if2NumbersEven = (restsOfDivisionsBy2 == 1);
I only use 1 and 2 for odd and even, because it's easier to understand.
The first part of the condition you did already figure out:
sumOfNumbers % 2 != 0
// 1+1+1 % 2 = 1 => true
// 1+1+2 % 2 = 0 => false
// 1+2+2 % 2 = 1 => true
// 2+2+2 % 2 = 0 => false
It's true if there are zero or two even numbers.
The second condition is needed to get rid of the "three uneven numbers" (= zero even numbers) case:
firstNumber * secondNumber % 2 == 0
// 1*1 % 2 = 1 => false
// 1*2 % 2 = 0 => true
// 2*2 % 2 = 0 => true
As you can see: This condition is only true if there's at least one or two even numbers. ("at least" because the third number has no impact on the result of this condition, it can be even or odd).
And if one, two or three numbers are even, then it's impossible that all three are odd (= it's impossible that there's no even number).
If you combine both you get something like this:
| 3 even | 2 even | 1 even | 0 even
-----------------------------------------------
1.condition | false | true | false | true
-----------------------------------------------
2.condition | true | true | true | false
-----------------------------------------------
result | false | true | false | false
If you use addition instead of multiplication, it won't work:
firstNumber + secondNumber % 2 == 0
// 1+1 % 2 = 0 => true
// 1+2 % 2 = 1 => false
// 2+2 % 2 = 0 => true
Now the condition would be true if "at least 2 numbers are odd". And this can mean that all three are odd.
The sum of all mods tells you exactly how many odd numbers you have.
int allMods = firstNumber%2 + secondNumber%2 + thirdNumber%2
Proof (in PowerShell)
PS C:\windows\system32>
$firstNumber = 1
$secondNumber = 2
$thirdNumber = 5
$firstNumber%2 + $secondNumber%2 + $thirdNumber%2
2
PS C:\windows\system32>
$firstNumber = 1
$secondNumber = 3
$thirdNumber = 5
$firstNumber%2 + $secondNumber%2 + $thirdNumber%2
3
PS C:\windows\system32>
$firstNumber = 1
$secondNumber = 2
$thirdNumber = 5
$firstNumber%2 + $secondNumber%2 + $thirdNumber%2
2
PS C:\windows\system32>
$firstNumber = 1
$secondNumber = 2
$thirdNumber = 4
$firstNumber%2 + $secondNumber%2 + $thirdNumber%2
1
The count of all numbers minus this resulting allMods number will give you the count of all even numbers.
For three numbers a, b, c let's look at the value of the expression (a + b + c) % 2 for differing numbers of odd values:
# odd (a+b+c)%2
0 0
1 1
2 0
3 1
So we can narrow down the cases to 1 and 3 just by checking for (a + b + c) % 2 != 0. Now we need to distinguish between one odd and all three odd.
Two odd numbers multiplied together give an odd result - in all other cases the result is even. So, if we pick any two of the three numbers and find that their product is even then at least one of them must be even, in which case all three cannot be odd, and we've identified the case of interest.
if2NumbersEven(a, b, c) = (a + b + c) % 2 == 1 and (a * b) % 2 == 0
I was implementing a very simple recursive method to multiply two numbers together. I am very a hard time understanding the basics of recursion.
Is anyone able to explain to me (Line-by-line if possible) how this code works? I am especially confused about the base case is written to return 0 when in reality the actual multiplication is returned instead.
public static int multiply(int n, int m) {
if (m == 0) {
return 0; //Base case
}
return multiply(n, m - 1) + n; //Recursive Case - Decrements m, while adding n
}
Thanks for any help
I will try to make this answer beginner friendly. First I will answer this part of your question:
I am especially confused about the base case is written to return 0
when in reality the actual multiplication is returned instead.
The value returned in the base case depends on how you are implementing your algorithm. Here in order to calculate n*m, we extend this multiplication to addition. A few examples will make this more clear.
2*3 = 2 + 2 + 2 + 0
4*1 = 4 + 0
5*5 = 5 + 5 + 5 + 5 + 5 + 0
n*m = n + n + n + ... + (m times) + 0
That is why we return 0 in the base case, we have to stop the recursion without making any change in the result and that is only possible if we add 0.
Here is the working of this program:
public static int multiply(int n, int m) {
if (m == 0) {
return 0; //Base case
}
return multiply(n, m - 1) + n;
Let us take n = 4 and m = 3.
Our first call to the method is multiply(4, 3). We then proceed further, the base condition is false so we skip that.
We then get to this part: return multiply(n, m - 1) + n. We make another call to the same function. multiple(4, 2). Again we skip the base case. Here is a table:
multiply(4, 3) -> return multiply (4, 2) + 4
multiple(4, 2) -> return multiply (4, 1) + 4
multiple(4, 1) -> return multiply (4, 0) + 4
multiple(4, 0) -> 0
On substituting the returned values we get,
multiple(4, 3) -> return 0 + 4 + 4 + 4
multiple(4, 2) -> return 0 + 4 + 4
multiple(4, 1) -> return 0 + 4
multiple(4, 0) -> return 0
If our first call is multiply(n, m), then the end returned value is:
multiply (n, m) -> return 0 + n + n + n + ... + (m times)
I hope I have helped you. Try to construct a similar relation like this on your own and you will understand it better. Here is a link on further explanation on recursion:
https://www.geeksforgeeks.org/recursion
I don't understand how this exercise return the number's square. In particular I don't understand the sixth line in which there is return statement and after this "+2*x-1". What is the program behavior in that call?
public class Es {
public static int RecCalc(int x) {
if (x==0) {
return 0;
}else {
return RecCalc(x - 1) + 2 * x - 1;
}
}
public static void main(String[] args) {
System.out.println(RecCalc(3));
}
}
We can see how this works with a little algebra:
(x-1)² + 2x - 1
== x² - 2x + 1 + 2x - 1
== x²
If you are unfamiliar with the formula for (x + y)² then you can do (x-1)² by writing it as (x-1)*(x-1) and using the FOIL method or the distributive property. This is left as an exercise for the reader.
Let's step through, one call at a time.
The first call to kick it all off is:
RecCalc(3);
In Java, the return statement will take everything up to the semi-colon.
So, return 3 + 2 will return 5 to the caller.
RecCalc(3) will result in calling:
RecCalc(2) + 2*3 -1;
RecCalc(2) will result in calling:
RecCalc(1) + 2*2 -1;
RecCalc(1) will result in calling:
RecCalc(0) + 2*1 - 1;
RecCalc(0) will return 0.
Now we can work our way back up the call stack.
RecCalc(0) == 0
RecCalc(1) == RecCalc(0) + 2*1 -1 == (0) + 2*1 -1 == 1
RecCalc(2) == RecCalc(1) + 2*2 -1 == (1) + 2*2 -1 == 4
RecCalc(3) == RecCalc(2) + 2*3 -1 == (4) + 2*3 -1 == 9
This doesn't explain the math, but explains the recursion.
Let's look at the math.
As explained by #CodeApprentice, x² = (x-1)² + 2x -1
The real trick to this whole recursive scheme is the (x-1)².
We know that for x = 4, we can use (x-1)² plus some other junk to get the answer.
But that's just the square of 3 plus some other junk!
Now, to get the square of 3, we know that 3² = (x-1)² plus junk.
But that's just the square of 2 plus some other junk!
And so, we work our way down until we get to a trivial answer, where we return 0. (In fact, you could also return 1 for x=1).
I hope that explains it!
If you have 4 things, you can make a square with side 2:
xx
xx
If you want to make a square with side 3, you need 9 things: add 2 things on each of the side and bottom, plus 1 for the corner:
xx.
xx.
..+
Or, to put it another way, add 3 things on each of the side and bottom, take away 1 for the corner.
Generalizing, if you have a square of side length (n-1), to make a square of side length (n), you have to add on 2 lots of (n-1) things, plus one; or 2 lots of (n) things, take away one.
Hence:
number of things in a square of side length n
= (number of things in a square of side length (n-1))
+ 2 * (n-1) + 1
= (number of things in a square of side length (n-1))
+ 2 * n - 1
Perhaps if you put in a print statement it will help.
public static void main(String[] args) {
System.out.println(RecCalc(5));
}
public static int RecCalc(int x) {
if (x == 0) {
return 0;
} else {
int v = RecCalc(x - 1) + 2 * x - 1;
System.out.println((x-1) + " " + (2*x) + " " + (-1));
return v;
}
}
Prints
0 2 -1
1 4 -1
2 6 -1
3 8 -1
4 10 -1
25
Notice that the value of the sum of the last two columns in each line is an odd number. And the sum of any number of consecutive odd numbers starting with 1 is a perfect square. So essentially, this method just sums up the first x odd numbers.
The problem is I have to print all combinations of a sequence of
numbers from 1 to N that will always result to zero. It is allowed
to insert "+" (for adding) and "-" (for subtracting) between each
numbers so that the result will be zero.
//Output
N = 7
1 + 2 - 3 + 4 - 5 - 6 + 7 = 0
1 + 2 - 3 - 4 + 5 + 6 - 7 = 0
1 - 2 + 3 + 4 - 5 + 6 - 7 = 0
1 - 2 - 3 - 4 - 5 + 6 + 7 = 0
So how can I implement this? I am not asking for the actual
codes to do this, just a hint and ideas to solve this will
do. Thank you..
You could also use recursion here. Just remember your current integer, your max integer, your current sum and some kind of history of operations (could also be your final sequence).
In every level you proceed the path in two dirdctions: adding to your sum and substracting from it.
I did a quick implementation in Python, but it should be easy to transfer this to Java or whatever you are using.
def zero_sum(curr, n, seq, sum):
if curr == n and sum == 0:
print(seq)
elif curr < n:
zero_sum(curr + 1, n, seq + " - " + str(curr + 1), sum - (curr + 1))
zero_sum(curr + 1, n, seq + " + " + str(curr + 1), sum + (curr + 1))
zero_sum(1, 7, "1", 1)
Hopefully you get the idea.
The first step is to turn the problem into an entirely regularly formed problem:
n
∑ ±i = -1
i=2
n-2
∑ ±(i+2) = -1
i=0
The term 1 at the start has no prefix +/-. And the walking index better runs from 0 when using a Java array.
So one has n-1 coefficients -1 or +1 for the possible values.
A brute force approach would be to start with the highest values, i = n-2.
The upper/lower bounds for j = 0, ..., i would be ± (i + 1) * (2 + i + 2) / 2, so one can cut the evaluation there - when the till then calculated sum can no longer reach -1.
To represent the coefficients, one could make a new int[n - 1] or simply a new BitSet(n-1).
public void solve(int n) {
int i = n-2;
int sumDone = 0;
BigSet negates = new BitSet(n - 1);
solveRecursively(i, sumDone, negates);
}
private void solveRecursively(int i, int SumDone, BitSet negates) {
if (i < 0) {
if (sumDone == -1) {
System.out.println("Found: " + negates);
}
return;
}
...
}
The interesting, actual (home) work I leave to you. (With BitSet better i = n, ... , 2 by -1 seems simpler though.)
The question here is how much efficiency matters. If you're content to do a brute-force approach, a regression method like the one indicated by holidayfun is a fine way to go, though this will become unwieldy as n gets large.
If performance speed matters, it may be worth doing a bit of math first. The easiest and most rewarding check is whether such a sum is even possible: since the sum of the first n natural numbers is n(n+1)/2, and since you want to divide this into two groups (a "positive" group and a "negative" group) of equal size, you must have that n(n+1)/4 is an integer. Therefore if neither n nor n+1 is divisible by four, stop. You cannot find such a sequence that adds to zero.
This and a few other math tricks might speed up your application significantly, if speed is of the essence. For instance, finding one solution will often help you find others, for large n. For instance, if n=11, then {-11, -10, -7, -5} is one solution. But we could swap the -5 for any combination that adds to 5 that isn't in our set. Thus {-11, -10, -7, -3, -2} is also a solution, and similarly for -7, giving {-11, -10, -5, -4, -3} as a solution (we are not allowed to use -1 because the 1 must be positive). We could continue replacing the -10, the -11, and their components similarly to pick up six more solutions.
This is probably how I'd approach this problem. Use a greedy algorithm to find the "largest" solution (the solution using the largest possible numbers), then keep splitting the components of that solution into successively smaller solutions. It is again fundamentally a recursion problem, but one whose running time decreases with the size of the component under consideration and which at each step generates another solution if a "smaller" solution exists. That being said, if you want every solution then you still have to check non-greedy combinations of your split (otherwise you'd miss solutions like {-7, -4, -3} in your n=7 example). If you only wanted a lot of solutions it would definitely be faster; but to get all of them it may be no better than a brute-force approach.
If I were you I would go for a graph implementation, and DFS algorithm. Imagine you have N nodes that are representing your numbers. Each number is connected to another via an "add" edge, or a "subtract" edge. So you have a fully connected graph. You can start from a node and compute all dfs paths that lead to zero.
For more information about DFS algorithm, you can see the wikipage.
Edit: In order to clarify my solution, the graph you will end up having will be a multigraph, which means that it has more than one edge between nodes. DFS in a multigraph is slightly more complicated, but it is not that hard.
I would suggest a straight forward solution because as you mentioned you are dealing with consecutive integer from 1 to N which are fixed. The only things that vary are the operators in between.
Let's look at your example before we implement a general solution:
For n = 7 you need somehow to produce all possible combinations:
1+2+3+4+5+6+7
1+2+3+4+5+6-7
1+2+3+4+5-6+7
1+2+3+4+5-6-7
...
1-2-3-4-5-6+7
1-2-3-4-5-6-7
If we remove the numbers from above strings/expressions then we'll have:
++++++
+++++-
++++-+
++++--
...
----+-
-----+
------
Which reminds on binary numbers; if we interpret + as 0 and - as 1 the above can be mapped to the binary numbers from 000000 to 111111.
For an input n you'll have n-1 operators inbetween, which means the count of all possible combinations will be 2^n-1.
Putting all the above together something like below can be used to print those which sums are zero:
public static void main(String args[]) throws IOException{
permute(7);
}
public static void permute(int n){
int combinations = (int)Math.pow(2, n-1);
for(int i = 0; i < combinations; i++){
String operators =String.format("%"+(n-1)+"s", Integer.toBinaryString(i)).replace(' ', '0');
int totalSum = 1;
StringBuilder sb = new StringBuilder();
for(int x = 0; x< operators.length(); x++){
sb.append(x+1);
if(operators.charAt(x)=='0'){
sb.append("+");
totalSum = totalSum + (x+2);
}
else{
sb.append("-");
totalSum = totalSum-(x+2);
}
}
sb.append(n);
if(totalSum == 0){
System.out.println(sb.toString() + " = " + totalSum);
}
}
}
Note/Example: String.format("%6s", Integer.toBinaryString(13)).replace(' ', '0') will produce a string with length = 6 from the binary representation of 13 with leading zeros, i.e 001101 instead of 1101 so that we get the required length of the operators.
This is an interesting question. It involves more math than programming because only if you discover the math portion then you may implement an efficient algorithm.
However even before getting into the math we must actually understand what exactly the question is. The question can be rephrased as
Given array [1..n], find all possible two groups (2 subarrays) with equal sum.
So the rules;
sum of [1..n] is n*n(+1)/2
If n*(n+1)/2 is odd then there is no solution.
If your target sum is t then you should not iterate further for lower values than Math.ceil((Math.sqrt(8*t+1)-1)/2) (by solving n from n(n+1)/2 = t equation)
Sorry... I know the question requests Java code but I am not fluent in Java so the code below is in JavaScript. It's good though we can see the results. Also please feel free to edit my answer to include a Java version if you would like to transpile.
So here is the code;
function s2z(n){
function group(t,n){ // (t)arget (n)umber
var e = Math.ceil((Math.sqrt(8*t+1)-1)/2), // don't try after (e)nd
r = [], // (r)esult
d; // (d)ifference
while (n >= e){
d = t-n;
r = d ? r.concat(group(d, d < n ? d : n-1).map(s => s.concat(n)))
: [[n]];
n--;
}
return r;
}
var sum = n*(n+1)/2; // get the sum of series [1..n]
return sum & 1 ? "No solution..!" // if target is odd then no solution
: group(sum/2,n);
}
console.log(JSON.stringify(s2z(7)));
So the result should be [[1,6,7],[2,5,7],[3,4,7],[1,2,4,7],[3,5,6],[1,2,5,6],[1,3,4,6],[2,3,4,5]].
what does this mean..? If you look into that carefuly you will notice that
These are all the possible groups summing up to 14 (half of 28 which is the sum of [1..7].
The first group (at index 0) is complemented by the last group (at index length-1) The second is complemented with the second last and so on...
Now that we have the interim results it's up to us how to display them. This is a secondary and trivial concern. My choice is a simple one as follows.
var arr = [[1,6,7],[2,5,7],[3,4,7],[1,2,4,7],[3,5,6],[1,2,5,6],[1,3,4,6],[2,3,4,5]],
res = arr.reduce((r,s,i,a) => r+s.join("+")+"-"+a[a.length-1-i].join("-")+" = 0 \n","");
console.log(res);
Of course you may put the numbers in an order or might stop halfway preventing the second complements taking positive values while the firsts taking negative values.
This algorithm is not hard tested and i might have overlooked some edges but I believe that this should be a very efficient algorithm. I have calculated up to [1..28] in a very reasonable time resulting 2399784 uniques groups to be paired. The memory is only allocated for the constructed result set despite this is a resursive approach.
It is a good question, but first you must have to try to solve it and show us what you tried so we can help you in the solution, this way you will improve more effectively.
However, the below code is a solution I have write before years, I think the code need improvement but it will help..
public static void main(String[] args) {
String plus = " + ", minus = " - ";
Set<String> operations = new HashSet<>();
operations.add("1" + plus);
operations.add("1" + minus);
// n >= 3
int n = 7;
for (int i = 1; i < n - 1; i++) {
Set<String> newOperation = new HashSet<>();
for (String opt : operations) {
if ((i + 2) == n) {
newOperation.add(opt + (i + 1) + plus + n);
newOperation.add(opt + (i + 1) + minus + n);
} else {
newOperation.add(opt + (i + 1) + plus);
newOperation.add(opt + (i + 1) + minus);
}
}
operations.clear();
operations.addAll(newOperation);
}
evalOperations(operations);
}
private static void evalOperations(Set<String> operations) {
// from JDK1.6, you can use the built-in Javascript engine.
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
try {
for (String opt : operations) {
if ((int) engine.eval(opt) == 0) {
System.out.println(opt + " = 0");
}
}
} catch (ScriptException e) {
e.printStackTrace();
}
}
First, the question is the special case of sum to N.
Second, sum a list to N, could be devided to the first element plus sublist and minus sublist.
Third, if there are only one element in the list, check if n equals the element.
Fourth, make recursion.
Here's the scala implementation, try finishing your java version:
def nSum(nums: List[Int], n: Int, seq: String, res: ListBuffer[String]): Unit =
nums match {
case Nil => if (n == 0) res.append(seq)
case head :: tail => {
nSum(tail, n - head, seq + s" + $head", res)
nSum(tail, n + head, seq + s" - $head", res)
}
}
def zeroSum(nums: List[Int]): List[String] = {
val res = ListBuffer[String]()
nSum(nums.tail, -nums.head, s"${nums.head}", res)
res.map(_ + " = 0").toList
}
val expected = List(
"1 + 2 - 3 + 4 - 5 - 6 + 7 = 0",
"1 + 2 - 3 - 4 + 5 + 6 - 7 = 0",
"1 - 2 + 3 + 4 - 5 + 6 - 7 = 0",
"1 - 2 - 3 - 4 - 5 + 6 + 7 = 0")
assert(expected == zeroSum((1 to 7).toList))