0

I am training with the following programming exercise: Adding values of arrays in a shifted way. The statement is the following:

Adding values of arrays in a shifted way

You have to write a method, that gets two parameter:

  1. An array of arrays with int-numbers
  2. The shifting value

The method should add the values of the arrays to one new array.

The arrays in the array will all have the same size and this size will always be greater than 0. The shifting value is always a value from 0 up to the size of the arrays. There are always arrays in the array, so you do not need to check for null or empty.

1. Example:

[[1,2,3,4,5,6], [7,7,7,7,7,-7]], 0

1,2,3,4,5,6 7,7,7,7,7,-7

--> [8,9,10,11,12,-1]

2. Example

[[1,2,3,4,5,6], [7,7,7,7,7,7]], 3

1,2,3,4,5,6 7,7,7,7,7,7

--> [1,2,3,11,12,13,7,7,7]

3. Example

[[1,2,3,4,5,6], [7,7,7,-7,7,7], [1,1,1,1,1,1]], 3

1,2,3,4,5,6 7,7,7,-7,7,7 1,1,1,1,1,1

--> [1,2,3,11,12,13,-6,8,8,1,1,1]

I have thought the following in pseudocode:

for each array of arrays
  while shift > 0
    Add to the result list the current number (they are the first numbers)
  Add current number to next number (the one in the following array) into result
  Add the last numbers to result
return result

And I have written the following Java code:

import java.util.*;
import java.util.stream.*;

public class Kata
{
  public static int[] addingShifted/*➕*/(int[][] arrayOfArrays, int shift)
  {
    System.out.println("\n\n\narrayOfArrays: "+Arrays.deepToString(arrayOfArrays));
    System.out.println("shift: "+shift);
    List<Integer> result = new ArrayList<Integer>();
    int originalShift = shift;

    for(int i = 0; i < arrayOfArrays.length; i++){
      int[] current = arrayOfArrays[i];
      int[] next = new int[0];
      if(i < arrayOfArrays.length - 1){
        next = arrayOfArrays[i+1];
      }
      for(int j = (i > 0) ? originalShift : 0; j < current.length; j++){
        while(shift > 0){
          result.add(current[j++]);
          shift--;
        }
        System.out.println("j: "+j);
        System.out.println("current[j]: "+current[j]);
        System.out.println("next.length: "+next.length);
        System.out.println("next[j-originalShift]: "+(next.length > 0 ? next[j-originalShift] : 0));

        result.add(current[j] + (next.length > 0 ? next[j-originalShift] : 0));
        System.out.println("result: "+Arrays.toString(result.toArray()));
      }
      if(originalShift == 0) break;
    }
    return result.stream().mapToInt(i->i).toArray();
  }
}

I have found a test where the code's output is different than the expected one:

arrayOfArrays: [[0, -9, -2, -8, 8, 2, 5, -5, 7, 1, -5, -9, -9, -1, 1, -2, -5, 9, -1, 9, 6, 2, -4, 4], [-4, -2, -8, 1, -6, -5, 8, 8, -7, -3, -6, -8, 5, 6, 1, 0, -2, -1, 5, 3, -9, -2, 4, -3], [-7, 3, 5, -3, 2, 2, 0, -6, 6, 7, 0, 9, 0, -6, -8, 6, -3, -5, -2, -4, -7, -4, -7, 1], [5, -6, 8, 5, 1, -2, -8, 5, 7, -5, 6, -3, 0, 7, -4, 6, -7, -8, 0, 2, 8, 5, -1, -3], [-7, -4, 7, 0, 0, -1, 3, 0, -5, 5, -5, -3, -7, -5, -9, -4, -5, -8, -5, 9, 0, 8, 8, -7], [5, 8, 2, 0, 3, -3, 2, -2, 6, -5, -6, -8, 4, -7, 9, 3, 4, -6, -7, 4, -8, -9, -3, -9], [9, 8, -2, -8, 8, -1, 6, 6, 0, -7, 9, 9, 2, 3, -7, 9, 4, -8, 8, -2, -2, 7, 9, 2]]
shift: 2

Expected: [0, -9, -6, -10, [-7, 6, 9, -19, 18, 12, 1, -12, -6, 10, 17, -3, 7, 2, -4, 19, -9, -14, -18, -12, 3, -7, -7, 18, -4, 1, 8, -18, -5, -2], 9, 2]

