Finding the sum of numbers in an array - excluding the number 13 and the number directly after it


Finding the sum of numbers in an array - excluding the number 13 and the number directly after it



I would like to write a program in Java which, given an array, finds the sum of all the numbers in the array - with an exception! Since the number 13 is very unlucky, I propose that we shall completely exclude the number 13, and the number directly after 13, if it exists, from the total sum.



The program, which I shall call sum13 , should produce the following results from the following inputs (these are just a few examples):


sum13



sum13([1,2,2,1]) = 6 This one is normal; no 13's here.


sum13([1,2,2,1]) = 6



sum13([5, 13, 2]) = 5 The 13 and the number directly after the 13 are excluded.


sum13([5, 13, 2]) = 5



sum13([13, 13]) = 0 The array contains only 13's, so neither of them are included.


sum13([13, 13]) = 0



sum13([1, 2, 13, 2, 1, 13]) = 4 A slightly longer example of the expected output.


sum13([1, 2, 13, 2, 1, 13]) = 4



Here is the code which I came up with for sum13 :


sum13


public int sum13(int nums) {
int sum = 0;
for (int i = 0; i < nums.length; i++) {
// we start by adding all the non-13s to the sum
if (nums[i] != 13) sum += nums[i];
}
// now we go back and remove all the non-13s directly after a 13
for (int j = 0; j < nums.length; j++) {
// the outermost loop checks if the numbers are a 13
if (nums[j] == 13 && j < nums.length - 1) {
for (int k = j + 1; k < nums.length; k++) {
// this loop checks that the number after the 13 is not a 13
if (nums[k] != 13) {
sum -= nums[k];
break;
}

}
}
}
return sum;
}



The program above works, although it does look quite messy!



Is there a better way of writing such a program that doesn't include multiple loops and nested ifs?


if





Just to clarify the semantics: An if statement is not a loop but just a conditional statement. You therefor do not have 4 nested loops in the code you posted above.
– OH GOD SPIDERS
2 days ago





I see. Could you rewrite that question for me? I don't know how to express it any clearer than that unfortunately :P
– NextTimeDW
2 days ago




5 Answers
5



Well, you use i as iterator. just make i++ when the current number is 13. This way, not only you don't add 13 to the sum but you also skip the next value.


i++


public int sum13(int nums) {
int sum = 0;
for (int i = 0; i < nums.length; i++) {
// we start by adding all the non-13s to the sum
if (nums[i] != 13){
sum += nums[i];
}
else {
i++;
}
}
return sum;
}





So am I right to understand that since you incremented the i in the else loop, will it be incremented again in the for loop? That is to say, when we come across a 13, will i be incremented twice?
– NextTimeDW
2 days ago


i


else


for


i





@NextTimeDW yes: in your example, 1, 2, 13, 2, 1, 13, when i = 2, nums[i] will be 13. We then enter in the else case, i become 3. end of the current loop, we increment i that become 4: we have skip the 2 that is directly after the 13
– Kepotx
2 days ago





@NextTimeDW - Yes. (But it's an "else block", not "else loop". A loop is something that repeats [loops]. for and while and do...while are loops. if and else and switch are not.)
– T.J. Crowder
2 days ago


else


else


for


while


do...while


if


else


switch





@NextTimeDW - The only reason I pointed it out was that you're clearly a beginner, and clearly someone who will improve. :-) (Sadly, not all beginners will improve.) Happy coding!
– T.J. Crowder
2 days ago






@NextTimeDW don't worry, it was clear enough anyway. We can understand that you make some mistake, after all StackOverflow is also here to learn.
– Kepotx
2 days ago



Kepotx shows how to do it with a traditional for loop. You can also do it with a flag in an enhanced for loop:


for


for


public int sum13(int nums) {
int sum = 0;
boolean skipNext = false;
for (int num : nums) {
if (num == 13) {
skipNext = true;
} else {
if (!skipNext) {
sum += num;
}
skipNext = false;
}
}
return sum;
}



Live Example with the provided inputs and expected outputs.



Hopefully someone savvy with streams shows us the clever streams approach... :-) ...and Malte Hartwig did (although as he says, there's a not-best-practice in there).





This is also a nice solution! For me at least, it's a little harder to follow than Kepotx's solution, but always good to know that there are multiple ways to do the same thing :)
– NextTimeDW
2 days ago





@TJ just added a stream based answer just for the fun of it, just in case you're still interested ;)
– Malte Hartwig
2 days ago



Using an AtomicBoolean can shorten to loop considerably, and it gets even shorter when you use IntStream to sum:


AtomicBoolean


IntStream


public static int sum13(int numbers)
{
AtomicBoolean was13 = new AtomicBoolean(false);
return IntStream.of(numbers)
.filter(i -> !was13.getAndSet(i == 13) && i != 13)
.sum();
}



The big advantage is that AtomicBoolean.getAndSet(boolean) allows us to check whether the previous number was 13 and store whether the current number is 13 the same time.


AtomicBoolean.getAndSet(boolean)



Warning: As Hulk pointed out in the comment, is not the best practice to change the state of objects "outside" the stream. This can come back to haunt you if you try to use the stream in parallel, for example. It is possible to avoid using outside state here using a custom Collector, but this would make the code way too complicated for this particular problem.


Collector





Probably really the best you can do using streams - but as this question is from a beginner, it might be wise to include a warning that stateful predicates should usually be avoided.
– Hulk
2 days ago





@Hulk thanks for pointing that out. I added a warning. I thought about adding a non-stream version as well, but it will get longer, so I don't think the increased difficulty (AtomicBoolean.getAndSet...) is worth the slightly shorter code then.
– Malte Hartwig
2 days ago



As soon as number 13 arrives you need to skip the 13 and next char in the loop


public class HelloWorld{

public static void main(String args){
int arr = {1, 2, 4, 2, 1, 13,10};
System.out.println(sum13(arr));
}

public static int sum13(int nums) {
int sum = 0;
int n = nums.length;
for (int i = 0; i < n; i++) {
if (nums[i] == 13){
i=i+2;
}

if(i<n){
sum += nums[i];
}

}
return sum;
}



}





This is unnecessarily complicated. Kepotx already showed how to do this by manipulating the loop index.
– T.J. Crowder
2 days ago





it will work as the sum is calculated after increasing it by 2.
– Ashu
2 days ago



Why not using ArrayList class? It has iterator() method implemented and the code could look like this:


int sum13 (ArrayList<Integer> a) {
Iterator<Integer> iter = a.iterator();
int n;
int sum=0;
while (iter.hasNext() ) {
n = iter.next();
if (n !=13)
sum = sum + n; /* n!=13 it will be added*/
else if (iter.hasNext() )
iter.next() /* n==13 not summing and skipping next */
}
return sum;
}





The method signature has already been given and cannot be altered. Sorry about that.
– NextTimeDW
2 days ago






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

how to run turtle graphics in Colaboratory

Export result set on Dbeaver to CSV