package com.interview.algorithms.general; import com.interview.basics.search.ASearcher; import com.interview.utils.ArrayUtil; /** * Created with IntelliJ IDEA. * User: stefanie * Date: 9/12/14 * Time: 2:41 PM * * Sudoku Game: Given a 3*3 matrix, and 1-8 numbers in random order, 1 place as space. * Write code to find the min exchange of numbers to make the matrix in order * 5 4 1 1 2 3 * 3 2 ---> 8 4 * 7 8 6 7 6 5 * Refer: http://blueve.me/archives/690 */ class GameState implements ASearcher.State<String> { static int size = 3; String s; GameState(String s) { this.s = s; } @Override public String key() { return s; } public GameState move(int direction){ String next = ""; int index = this.s.indexOf('0'); switch (direction){ case C1_55_SudokuGame.UP: if(index < 3) return null; next = ArrayUtil.swap(this.s, index, index - 3); break; case C1_55_SudokuGame.DOWN: if(index > 5) return null; next = ArrayUtil.swap(this.s, index, index + 3); break; case C1_55_SudokuGame.LEFT: if(index % 3 == 0) return null; next = ArrayUtil.swap(this.s, index, index - 1); break; case C1_55_SudokuGame.RIGHT: if((index + 1) % 3 == 0) return null; next = ArrayUtil.swap(this.s, index, index + 1); break; } return new GameState(next); } public static int getOp(String current, String next){ int i = current.indexOf('0'); int j = next.indexOf('0'); if(j == i - 3) return C1_55_SudokuGame.UP; else if(j == i + 3) return C1_55_SudokuGame.DOWN; else if(j == i + 1) return C1_55_SudokuGame.RIGHT; else if(j == i - 1) return C1_55_SudokuGame.LEFT; return -1; } public static String getString(Integer[][] matrix){ StringBuilder builder = new StringBuilder(); for(int i = 0; i < size; i++){ for(int j = 0; j < size; j++){ builder.append(matrix[i][j]); } } return builder.toString(); } public static void print(String s){ for(int i = 0; i < size; ++i){ for(int j = 0; j < size; ++j){ System.out.print(s.charAt(i * 3 + j) + " "); } System.out.println(); } } } public class C1_55_SudokuGame extends ASearcher<String, GameState, Integer> { public final static int UP = 0; public final static int DOWN = 1; public final static int LEFT = 2; public final static int RIGHT = 3; public final static int[] DIRECTIONS = new int[] {UP, DOWN, LEFT, RIGHT}; public C1_55_SudokuGame(Integer size) { super(size); } public void debug(boolean flag){ this.isDebug = flag; } @Override protected double heuristicEstimateDistance(GameState c, GameState t) { double diff = 0.0; for(int i = 0; i < 9; i++) { if(c.s.charAt(i) != t.s.charAt(i)) diff++; } return diff; } @Override protected boolean isSame(GameState c, GameState t) { return c.s.equals(t.s); } @Override protected GameState[] nextState(GameState gameState) { //System.out.println(gameState.key()); GameState[] next = new GameState[4]; int i = 0; for(int direction : DIRECTIONS){ next[i++] = gameState.move(direction); } return next; } @Override protected double gScore(Candidate c, GameState t) { return gScore.get(c.state.key()) + 1; } public int[] solve(Integer[][] startMatrix, Integer[][] endMatrix){ GameState start = new GameState(GameState.getString(startMatrix)); GameState end = new GameState(GameState.getString(endMatrix)); Path<String> path = this.pathTo(start, end); int[] ops = new int[path.path.size()]; if(path.path.size() > 0){ int i = 0; String pre = start.key(); while(!path.path.isEmpty()){ String current = path.path.pop(); int op = GameState.getOp(pre, current); pre = current; ops[i++] = op; } } return ops; } }