Code's output: [0, -9, -6, -10, [0, 3, -1, -10, 15, 9, -12, -12, -15, -9, 6, 4, -4, 9, -3, 8, 11, 5, -13, 2, -15, 4, -1, -8, 10, 10, -7, -9, 0, -1, 5, 15, 1, -6, -10, 5, 2, -2, -11, -6, -3, -7, 10, -9, 10, 7, 1, -8, -2, 12, 7, 4, 6, -9, -8, 13, -7, 1, -9, -12, -7, -2, 1, 6, 1, 1, 8, -2, -8, 4, 10, -5, 1, 2, -5, 4, -11, 1, -16, -12, -5, -6, 3, 14, -1, 5, 12, 8, 2, -1, 6, -3, -3, 3, 1, -8, -13, -13, -5, -11, 4, -5, -1, 3, -7, 12, 0, -16, 11, 8, 1, -11, 10, -3, 12, 1, -6, -15, 13, 2, 11, 6, -3, 3, -3, -4, 0, -11, -5, -2, -2, -8, 8, -1, 6, 6, 0, -7, 9, 9, 2, 3, -7, 9, 4, -8, 8, -2, -2, 7], 9, 2]

The trace starts as follows:

j: 2
current[j]: -2
next.length: 24
next[j-originalShift]: -4
result: [0, -9, -6]
j: 3
current[j]: -8
next.length: 24
next[j-originalShift]: -2
result: [0, -9, -6, -10]
j: 4
current[j]: 8
next.length: 24
next[j-originalShift]: -8
result: [0, -9, -6, -10, 0]
j: 5
current[j]: 2
next.length: 24
next[j-originalShift]: 1
result: [0, -9, -6, -10, 0, 3]

We observe that the first result where our code and the expected result differs is when j: 4, so expected value is: -7 but it calculates 0 (8-8).

Also, we see that the output has a zillion more numbers than the expected result.

I wonder why both of the previous facts happen!?

How could we improve the code‽‽‽

Is there a simpler, cleaner and easier to read answer‽‽‽

I ask because of the code which I have posted passes the following tests (extracted from the exercise's tests):

import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.*;
import org.junit.runners.JUnit4;

public class SolutionTest {
    @Test
    public void basicTests() {        
      int[][] arrayOfArrays = new int[][] { new int[] { 1, 2, 3, 4, 5, 6 }, new int[] { 7, 7, 7, 7, 7, 7 } };
      int[] expected = new int[] { 8, 9, 10, 11, 12, 13 };
      int[] result = Kata.addingShifted(arrayOfArrays, 0);
      assertNotNull(result);
      assertEquals(Arrays.toString(expected), Arrays.toString(result));

      arrayOfArrays = new int[][] { new int[] { 1, 2, 3, 4, 5, 6 }, new int[] { 7, 7, 7, 7, 7, 7 } };
      expected = new int[] { 1, 2, 3, 11, 12, 13, 7, 7, 7 };
      result = Kata.addingShifted(arrayOfArrays, 3);
      assertNotNull(result);      
      assertEquals(Arrays.toString(expected), Arrays.toString(result));

      arrayOfArrays = new int[][] { new int[] { 1, 2, 3, 4, 5, 6 }, new int[] { 7, 7, 7, -7, 7, 7 }, new int[] { 1, 1, 1, 1, 1, 1 } };
      expected = new int[] { 1, 2, 3, 11, 12, 13, -6, 8, 8, 1, 1, 1 };
      result = Kata.addingShifted(arrayOfArrays, 3);
      assertNotNull(result);
      assertEquals(Arrays.toString(expected), Arrays.toString(result));

    }
}

However as we have seen it has difficulties with bigger arrays. Why‽

I have also read:

Yone
  • 2,064
  • 5
  • 25
  • 56

1 Answers1

2

Here is a simpler, cleaner solution:

public static int[] addingShifted(int[][] input, int shift) {
    int[] result = new int[input[0].length + shift * (input.length - 1)];
    for (int i = 0; i < input.length; i++)
        for (int j = 0; j < input[i].length; j++)
            result[i * shift + j] += input[i][j];
    return result;
}

Test

System.out.println(Arrays.toString(addingShifted(new int[][] {{1,2,3,4,5,6}, {7,7,7,7,7,-7}}, 0)));
System.out.println(Arrays.toString(addingShifted(new int[][] {{1,2,3,4,5,6}, {7,7,7,7,7,7}}, 3)));
System.out.println(Arrays.toString(addingShifted(new int[][] {{1,2,3,4,5,6}, {7,7,7,-7,7,7}, {1,1,1,1,1,1}}, 3)));

Output

[8, 9, 10, 11, 12, -1]
[1, 2, 3, 11, 12, 13, 7, 7, 7]
[1, 2, 3, 11, 12, 13, -6, 8, 8, 1, 1, 1]
Andreas
  • 154,647
  • 11
  • 152
  • 247