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 if
s?
if
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.
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