(This post has an continuation: Snail matrix in Java - version II.)
Inspired by this post, I decided to solve that problem in Java. The idea is to decide on an \$n \in \mathbb{N}\$, create a square matrix \$M_n = \mathbb{N}^{n \times n}, \$ and set the integers \$1, 2, \ldots, n^2\$ in \$M_n\$ such that they resemble a «snail pattern». For example, for \$n = 3,\$ \$M_3\$ is
1 2 3
8 9 4
7 6 5
com.github.coderodde.fun.snailmatrix.SnailMatrixGenerator.java:
package com.github.coderodde.fun.snailmatrix;
/**
* This class provides a static method for generating snail matrices. A snail
* matrix is any square matrix with all the cell values {@code 1, 2, ..., n x n}
* in a snail pattern. For example, for {@code n = 3}, the matrix will look like
* <code>
* 1 2 3
* 8 9 4
* 7 6 5
* </code>
*/
public final class SnailMatrixGenerator {
private final SnailMatrix matrix;
private final IntPair currentCursor = new IntPair();
private final IntPair[] deltas =
{
new IntPair(1, 0),
new IntPair(0, 1),
new IntPair(-1, 0),
new IntPair(0, -1)
};
private int deltaIndex = 0;
private SnailMatrixGenerator(final int n) {
this.matrix = new SnailMatrix(n);
}
public static SnailMatrix generateSnailMatrix(final int n) {
final SnailMatrixGenerator state = new SnailMatrixGenerator(n);
int value = 1;
while (true) {
state.setValueAtCursor(value);
if (value == n * n) {
return state.matrix;
}
value++;
state.moveCursorToNextLocation();
}
}
private void setValueAtCursor(final int value) {
matrix.set(currentCursor.x,
currentCursor.y,
value);
}
private void moveCursorToNextLocation() {
final int saveX = currentCursor.x;
final int saveY = currentCursor.y;
while (true) {
final int x = saveX + deltas[deltaIndex].x;
final int y = saveY + deltas[deltaIndex].y;
if (checkCurrentCursorIsValid(x, y)) {
currentCursor.x = x;
currentCursor.y = y;
return;
}
getNextCursorDirection();
}
}
private boolean checkCurrentCursorIsValid(final int x, final int y) {
final int n = matrix.getWidth();
if (x == -1 || x == n || y == -1 || y == n) {
return false;
}
return matrix.get(x, y) == 0;
}
private void getNextCursorDirection() {
if (deltaIndex == 3) {
deltaIndex = 0;
} else {
deltaIndex++;
}
}
public static void main(String[] args) {
final int n = 3;
final SnailMatrix matrix = SnailMatrixGenerator.generateSnailMatrix(n);
System.out.println(matrix);
}
private static final class IntPair {
IntPair(final int x, final int y) {
this.x = x;
this.y = y;
}
IntPair() {}
int x;
int y;
}
}
com.github.coderodde.fun.snailmatrix.SnailMatrix.java:
package com.github.coderodde.fun.snailmatrix;
public final class SnailMatrix {
private final int[][] data;
SnailMatrix(final int n) {
this.data = new int[n][n];
}
public int getWidth() {
return data.length;
}
public int getCapacity() {
return data.length * data.length;
}
public int get(final int x, final int y) {
return data[y][x];
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
final int capacity = getCapacity();
final int cellLength = Integer.toString(capacity).length();
final String cellFormat = String.format("%%%dd ", cellLength);
for (int y = 0; y < getWidth(); y++) {
for (int x = 0; x < getWidth(); x++) {
sb.append(String.format(cellFormat, get(x, y)));
}
sb.append("\n");
}
sb.deleteCharAt(sb.length() - 1); // Delete last newline character.
return sb.toString();
}
void set(final int x, final int y, final int value) {
data[y][x] = value;
}
}
Typical output
For \$n = 10\$, the output is:
1 2 3 4 5 6 7 8 9 10
36 37 38 39 40 41 42 43 44 11
35 64 65 66 67 68 69 70 45 12
34 63 84 85 86 87 88 71 46 13
33 62 83 96 97 98 89 72 47 14
32 61 82 95 100 99 90 73 48 15
31 60 81 94 93 92 91 74 49 16
30 59 80 79 78 77 76 75 50 17
29 58 57 56 55 54 53 52 51 18
28 27 26 25 24 23 22 21 20 19
Critique request
As always, I would be glad to receive any commentary on my work here.