import java.util.*;
import java.lang.*;
class Main
{
private static Point current = new Point(0, 0);
private static Direction lastMove = Direction.RIGHT;
private static int width;
private static int height;
private static Set<Point> visited;
public static void main(String[] args) throws java.lang.Exception {
int [][] test = {
{ 1, 2, 3 },
{ 4, 5, 6 } ,
{ 7, 8, 9 } };
spiralPrint(test);
}
public static synchronized void spiralPrint(int[][] data)
{
width = data[0].length;
height = data.length;
int numPoints = width * height;
visited = new HashSet<Point>();
while (visited.size() < numPoints)
{
System.out.print(data[current.y][current.x]);
System.out.print(" ");
visited.add(current);
current = getNextMove();
}
}
private static Point getNextMove()
{
int x = current.x;
int y = current.y;
Point nextPoint = lastMove.nextPoint(x, y);
if (! visited.contains(nextPoint)
&& nextPoint.x < width && nextPoint.x >= 0
&& nextPoint.y < height && nextPoint.y >= 0)
{
return nextPoint;
}
lastMove = lastMove.turnRight();
return lastMove.nextPoint(x, y);
}
private static class Point
{
private Integer x;
private Integer y;
public Point(Integer x, Integer y)
{
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object anotherObj)
{
Point test = (Point) anotherObj;
return test.x == this.x && test.y == this.y;
}
@Override
public int hashCode()
{
return this.x.hashCode() ^ this.y.hashCode();
}
}
private static enum Direction
{
UP, DOWN, LEFT, RIGHT;
public Point nextPoint(int x, int y)
{
if (this == Direction.RIGHT)
{
return new Point(x + 1, y);
}
if (this == Direction.LEFT)
{
return new Point(x - 1, y);
}
if (this == Direction.DOWN)
{
return new Point(x, y + 1);
}
return new Point(x, y - 1);
}
public Direction turnRight()
{
if (this == Direction.RIGHT)
{
return Direction.DOWN;
}
if (this == Direction.LEFT)
{
return Direction.UP;
}
if (this == Direction.DOWN)
{
return Direction.LEFT;
}
return Direction.RIGHT;
}
}
}
aW1wb3J0IGphdmEudXRpbC4qOwoKaW1wb3J0IGphdmEubGFuZy4qOyAKY2xhc3MgTWFpbgoKewoKcHJpdmF0ZSBzdGF0aWMgUG9pbnQgY3VycmVudCA9IG5ldyBQb2ludCgwLCAwKTsKCnByaXZhdGUgc3RhdGljIERpcmVjdGlvbiBsYXN0TW92ZSA9IERpcmVjdGlvbi5SSUdIVDsKCnByaXZhdGUgc3RhdGljIGludCB3aWR0aDsKCnByaXZhdGUgc3RhdGljIGludCBoZWlnaHQ7Cgpwcml2YXRlIHN0YXRpYyBTZXQ8UG9pbnQ+IHZpc2l0ZWQ7IApwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB0aHJvd3MgamF2YS5sYW5nLkV4Y2VwdGlvbiB7IAoKaW50IFtdW10gdGVzdCA9IHsKCnsgMSwgMiwgMyB9LAoKeyA0LCA1LCA2IH0gLAoKeyA3LCA4LCA5IH0gfTsgCgpzcGlyYWxQcmludCh0ZXN0KTsKCn0gCgpwdWJsaWMgc3RhdGljIHN5bmNocm9uaXplZCB2b2lkIHNwaXJhbFByaW50KGludFtdW10gZGF0YSkKCnsKCndpZHRoID0gZGF0YVswXS5sZW5ndGg7CgpoZWlnaHQgPSBkYXRhLmxlbmd0aDsKCmludCBudW1Qb2ludHMgPSB3aWR0aCAqIGhlaWdodDsKCnZpc2l0ZWQgPSBuZXcgSGFzaFNldDxQb2ludD4oKTsKCndoaWxlICh2aXNpdGVkLnNpemUoKSA8IG51bVBvaW50cykKCnsKClN5c3RlbS5vdXQucHJpbnQoZGF0YVtjdXJyZW50LnldW2N1cnJlbnQueF0pOwoKU3lzdGVtLm91dC5wcmludCgiICIpOwoKdmlzaXRlZC5hZGQoY3VycmVudCk7CgpjdXJyZW50ID0gZ2V0TmV4dE1vdmUoKTsKCn0KCn0gCgpwcml2YXRlIHN0YXRpYyBQb2ludCBnZXROZXh0TW92ZSgpCgp7CgppbnQgeCA9IGN1cnJlbnQueDsKCmludCB5ID0gY3VycmVudC55OwoKUG9pbnQgbmV4dFBvaW50ID0gbGFzdE1vdmUubmV4dFBvaW50KHgsIHkpOwoKaWYgKCEgdmlzaXRlZC5jb250YWlucyhuZXh0UG9pbnQpCgomJiBuZXh0UG9pbnQueCA8IHdpZHRoICYmIG5leHRQb2ludC54ID49IDAKCiYmIG5leHRQb2ludC55IDwgaGVpZ2h0ICYmIG5leHRQb2ludC55ID49IDApCgp7CgpyZXR1cm4gbmV4dFBvaW50OwoKfSAKCmxhc3RNb3ZlID0gbGFzdE1vdmUudHVyblJpZ2h0KCk7CgpyZXR1cm4gbGFzdE1vdmUubmV4dFBvaW50KHgsIHkpOwoKfSAKCnByaXZhdGUgc3RhdGljIGNsYXNzIFBvaW50Cgp7Cgpwcml2YXRlIEludGVnZXIgeDsKCnByaXZhdGUgSW50ZWdlciB5OyAKcHVibGljIFBvaW50KEludGVnZXIgeCwgSW50ZWdlciB5KQoKewoKdGhpcy54ID0geDsKCnRoaXMueSA9IHk7Cgp9IAoKQE92ZXJyaWRlCgpwdWJsaWMgYm9vbGVhbiBlcXVhbHMoT2JqZWN0IGFub3RoZXJPYmopCgp7CgpQb2ludCB0ZXN0ID0gKFBvaW50KSBhbm90aGVyT2JqOwoKcmV0dXJuIHRlc3QueCA9PSB0aGlzLnggJiYgdGVzdC55ID09IHRoaXMueTsKCn0gCgpAT3ZlcnJpZGUKCnB1YmxpYyBpbnQgaGFzaENvZGUoKQoKewoKcmV0dXJuIHRoaXMueC5oYXNoQ29kZSgpIF4gdGhpcy55Lmhhc2hDb2RlKCk7Cgp9Cgp9IAoKcHJpdmF0ZSBzdGF0aWMgZW51bSBEaXJlY3Rpb24KCnsKClVQLCBET1dOLCBMRUZULCBSSUdIVDsgCnB1YmxpYyBQb2ludCBuZXh0UG9pbnQoaW50IHgsIGludCB5KQoKewoKaWYgKHRoaXMgPT0gRGlyZWN0aW9uLlJJR0hUKQoKewoKcmV0dXJuIG5ldyBQb2ludCh4ICsgMSwgeSk7Cgp9CgppZiAodGhpcyA9PSBEaXJlY3Rpb24uTEVGVCkKCnsKCnJldHVybiBuZXcgUG9pbnQoeCAtIDEsIHkpOwoKfQoKaWYgKHRoaXMgPT0gRGlyZWN0aW9uLkRPV04pCgp7CgpyZXR1cm4gbmV3IFBvaW50KHgsIHkgKyAxKTsKCn0KCnJldHVybiBuZXcgUG9pbnQoeCwgeSAtIDEpOwoKfQoKcHVibGljIERpcmVjdGlvbiB0dXJuUmlnaHQoKQoKewoKaWYgKHRoaXMgPT0gRGlyZWN0aW9uLlJJR0hUKQoKewoKcmV0dXJuIERpcmVjdGlvbi5ET1dOOwoKfQoKaWYgKHRoaXMgPT0gRGlyZWN0aW9uLkxFRlQpCgp7CgpyZXR1cm4gRGlyZWN0aW9uLlVQOwoKfQoKaWYgKHRoaXMgPT0gRGlyZWN0aW9uLkRPV04pCgp7CgpyZXR1cm4gRGlyZWN0aW9uLkxFRlQ7Cgp9CgpyZXR1cm4gRGlyZWN0aW9uLlJJR0hUOwoKfQoKfQoKfQ==