I was going through a simple program that takes a number and finds the number of occurrences of consecutive numbers that matches with given number.
For example:
if input is 15, then the consecutive numbers that sum upto 15 are:
1,2,3,4,5
4,5,6
7,8
So the answer is 3 as we have 3 possibilities here.
When I was looking for a solution I found out below answer:
static long process(long input) {
long count = 0;
for (long j = 2; j < input/ 2; j++) {
long temp = (j * (j + 1)) / 2;
if (temp > input) {
break;
}
if ((input- temp) % j == 0) {
count++;
}
}
return count;
}
I am not able to understand how this solves the requirement because this program is using some formula which I am not able to understand properly, below are my doubts:
The for loop starts from 2, what is the reason for this?
long temp = (j * (j + 1)) / 2; What does this logic indicates? How is this helpful to solving the problem?
if ((num - temp) % j == 0) Also what does this indicate?
Please help me in understanding this solution.
I will try to explain this as simple as possible.
If input is 15, then the consecutive numbers that sum upto 15 are:
{1,2,3,4,5} -> 5 numbers
{4,5,6} -> 3 numbers
{7,8} -> 2 numbers
At worst case, this must be less than the Sum of 1st n natural numbers = (n*(n+1) /2.
So for a number 15, there can never be a combination of 6 consecutive numbers summing up to 15 as the sum of 1st 6 numbers =21 which is greater than 15.
Calculate temp: This is (j*(j+1))/2.
Take an example. Let input = 15. Let j =2.
temp = 2*3/2 = 3; #Meaning 1+2 =3
For a 2-number pair, let the 2 terms be 'a+1' and 'a+2'.(Because we know that the numbers are consecutive.)
Now, according to the question, the sum must add up to the number.
This means 2a+3 =15;
And if (15-3) is divisible by 2, 'a' can be found. a=6 -> a+1=7 and a+2=8
Similarly, let a+1 ,a+2 and a+3
a + 1 + a + 2 + a + 3 = 15
3a + 6 = 15
(15-6) must be divisible by 3.
Finally, for 5 consecutive numbers a+1,a+2,a+3,a+4,a+5 , we have
5a + 15 = 15;
(15-15) must be divisible by 5.
So, the count will be changed for j =2,3 and 5 when the input is 15
If the loop were to start from 1, then we would be counting 1 number set too -> {15} which is not needed
To summarize:
1) The for loop starts from 2, what is the reason for this?
We are not worried about 1-number set here.
2) long temp = (j * (j + 1)) / 2; What does this logic indicates? How is this helpful to solving the problem?
This is because of the sum of 1st n natural numbers property as I have
explained the above by taking a+1 and a+2 as 2 consecutive
numbers.
3) if ((num - temp) % j == 0) Also what does this indicate?
This indicates the logic that the input subtracted from the sum of 1st
j natural numbers must be divisible by j.
We need to find all as and ns, that for given b the following is true:
a + (a + 1) + (a + 2) + ... (a + (n - 1)) = b
The left side is an arithmetic progression and can be written as:
(a + (n - 1) / 2) * n = b (*)
To find the limit value of n, we know, that a > 0, so:
(1 + (n - 1) / 2) * n = n(n + 1) / 2 <= b
n(n + 1) <= 2b
n^2 + n + 1/4 <= 2b + 1/4
(n + 1/2)^2 <= 2b + 1/4
n <= sqrt(2b + 1/4) - 1/2
Now we can rewrite (*) to get formula for a:
a = b / n - (n - 1) / 2
Example for b = 15 and n = 3:
15 / 3 - (3 - 1) / 2 = 4 => 4 + 5 + 6 = 15
And now the code:
double b = 15;
for (double n = 2; n <= Math.ceil(Math.sqrt(2 * b + .25) - .5); n++) {
double candidate = b / n - (n - 1) / 2;
if (candidate == (int) candidate) {
System.out.println("" + candidate + IntStream.range(1, (int) n).mapToObj(i -> " + " + (candidate + i)).reduce((s1, s2) -> s1 + s2).get() + " = " + b);
}
}
The result is:
7.0 + 8.0 = 15.0
4.0 + 5.0 + 6.0 = 15.0
1.0 + 2.0 + 3.0 + 4.0 + 5.0 = 15.0
We are looking for consecutive numbers that sum up to the given number.
It's quite obvious that there could be at most one series with a given length, so basically we are looking for those values witch could be the length of such a series.
variable 'j' is the tested length. It starts from 2 because the series must be at least 2 long.
variable 'temp' is the sum of a arithmetic progression from 1 to 'j'.
If there is a proper series then let X the first element. In this case 'input' = j*(X-1) + temp.
(So if temp> input then we finished)
At the last line it checks if there is an integer solution of the equation. If there is, then increase the counter, because there is a series with j element which is a solution.
Actually the solution is wrong, because it won't find solution if input = 3. (It will terminate immediately.) the cycle should be:
for(long j=2;;j++)
The other condition terminates the cycle faster anyway.
NB: loop is starting from 2 because=> (1*(1+1))/2 == 1, which doesn't make sense, i.e, it doesn't effect on the progress;
let, k = 21;
so loop will iterate upto (k/2) => 10 times;
temp = (j*(j+1))/2 => which is, 3 when j =2, 6 when j = 3, and so on (it calculates sum of N natural numbers)
temp > k => will break the loop because, we don't need to iterate the loop when we got 'sum' which is more than 'K'
((k-temp)%j) == 0 => it is basically true when the input subtracted from the sum of first j natural numbers are be divisible by j, if so then increment the count to get total numbers of such equation!
public static long process(long input) {
long count = 0, rest_of_sum;
for (long length = 2; length < input / 2; length++) {
long partial_sum = (length * (length + 1)) / 2;
if (partial_sum > input) {
break;
}
rest_of_sum = input - partial_sum
if (rest_of_sum % length == 0)
count++;
}
return count;
}
input - given input number here it is 15
length - consecutive numbers length this is at-least 2 at max input/2
partial_sum = sum of numbers from 1 to length (which is a*(a+1)/2 for 1 to a numbers) assume this is a partial sequence
rest_of_sum = indicates the balance left in input
if rest of sum is multiple of length meaning is that we can add (rest_of_sum/length) to our partial sequence
lets call (rest_of_sum/length) as k
this only means we can build a sequence here that sums up to our input number
starting with (k+1) , (k+2), ... (k+length)
this can validated now
(k+1) + (k+2) + ... (k+length)
we can reduce this as k+k+k+.. length times + (1+2+3..length)
can be reduced as => k* length + partial_sum
can be reduced as => input (since we verified this now)
So idea here is to increment count every-time we find a length which satisfies this case here
If you put this tweak in it may fix code. I have not extensively tested it. It's an odd one but it puts the code through an extra iteration to fix the early miscalculations. Even 1/20000 would work! Had this been done with floats that got rounded down and 1 added to them I think that would have worked too:
for (long j = 2; j < input+ (1/2); j++) {
In essence you need to only know one formula:
The sum of the numbers m..n (or m to n) (and where n>m in code)
This is ((n-m+1)*(n+m))/2
As I have commented already the code in the original question was bugged.
See here.
Trying feeding it 3. That has 1 occurrence of the consecutive numbers 1,2. It yields 0.
Or 5. That has 2,3 - should yield 1 too - gives 0.
Or 6. This has 1,2,3 - should yield 1 too - gives 0.
In your original code, temp or (j * (j + 1)) / 2 represented the sum of the numbers 1 to j.
1 2 3 4 5
5 4 3 2 1
=======
6 6 6 6 6 => (5 x 6) /2 => 30/2 => 15
As I have shown in the code below - use System.out.println(); to spew out debugging info.
If you want to perfect it make sure m and n's upper limits are half i, and i+1 respectively, rounding down if odd. e.g: (i=15 -> m=7 & n=8)
The code:
class Playground {
private static class CountRes {
String ranges;
long count;
CountRes(String ranges, long count) {
this.ranges = ranges;
this.count = count;
}
String getRanges() {
return this.ranges;
}
long getCount() {
return this.count;
}
}
static long sumMtoN(long m, long n) {
return ((n-m+1)* (n+m))/2;
}
static Playground.CountRes countConsecutiveSums(long i, boolean d) {
long count = 0;
StringBuilder res = new StringBuilder("[");
for (long m = 1; m< 10; m++) {
for (long n = m+1; n<=10; n++) {
long r = Playground.sumMtoN(m,n);
if (d) {
System.out.println(String.format("%d..%d %d",m,n, r));
}
if (i == r) {
count++;
StringBuilder s = new StringBuilder(String.format("[%d..%d], ",m,n));
res.append(s);
}
}
}
if (res.length() > 2) {
res = new StringBuilder(res.substring(0,res.length()-2));
}
res.append("]");
return new CountRes(res.toString(), count);
}
public static void main(String[ ] args) {
Playground.CountRes o = countConsecutiveSums(3, true);
for (long i=3; i<=15; i++) {
o = Playground.countConsecutiveSums(i,false);
System.out.println(String.format("i: %d Count: %d Instances: %s", i, o.getCount(), o.getRanges()));
}
}
}
You can try running it here
The output:
1..2 3
1..3 6
1..4 10
1..5 15
1..6 21
1..7 28
1..8 36
1..9 45
1..10 55
2..3 5
2..4 9
2..5 14
2..6 20
2..7 27
2..8 35
2..9 44
2..10 54
3..4 7
3..5 12
3..6 18
3..7 25
3..8 33
3..9 42
3..10 52
4..5 9
4..6 15
4..7 22
4..8 30
4..9 39
4..10 49
5..6 11
5..7 18
5..8 26
5..9 35
5..10 45
6..7 13
6..8 21
6..9 30
6..10 40
7..8 15
7..9 24
7..10 34
8..9 17
8..10 27
9..10 19
i: 3 Count: 1 Instances: [[1..2]]
i: 4 Count: 0 Instances: []
i: 5 Count: 1 Instances: [[2..3]]
i: 6 Count: 1 Instances: [[1..3]]
i: 7 Count: 1 Instances: [[3..4]]
i: 8 Count: 0 Instances: []
i: 9 Count: 2 Instances: [[2..4], [4..5]]
i: 10 Count: 1 Instances: [[1..4]]
i: 11 Count: 1 Instances: [[5..6]]
i: 12 Count: 1 Instances: [[3..5]]
i: 13 Count: 1 Instances: [[6..7]]
i: 14 Count: 1 Instances: [[2..5]]
i: 15 Count: 3 Instances: [[1..5], [4..6], [7..8]]
This question already has answers here:
Understanding The Modulus Operator %
(10 answers)
Closed 5 years ago.
I ran into some code containing the % symbol inside the array argument.
What does it mean and how does it work?
Example:
String[] name = { "a", "b", "c", "d" };
System.out.println(name[4 % name.length]);
System.out.println(name[7 % name.length]);
System.out.println(name[50 % name.length]);
Output:
a
d
c
That's the remainder operator, it gives the remainder of integer division. For instance, 3 % 2 is 1 because the remainder of 3 / 2 is 1.
It's being used there to keep a value in range: If name.length is less than 4, 7, or 50, the result of % name.length on those values is a value that's in the range 0 to name.length - 1.
So that code picks entries from the array reliably, even when the numbers (4, 7, or 50) are out of range. 4 % 4 is 0, 7 % 4 is 3, 50 % 4 is 2. All of those are valid array indexes for name.
Complete example (live copy):
class Example
{
public static void main (String[] args) throws java.lang.Exception
{
String[] name = { "a" , "b" , "c" , "d"};
int n;
n = 4 % name.length;
System.out.println(" 4 % 4 is " + n + ": " + name[n]);
n = 7 % name.length;
System.out.println(" 7 % 4 is " + n + ": " + name[n]);
n = 50 % name.length;
System.out.println("50 % 4 is " + n + ": " + name[n]);
}
}
Output:
4 % 4 is 0: a
7 % 4 is 3: d
50 % 4 is 2: c
Simple: this is the modulo, or to be precise the remainder operator.
This has nothing to do with arrays per se. It is just a numerical computation on the value that gets used to compute the array index.
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 8 years ago.
Improve this question
I don't understand how the results are calculated
int halfDollar = remainingAmount / 50;
remainingAmount = remainingAmount % 50;
int numberOfQuarters = remainingAmount / 25;
remainingAmount = remainingAmount % 25;
ETC.....
import java.util.Scanner;
public class Program3
{
public static void main(String [] args)
{
Scanner kbd = new Scanner(System.in);
System.out.print("Please enter the total dollar amount in the piggy bank: $");
double amount = kbd.nextDouble();
int remainingAmount = (int)(amount * 100);
int halfDollar = remainingAmount / 50;
remainingAmount = remainingAmount % 50;
int numberOfQuarters = remainingAmount / 25;
remainingAmount = remainingAmount % 25;
int numberOfDimes = remainingAmount / 10;
remainingAmount = remainingAmount % 10;
int numberOfNickels = remainingAmount / 5;
remainingAmount = remainingAmount % 5;
int numberOfPennies = remainingAmount;
System.out.println(String.format("In $" + "%.2f", amount) + " worth of pennies there are:");
System.out.println(halfDollar + " half dollar(s), " + numberOfQuarters + " quarter(s), " + numberOfDimes + " dime(s), " + numberOfNickels + " nickle(s), and " + numberOfPennies + " cent(s).");
}
}
It's simple, you multiple the number of dollars by 100 and you get the number of cents, then you calculate how many nickels, dimes etc that would be.
For example, $5.26 is 526 cents, which is 10 half dollars ($5), 1 quarter, 1 penny.
Integer division gives you the number of times X is contained in Y, and modulus (%) gives you the remainder.
526 / 50 = 10
526 % 50 = 26
26 / 25 = 1
26 % 25 = 1
1 / 10 = 0
1 % 10 = 1
1 / 5 = 0
1 % 5 = 1
1 / 1 = 1
1 % 1 = 0
Obviously, what that does is break the amount of money in the least number of coins by giving you as many coins of the highest denomination first, then the highest number of coins of the next denomination etc.
For avoiding fractions you multiply value with 100. Making calculations with fractions is a little bit difficult.
For example instead of making calculations with $1.25 programmers prefer to make calculations 125. It makes to easy understanding.
If you divide(/) X to Y you find the number of Y that X contains.
If you take mod(%) X of Y you find the remainder of X divided by Y
Think that $1.43 entered.
1.43 * 100 = 143
143 / 50 = 2 -> Half dollar
143 % 50 = 43 -> remainder of division
43 / 25 = 1 -> Quarter
43 % 25 = 18 -> remainder of division
18 / 10 = 1 -> Dimes
18 % 10 = 8 -> remainder of division
8 / 5 = 1 -> Nickels
8 % 5 = 3 -> remainder of division
There is no more division last remainder is pennies and it is 3
The / operator when applied to ints provides integer division. That is: division where the fractional part is thrown away.
For example: 10 / 3 gives 3.
Since:
10 divided by 3 is 3.3333333 recurring.
Throwing away the fractional part (0.3333333 recurring) gives the result 3.
The % operator provides modulus or the remainder of integer division. That is: the numerator minus the greatest multiple of the denominator that is less than the numerator.
For example: 10 % 3 gives 1.
Since:
the numerator is 10
the denominator is 3
The result of the integer division 10 / 3 is 3 (as we worked out above)
The greatest multiple of the denominator (3) that is less than the numerator (10) is 3, since 3 * 3 is 9 and no multiple of 3 is greater than 9 but less than 10.
Subtracting that (9) from the numerator (10) you get 10 - 9 which is the result 1.
An easier way to understand this is that integer / is division of whole things that can't be split. So you might want to divide 10 marbles (which you don't want to split into pieces) evenly between 3 people. Then each person gets 3 marbles, but there is 1 marble left over.
Note: that the greatest multiple of the denominator is exactly the result of the integer division (3 in this case, as in 10 / 3 is 3)
Note: You could also work this out by multiplying the fractional part by the result of the integer division (which we worked out was 10 / 3 =3). Giving 0.33333... * 3 which is the result 1.
I need your help guys with this specific question.
How many numbers from an interval a <= b [1, 10^18] are dividable by 2, 3 or 5?
Result must be run in max 1 sec!
A standard program would use a for loop seen bellow.
a = 1;
b = 1000000000
results = 0;
for (int i = a; i <= b; i++){
if (i % 2 == 0 || i % 3 == 0, i % 5 == 0){
results++;
}
}
System.out.println(results);
But if I enter high numbers, my program need a lot of time to give me the results.
Example 1:
a = 11, b = 30, result = 14
Example 2:
a = 123456789012345678, b = 876543210987654321
, result = 552263376115226339
I came up with something like that
public static void main(String[] args) {
long a = 123456789012345678L, b = 876543210987654321L;
long start = System.currentTimeMillis();
long score = getCount(b) - getCount(a - 1);
System.out.println("Time: " + ((System.currentTimeMillis() - start)));
System.out.println("Divisible by 2 or 3 or 5: " + score);
}
public static long getCount(long end) {
return (end / 2) + (end / 3) + (end / 5) - ((end / 6) + (end / 10) + (end / 15)) + (end / 30);
}
The solution:
It counts how many numbers are divisible by 2 or 3 or 5 separately and sums that.
Now we need to discard numbers that where counted twice: for 2 and 3 it will be every 6th number, for 2 and 5 every 10th number, for 3 and 5 every 15th number
At the end we need to include numbers that are divisible by 2 and 3 and 5 that where discarded in step 2 so we add every 30th number.
I have the following variable decelrations, assignments and variable declerations
variable e is an expression statement which should return the value of the evaulated variables in the expression;
What is the order of precdence of the opperators in the e variable?
Computed it equals = 60;
With a calculator I get 422;
int a, b, c, d;
a = 10;
b = 2;
c = 1;
d = 20;
e = a + b * d / c + a + b / d;
e = 10 + 2 * 20 / 1 + 10 + 2 / 20;
e = 60;
Actually the answer is 60.1 but since variables are int its showing 60. It is happening as below
10 + (2 * (20 / 1)) + 10 + (int)(2 / 20) = 10 + (2 * 20) + 10 + (int)0.1
= 10 + 40 + 10 + 0 = 60
Here is a link outlining operator precedence. As for your result, this can also be attributed to integer division (which takes the floor of the result; for instance, 2/20 = 0).
Just like in school, multiplication and division have priority over addition. So you have:
10 + 2 * 20 / 1 + 10 + 2 / 20 = 10 + 40 + 10 + 0 = 60
* takes first precedence so first, 2*20 =40, 10 + 40 / 1 + 10 + 2 / 20;
/ takes precedence so , 10 + 40 + 10 + 0;
+ takes precedence so, 60
Here is link for operator precedence: Operator precedence