/** * A spec is an 81-character string, representing a Sudoku board's cells * starting in the upper left, going across the top row, then starting * back at the left edge of the second row. Just like reading a book * printed in the English language. Filled-in cells should contain the * appropriate digit (1-9). Empty cells can contain any other value, * but zero, a dash, or a period is recommended. */ class BoardSpec { String _spec Board _board; def BoardSpec(Board board) { _board = board } def BoardSpec(String spec) { spec = spec.trim() if (spec.length() != 81) { throw new IllegalArgumentException("Your spec is " + spec.length() + " characters long. It MUST be 81.") } _spec = spec.replaceAll(/[^1-9]/, '.') } def getBoard() { if (_board == null) { _board = new Board() _spec.eachWithIndex { it, i -> if (it != '.') { _board.getCell(Math.floor(i / 9) + 1 as int, i % 9 + 1).setValue(it.toInteger()) } } } _board } def getSpec() { if (_spec == null) { def sb = new StringBuilder() def cell for (r in 1..9) { for (c in 1..9) { cell = board.getCell(r, c) sb.append(cell.isKnown() ? cell.value : '.') } } _spec = sb.toString() } _spec } private char[][] toGrid(s) { def g = new char[9][9] s.eachWithIndex { it, i -> g[Math.floor(i / 9) as int][i % 9] = it as char } g } def rotateLeft() { def grid = toGrid(spec) def sb = new StringBuilder() for (c in 0..8) { for (r in 0..8) { sb.append(grid[r][8 - c]) } } new BoardSpec(sb.toString()) } def rotateRight() { def grid = toGrid(spec) def sb = new StringBuilder() for (c in 0..8) { for (r in 0..8) { sb.append(grid[8 - r][c]) } } new BoardSpec(sb.toString()) } def rotateAround() { // cheat!! flipLeftToRight().flipTopToBottom() } def flipLeftToRight() { def grid = toGrid(spec) def sb = new StringBuilder() for (r in 0..8) { for (c in 0..8) { sb.append(grid[r][8 - c]) } } new BoardSpec(sb.toString()) } def flipTopToBottom() { def grid = toGrid(spec) def sb = new StringBuilder() for (r in 0..8) { for (c in 0..8) { sb.append(grid[8 - r][c]) } } new BoardSpec(sb.toString()) } def flipPrimaryDiagonal() { // cheat!! rotateRight().flipLeftToRight() } def flipSecondaryDiagonal() { // cheat!! flipLeftToRight().rotateRight() } def swapNumbers(a, b) { a = a.toString() b = b.toString() new BoardSpec(spec.replaceAll(a, 'x').replaceAll(b, a).replaceAll('x', b)) } String toString() { spec } String getWrapped() { spec.replaceAll(/([0-9.]{9})/, '$1\n').trim() } }