12

I managed to solve this, below is my solution :

public class ProblemA001k {

public static void main(String[] args) {



        System.out.println("Sum from 1" + " to " + divQ + ":" + sum2);
        System.out.println();
        divQ += q;
        newQ += q;
        sum1 = 0;
        sum2 = 0;
        }

key.close();
}

}

Now I was told to modify my solution so that it uses ONLY ONE LOOP. I have 3 loops in the code above, even when I tried using only 2 loops I struggled. but ONE LOOP ? I don't know how to improve my code. Please help me.

4 Answers4

11

This is a Mathematic problem.

If you know that you can find the sum of all integers from 1 to X, you just need to do X * (X+1) / 2.

You can find all the batch values easily.

Sum from 1 to 400: 80200
Sum from 401 to 450: 21275
Sum from 1 to 450: 101475

Will be found like this :

450 * 451 / 2 = 101475 (1 to 450)
400 * 401 / 2 = 80200  (1 to 400)
101475 - 80200 = 21275 (401 to 450)

With this, you can limit the loop to just calculate the values from q to n by incrementing by q

And a quick code to do it :

static void sum(int n, int q){
    int i = q;
    int sum, tmp=0;
    while(i < n){
        sum = i * (i+1) / 2;
        System.out.println(String.format("Sum from %d to %d : %d", i-q+1 , i, sum - tmp));
        System.out.println(String.format("Sum from %d to %d : %d", 1, i, sum));
        tmp = sum;
        i += q;
    }
}

And I run it with

public static void main(String[] args){
    sum(500, 50);
}

to have this result

Sum from 1 to 50 : 1275
Sum from 1 to 50 : 1275
Sum from 51 to 100 : 3775
Sum from 1 to 100 : 5050
Sum from 101 to 150 : 6275
Sum from 1 to 150 : 11325
Sum from 151 to 200 : 8775
Sum from 1 to 200 : 20100
Sum from 201 to 250 : 11275
Sum from 1 to 250 : 31375
Sum from 251 to 300 : 13775
Sum from 1 to 300 : 45150
Sum from 301 to 350 : 16275
Sum from 1 to 350 : 61425
Sum from 351 to 400 : 18775
Sum from 1 to 400 : 80200
Sum from 401 to 450 : 21275
Sum from 1 to 450 : 101475

The good think with this solution is the number of loop, this will increment by q instead of 1

Note : The solution is a quick implementation, this could be done better.

EDIT :

Thanks to Margaret Bloom in the comments to point out the name of this formula :) For more information, you are welcome to look at Triangular Number

AxelH
  • 14,325
  • 2
  • 25
  • 55
  • AleIH could you please use one loop ? , I am forced to use ONE loop. – Nkosie Maphumulo Nov 11 '16 at 08:02
  • @NkosieMaphumulo here it is – AxelH Nov 11 '16 at 08:30
  • 1
    While correct and professional I don't think this is the right solution for the OP. IMO the exercise is meant to teach loops and reasoning about variables management. If that's true, this answer totally misses the point. – Margaret Bloom Nov 11 '16 at 10:28
  • @MargaretBloom, using one loop like the OP ask and for the variable management, using a temp variable to store the previous sum is effective. Algorithm should be think to be effecient, so why is it bad ? I was asked a while back to print the date for an epoch value (without Date instance ;) ). This was done in -10lines with simple Math (modulo and division to find each steps) most of the student do it with huge code using loop and switch. The teacher was glad to find the logic. – AxelH Nov 11 '16 at 10:35
  • I agree with you, I'm not criticising your answer at all :) But as a teacher I would ask the student to perform the task again without exploiting the properties of triangular numbers. I'd want them to master loops, possible without having me thinking too hard to find an exercise that cannot be simplified by basic math :) – Margaret Bloom Nov 11 '16 at 10:53
  • @MargaretBloom, I don't see any critics here :) But what would you not found in this solution use triangular number that you could find in a simple iterative loop (this could be done with a for loop if you prefer ;) ) There is a loop to go through the range of numbers (not all) two variables to store result in time. This would be a correct way to test the knowledge of loop usage for me. – AxelH Nov 11 '16 at 10:57
  • @MargaretBloom: If the exercise is meant to teach loops, then the exercise misses the point. Obviously, you need simplified examples for the purpose of teaching. But a simplified example that doesn't have the property you are teaching? That's just bad teaching. This example simply doesn't require a loop. Like, at all. A fold, maybe. But really, not even that. (Honestly, I can't remember the last time I encountered a problem that required a loop. I write lots of maps and folds and filters and scans, and some tail-recursion. Loops, not so much.) – Jörg W Mittag Nov 11 '16 at 11:34
  • @JörgWMittag Aren't folds and maps just loops already cooked for you? Anyway, I didn't want to make a big deal, just my two cents. – Margaret Bloom Nov 11 '16 at 11:42
