0

I would like to write a program which adds up all the numbers in an integer array - with an exception! Since the number 6 isn't the nicest, I propose that we exclude all sections of numbers beginning with a 6 and ending with a 7 - inclusive. Every 6 will always be followed by a 7, but not necessarily vice versa.

Here are a few examples of the input arrays and their expected output:

sum67([1, 2, 2, 6, 99, 99, 7]) = 5 All numbers between a 6 and a 7 are excluded.

sum67([1, 2, 2]) = 5 No 6's or 7's here.

sum67([1, 1, 6, 7, 2]) → 4 Neither the 6 or the 7 is included.

All the above tests passed.

Once again, the method header is fixed, and I may only change the body of the method. Here is my attempt at the code:

public int sum67(int[] nums) {
  int sum = 0;
  for (int i = 0; i < nums.length; i++) {
    // Adding all numbers that are not a 6
    if (nums[i] != 6) sum += nums[i];
  }
  for (int j = 0; j < nums.length; j++) {
    // check for the sixes - the lower bound exclusive
    if (nums[j] == 6) {
      for (int k = j + 1; k < nums.length; k++) {
        // check for the sevens - the upper bound inclusive
        if (nums[k] == 7) {
          // take away all the numbers between the 2 bounds, including the 7
          for (int m = j + 1; m <= k; m++) {
            sum -= nums[m];
          }
        }
      }
    }
  }
  return sum;
}

The above program not only does not work, but is clearly extremely messy. In particular, it fails the following tests, among others:

sum67([1, 6, 2, 6, 2, 7, 1, 6, 99, 99, 7]) = 2 Actual output is -463!

sum67([2, 2, 6, 7, 7]) = 11 Actual output is -3.

So essentially:

Where is the error line or lines in my code?

Is there a better way of writing this program that doesn't have as many loops and nested ifs?

AnagramDatagram
  • 329
  • 1
  • 2
  • 14

2 Answers2

2
public int sum67(int[] arr) {
    int sum = 0;
    boolean isIn67 = false;
    for (int i = 0 ; i < arr.length ; i++) {
        if (arr[i] == 6) {
            isIn67 = true;
            continue;
        } else if (arr[i] == 7 && isIn67) {
            isIn67 = false;
            continue;
        }
        if (!isIn67) {
            sum += arr[i];
        }
    }
    return sum;
}

The above is my attempt. Explanation:

  • Only one loop is needed to loop through all the elements. In each iteration, some if statements are used to determine whether that element should be added to the sum.
  • There is a variable called isIn67 that indicates whether arr[i] is inside a 6-7 range and so shouldn't be added to the sum
  • When we encounter a 6, we set isIn67 to true.
  • When we encounter a 7 and isIn67 is true, we set isIn67 to false.
  • continue is used so that we don't count those 7s
  • And finally, if we are not in67, we add the element to the sum.

The problem with your code is probably that you are nesting too much. The line to subtract the unwanted numbers is nested in the outer loop so it might get executed for many more times than expected, making the results negative.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • I upvoted, but it would be nice to note that this only works because it's assumed that every 6 will always be followed by a 7. If 1236345 was a valid sequence, for example, it wouldn't work anymore. – JB Nizet Jun 30 '18 at 08:59
  • @JBNizet Didn't the OP said in the question that 6 will always be followed by a 7? It's in bold as well. – Sweeper Jun 30 '18 at 09:03
  • Thanks Sweeper! Might I ask, as a newbie coder, how does the `continue` statement work? – AnagramDatagram Jun 30 '18 at 09:03
  • And @JBNizet yes, every 6 is guaranteed to be followed by a 7. – AnagramDatagram Jun 30 '18 at 09:04
  • @NextTimeDW It makes the loop go to the next iteration without executing the rest of the current iteration. – Sweeper Jun 30 '18 at 09:04
  • @Sweeper he/she did, and that's why I upvoted, and said in my comment: "it's assumed that every 6 will always be followed by a 7". But future readers might miss that fact. – JB Nizet Jun 30 '18 at 09:04
  • For future readers: an straightforward way to handle the case where 7 might not exist in an array with 6s, you can check if a 7 exists before looping through the array. If it does not then set a flag. Before setting `isIn67` to true, you just check the flag. – Sweeper Jun 30 '18 at 09:07
  • @NextTimeDW See this question as well: https://stackoverflow.com/questions/389741/what-is-the-continue-keyword-and-how-does-it-work-in-java – Sweeper Jun 30 '18 at 09:07
1

The logic you are using is not representative of what you want to do. Take your first example, and consider the second loop (so you have summed up everything)

  1. Iterate until you see a 6
  2. Now iterate until you see the first 7, and subtract everything in between including the last 7 (<= - this is the reason for the -3 in the second example)
  3. Now go on and do this again for the next 7 - you are double subtracting everything between the first 6 and the first 7!
  4. Continue to next 6 - and do the same - you again will subtract stuff you subtracted before.

I suggest following your code with pen and paper to see how it works. A simpler solution is to do exactly what you want:

int sum = 0;
boolean noLikey = false;
for (int i = 0; i < nums.length; i++) {
    if (! noLikey && nums[i] == 6 ) noLikey = true;
    if ( noLikey ) {
        if ( nums[i] == 7 ) noLikey = false;
        continue;
    }
    sum += nums[i];
}

This of course assumes a 6 is always followed by a 7.

kabanus
  • 24,623
  • 6
  • 41
  • 74
  • Thanks @kabanus! Would it be possible to salvage my code in any way by inserting a `break` statement anywhere? Also, where should I put the code snippet you provided? – AnagramDatagram Jun 30 '18 at 09:09
  • @NextTimeDW Inside `sum67`. As for your code, you would need to break twice, and use conditionals. If you want to rewrite it yourself (which I recommend), I suggest starting from scratch, and trying to really follow the logic of your though with code (which is I realize is the whole art of programming). – kabanus Jun 30 '18 at 09:11