The key is to generalize like mad! - Force your code to deal with any square puzzle. - Strive to reuse the same code for rows and columns. Additional tips: - Make it object-oriented to reduce parameter-passing clutter. - Use 0-based indexing for row and column numbers. - Avoid `ArrayList` — your lists aren't going to grow. Arrays have tidier syntax and better performance. <!-- --> // Use Arrays.binarySearch() like ArrayList.indexOf() import static java.util.Arrays.binarySearch; public class Puzzle { public static enum Axis { ROW, COL }; private int[] state; private int side; public Puzzle(int[] state) { this.state = state; this.side = (int)Math.sqrt(state.length); if (side * side != state.length) { throw new IllegalArgumentException("Puzzle must be square"); } } /** * Returns the squares of the puzzle for a specified row or column. * * @param rc row or col number (0-based) */ private int[] tuple(Axis dir, int rc) { int[] result = new int[this.side]; switch (dir) { case ROW: System.arraycopy(this.state, rc * this.side, result, 0, this.side); break; case COL: for (int i = 0, j = rc; i < this.side; i++, j += this.side) { result[i] = this.state[j]; } break; } return result; } /** * Returns the squares of the puzzle of this size as if it were in * its solved state for a specified row or column. * * @param rc row or col number (0-based) */ private int[] idealTuple(Axis dir, int rc) { int[] result = new int[this.side]; switch (dir) { case ROW: for (int i = 0, j = rc * this.side + 1; i < this.side; i++, j++) { result[i] = (j < this.state.length) ? j : 0; } break; case COL: for (int i = 0, j = this.side + rc + 1; i < this.side; i++, j += this.side) { result[i] = (j < this.state.length) ? j : 0; } break; } return result; } /** * Count inversions (linear conflicts) for a row or column. */ public int inversions(Axis dir, int rc) { int[] have = this.tuple(dir, rc); int[] want = this.idealTuple(dir, rc); int inversions = 0; // For each pair of squares, if both numbers are supposed to be in this // tuple, and neither is 0 (blank)... for (int i = 1, iPos; i < this.side; i++) { if (have[i] != 0 && 0 <= (iPos = binarySearch(want, have[i]))) { for (int j = 0, jPos; j < i; j++) { if (have[j] != 0 && 0 <= (jPos = binarySearch(want, have[j]))) { // ... and are inverted, count it as a conflict. if ((have[i] < have[j]) != (i < j)) { inversions++; } } } } } return inversions; } public static void main(String[] args) { Puzzle p = new Puzzle(new int[] { 3, 2, 1, 4, 7, 5, 8, 6, 0 }); System.out.printf("Row %d inversions = %d\n", 0, p.inversions(Axis.ROW, 0)); System.out.printf("Row %d inversions = %d\n", 1, p.inversions(Axis.ROW, 1)); System.out.printf("Row %d inversions = %d\n", 2, p.inversions(Axis.ROW, 2)); System.out.printf("Col %d inversions = %d\n", 0, p.inversions(Axis.COL, 0)); System.out.printf("Col %d inversions = %d\n", 1, p.inversions(Axis.COL, 1)); System.out.printf("Col %d inversions = %d\n", 2, p.inversions(Axis.COL, 2)); } }