6

This should do it:

int totalSum = 0;
int batchSum = 0;

for (int i = 1; i <= n; i++) {
    totalSum += i;
    batchSum += i;
    if (i % q == 0) {
        System.out.println("Sum from " + (i - q + 1) + " to " + i + ":" + batchSum);
        System.out.println("Sum from 1 to " + i + ":" + totalSum);
        batchSum = 0;
    }

}

Edit: The better Math way:

int lastTotalSum = 0;
for (int i = 1; i <= n / q; i++ ) {
    int top = i * q;
    int totalSum = top * (top + 1) / 2;
    int batchSum = totalSum - lastTotalSum;
    System.out.println("Sum from " + (top - q + 1) + " to " + top + ":" + batchSum);
    System.out.println("Sum from 1 to " + top + ":" + totalSum);
    lastTotalSum = totalSum;

}
Bijay Gurung
  • 1,094
  • 8
  • 12
  • Thank You. :) Appreciate it. – Nkosie Maphumulo Nov 11 '16 at 08:17
  • Pleasure. Hope it's understandable. – Bijay Gurung Nov 11 '16 at 08:18
  • 1
    Shouldn't it be top+1 instead of top - 1? – MikeMB Nov 11 '16 at 08:22
  • @AxelH It wasn't your solution. It's just a mathematical formula. Granted, I realized it could be solved this way after seeing your answer. But, didn't know you were planning to put up an implementation too. So, I went ahead and did it myself to help the OP. There wasn't a need to downvote. In any case, I have removed it as you were technically the first to point out the Math method. Do use a running total (lastTotalSum) though. – Bijay Gurung Nov 11 '16 at 08:45
  • @AxelH I rolled back the changes as it doesn't feel right to keep such an inefficient method up. Nkosie, Please accept AxelH's answer. That would be the right thing to do. – Bijay Gurung Nov 11 '16 at 08:55
  • Having tutored a lot of high-school students, I believe the **first algorithm** is what the teacher wanted. While triangular numbers have a simple formula, using that would completely defeat the purpose of the exercise: thinking in terms of loops. – Margaret Bloom Nov 11 '16 at 10:24
  • @Margaret Hmm... Ya, likely to be so. Thinking in loop can be tricky in the beginning. And this is a good exercise. – Bijay Gurung Nov 11 '16 at 14:00
2

I found a nice solution with java8 Streams:

int n=1000;
int q=50;
int length = n/q -1;        
int[] previousSum={0};
IntStream.range(0, length).map(i -> (i+1)*q).forEach(s -> {
    int sum=(s*(s+1))/2;
    int batch = sum - previousSum[0];
    previousSum[0] = sum;
    System.out.println("Sum from " + (s - q + 1) + " to " + s + ":" + batch); 
    System.out.println("Sum from 1 to " + s + ":" + sum);
});
user6904265
  • 1,938
  • 1
  • 16
  • 21
  • 2
    Original idea ! Well you have a lot of loops here (hidden in Arrays.stream). If you could do this in one stream this would be much better :) still 2 loops (3 if you print like this). – AxelH Nov 11 '16 at 15:11
  • Yes, even if it's not a single loop as requested by OP, I wanted to post it anyway because it is a nice solution I think. Thank you for pointing this out. – user6904265 Nov 11 '16 at 16:52
  • I had time to work on the "only one loop" solution with java8 Streams, is this solution nice? :) – user6904265 Nov 12 '16 at 12:56
  • Really true, streams solution requires 2 loops at least as you said in the previous comment. I used an array because if I declare a simple `int` variable I get a compilation error, this problem has been already faced [here](http://stackoverflow.com/questions/32521972/in-java8-how-to-set-the-global-value-in-the-lambdas-foreach-block). Anyway, a declarative approach doesn't fit here and then also java8 Streams. A procedural approach (like your solution) is more appropriate for this kind of problems. – user6904265 Nov 14 '16 at 19:15
0

Do one loop iterating entire range and use indexes to decide whether to add, reset or print your sums.

Hope this gives your right idea, if you still dont know I can illustrate it a bit more.

Mats391
  • 1,199
  • 7
  • 12