Advertisement
Guest User

Untitled

a guest
Apr 27th, 2017
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.53 KB | None | 0 0
  1. import java.util.*;
  2.  
  3. /*
  4.  * Encapsulates a Sudoku grid to be solved.
  5.  * CS108 Stanford.
  6.  */
  7. public class Sudoku {
  8.  
  9.     /**
  10.      * Stores empty rows in the way to easily test possible values of this spot.
  11.      */
  12.     private class Spot implements Comparable{
  13.  
  14.         // Private variables
  15.         private int row, column, value, curIndex;
  16.         private int[][] grid;
  17.         private List<Integer> nums;
  18.  
  19.         /**
  20.          * Constructor to create default empty spot on row and column coordinates
  21.          * @param row
  22.          * @param column
  23.          * @param grid
  24.          */
  25.         public Spot(int row, int column, int[][] grid){
  26.             this.grid = grid;
  27.             this.row = row;
  28.             this.column = column;
  29.             this.value = grid[row][column];
  30.             this.curIndex = -1;
  31.             nums = new ArrayList<>();
  32.         }
  33.  
  34.         /**
  35.          * Checks if the spot is valid with the current value
  36.          * @return
  37.          */
  38.         private boolean isValid(){
  39.             int bigRow = (row / PART) * PART;
  40.             int bigCol = (column / PART) * PART;
  41.             for(int i = 0; i < SIZE; i++)
  42.                 if(grid[i][column] == value && i != row || grid[row][i] == value && i != column) {
  43.                     return false;
  44.                 }
  45.             for(int i = 0; i < PART; i++)
  46.                 for(int j = 0; j < PART; j++)
  47.                     if(grid[bigRow + i][bigCol + j] == value && (bigRow + i != row || bigCol + j != column)) {
  48.                         return false;
  49.                     }
  50.             return true;
  51.         }
  52.  
  53.         /**
  54.          * Generates possible values that can be assigned to spot
  55.          * for current condition of grid.
  56.          */
  57.         public void findNums(){
  58.             nums.clear();
  59.             for(int i = 1; i <= SIZE; i++){
  60.                 setValue(i);
  61.                 if(isValid())
  62.                     addNum(i);
  63.             }
  64.             setValue(0);
  65.         }
  66.  
  67.         /**
  68.          * Picks next possible value from the list generated by findNums
  69.          * Returns false if all values have been tried
  70.          * If number can't be assigned writes 0 in the spot, but returns true
  71.          * @return
  72.          */
  73.         public boolean setNext(){
  74.             if(++curIndex >= nums.size()) {
  75.                 curIndex = -1;
  76.                 setValue(0);
  77.                 return false;
  78.             }
  79.             setValue(nums.get(curIndex));
  80.             if(isValid())
  81.                 return true;
  82.             setValue(0);
  83.             return true;
  84.         }
  85.  
  86.         /**
  87.          * Sets value
  88.          * @param value
  89.          */
  90.         private void setValue(int value){
  91.             grid[this.row][this.column] = value;
  92.             this.value = value;
  93.         }
  94.  
  95.         /**
  96.          * Adds number into possible values
  97.          * @param value
  98.          */
  99.         private void addNum(int value){
  100.             nums.add(value);
  101.         }
  102.  
  103.         /**
  104.          * Compares two spots
  105.          * @param s
  106.          * @return
  107.          */
  108.         @Override
  109.         public int compareTo(Object s){
  110.             if(s == null) throw new NullPointerException();
  111.             return new Integer(this.nums.size()).compareTo(((Spot)s).nums.size());
  112.         }
  113.  
  114.         /**
  115.          * Puts linebreak after any string or Object.toString
  116.          * @param o
  117.          * @return
  118.          */
  119.         private String ln(Object o){
  120.             return o + "\n";
  121.         }
  122.  
  123.         /**
  124.          * Writes object details as String
  125.          * @return
  126.          */
  127.         @Override
  128.         public String toString(){
  129.             String res = "";
  130.             res += ln("[");
  131.             res += ln("\trow: " + row);
  132.             res += ln("\tcolumn: " + column);
  133.             res += ln("\tvalue: " + value);
  134.             res += ln("\tcurIndex: " + curIndex);
  135.             res += ln("\tnums: " + Arrays.toString(nums.toArray()));
  136.             res += ln("]");
  137.             return res;
  138.         }
  139.     }
  140.  
  141.  
  142.     // Provided grid data for main/testing
  143.     // The instance variable strategy is up to you.
  144.    
  145.     // Provided easy 1 6 grid
  146.     // (can paste this text into the GUI too)
  147.     public static final int[][] easyGrid = Sudoku.stringsToGrid(
  148.     "1 6 4 0 0 0 0 0 2",
  149.     "2 0 0 4 0 3 9 1 0",
  150.     "0 0 5 0 8 0 4 0 7",
  151.     "0 9 0 0 0 6 5 0 0",
  152.     "5 0 0 1 0 2 0 0 8",
  153.     "0 0 8 9 0 0 0 3 0",
  154.     "8 0 9 0 4 0 2 0 0",
  155.     "0 7 3 5 0 9 0 0 1",
  156.     "4 0 0 0 0 0 6 7 9");
  157.  
  158.     public static final int[][] myGrid = Sudoku.stringsToGrid(
  159.     "0 0 0 0 0 0 0 0 0",
  160.     "0 0 0 0 0 0 0 0 0",
  161.     "0 0 0 0 0 0 0 0 0",
  162.     "0 0 0 0 0 0 0 0 0",
  163.     "0 0 0 0 0 0 0 0 0",
  164.     "0 0 0 0 0 0 0 0 0",
  165.     "0 0 0 0 0 0 0 0 0",
  166.     "0 0 0 0 0 0 0 0 0",
  167.     "0 0 0 0 0 0 0 0 0");
  168.  
  169.    
  170.     // Provided medium 5 3 grid
  171.     public static final int[][] mediumGrid = Sudoku.stringsToGrid(
  172.      "530070000",
  173.      "600195000",
  174.      "098000060",
  175.      "800060003",
  176.      "400803001",
  177.      "700020006",
  178.      "060000280",
  179.      "000419005",
  180.      "000080079");
  181.    
  182.     // Provided hard 3 7 grid
  183.     // 1 solution this way, 6 solutions if the 7 is changed to 0
  184.     public static final int[][] hardGrid = Sudoku.stringsToGrid(
  185.     "3 7 0 0 0 0 0 8 0",
  186.     "0 0 1 0 9 3 0 0 0",
  187.     "0 4 0 7 8 0 0 0 3",
  188.     "0 9 3 8 0 0 0 1 2",
  189.     "0 0 0 0 4 0 0 0 0",
  190.     "5 2 0 0 0 6 7 9 0",
  191.     "6 0 0 0 2 1 0 4 0",
  192.     "0 0 0 5 3 0 9 0 0",
  193.     "0 3 0 0 0 0 0 5 1");
  194.    
  195.    
  196.     public static final int SIZE = 9;  // size of the whole 9x9 puzzle
  197.     public static final int PART = 3;  // size of each 3x3 part
  198.     public static final int MAX_SOLUTIONS = 100;
  199.    
  200.     // Provided various static utility methods to
  201.     // convert data formats to int[][] grid.
  202.    
  203.     /**
  204.      * Returns a 2-d grid parsed from strings, one string per row.
  205.      * The "..." is a Java 5 feature that essentially
  206.      * makes "rows" a String[] array.
  207.      * (provided utility)
  208.      * @param rows array of row strings
  209.      * @return grid
  210.      */
  211.     public static int[][] stringsToGrid(String... rows) {
  212.         int[][] result = new int[rows.length][];
  213.         for (int row = 0; row<rows.length; row++) {
  214.             result[row] = stringToInts(rows[row]);
  215.         }
  216.         return result;
  217.     }
  218.    
  219.    
  220.     /**
  221.      * Given a single string containing 81 numbers, returns a 9x9 grid.
  222.      * Skips all the non-numbers in the text.
  223.      * (provided utility)
  224.      * @param text string of 81 numbers
  225.      * @return grid
  226.      */
  227.     public static int[][] textToGrid(String text) {
  228.         int[] nums = stringToInts(text);
  229.         if (nums.length != SIZE*SIZE) {
  230.             throw new RuntimeException("Needed 81 numbers, but got:" + nums.length);
  231.         }
  232.        
  233.         int[][] result = new int[SIZE][SIZE];
  234.         int count = 0;
  235.         for (int row = 0; row<SIZE; row++) {
  236.             for (int col=0; col<SIZE; col++) {
  237.                 result[row][col] = nums[count];
  238.                 count++;
  239.             }
  240.         }
  241.         return result;
  242.     }
  243.    
  244.    
  245.     /**
  246.      * Given a string containing digits, like "1 23 4",
  247.      * returns an int[] of those digits {1 2 3 4}.
  248.      * (provided utility)
  249.      * @param string string containing ints
  250.      * @return array of ints
  251.      */
  252.     public static int[] stringToInts(String string) {
  253.         int[] a = new int[string.length()];
  254.         int found = 0;
  255.         for (int i=0; i<string.length(); i++) {
  256.             if (Character.isDigit(string.charAt(i))) {
  257.                 a[found] = Integer.parseInt(string.substring(i, i+1));
  258.                 found++;
  259.             }
  260.         }
  261.         int[] result = new int[found];
  262.         System.arraycopy(a, 0, result, 0, found);
  263.         return result;
  264.     }
  265.  
  266.  
  267.     // Provided -- the deliverable main().
  268.     // You can edit to do easier cases, but turn in
  269.     // solving hardGrid.
  270.     public static void main(String[] args) {
  271.         Sudoku sudoku;
  272.         sudoku = new Sudoku(myGrid);
  273.        
  274.         System.out.println(sudoku); // print the raw problem
  275.         int count = sudoku.solve();
  276.         System.out.println("solutions:" + count);
  277.         System.out.println("elapsed:" + sudoku.getElapsed() + "ms");
  278.         System.out.println(sudoku.getSolutionText());
  279.     }
  280.    
  281.  
  282.     // Private variables
  283.     private int[][] grid;
  284.     private int[][] resultGrid;
  285.     private List<Spot> emptySpots;
  286.     private long time;
  287.    
  288.  
  289.     /**
  290.      * Sets up based on the given ints.
  291.      */
  292.     public Sudoku(int[][] ints) {
  293.         if(ints.length != SIZE || ints[0].length != SIZE) throw new RuntimeException("Parsing Problem");
  294.         grid = copyGrid(ints);
  295.         emptySpots = new ArrayList<>();
  296.         resultGrid = null;
  297.         for(int i = 0; i < grid.length; i++){
  298.             for(int j = 0; j < grid[i].length; j++) {
  299.                 if (grid[i][j] == 0) {
  300.                     Spot s = new Spot(i, j, grid);
  301.                     emptySpots.add(s);
  302.                     s.findNums();
  303.                 }
  304.             }
  305.         }
  306.         Collections.sort(emptySpots);
  307.     }
  308.  
  309.     /**
  310.      * String constructor
  311.      * @param text
  312.      */
  313.     public Sudoku(String text){
  314.         this(textToGrid(text));
  315.     }
  316.  
  317.  
  318.     /**
  319.      * Copies and returns ints grid
  320.      * @param grid
  321.      * @return
  322.      */
  323.     private int[][] copyGrid(int[][] grid){
  324.         int[][] res = new int[grid.length][grid[0].length];
  325.         for(int i = 0; i < grid.length; i++)
  326.             System.arraycopy(grid[i], 0, res[i], 0, grid[i].length);
  327.         return res;
  328.     }
  329.  
  330.     /**
  331.      * Solves sudoku for ith empty spot, assumes that if method is called, everything before it was right
  332.      * @param i
  333.      * @return
  334.      */
  335.     public int solve(int i){
  336.         int res = 0;
  337.         if(i >= emptySpots.size()){
  338.             if(resultGrid == null)
  339.                 resultGrid = copyGrid(grid);
  340.             return 1;
  341.         }
  342.         Spot s = emptySpots.get(i);
  343.         s.findNums();
  344.         while(s.setNext()){
  345. //          if(s.value == 0)
  346. //              continue;
  347.             res += solve(i + 1);
  348.             if(res >= MAX_SOLUTIONS) return res;
  349.         }
  350.         return res;
  351.     }
  352.  
  353.     /**
  354.      * Checks entire board to see if starting grid was bad or not
  355.      * @return
  356.      */
  357.     private boolean checkBoard(){
  358.         for(int i = 0; i < SIZE; i++)
  359.             for(int j = 0; j < SIZE; j++)
  360.                 if(grid[i][j] != 0)
  361.                     if(!new Spot(i, j, grid).isValid())
  362.                         return false;
  363.         return true;
  364.     }
  365.    
  366.    
  367.     /**
  368.      * Solves the puzzle, invoking the underlying recursive search.
  369.      */
  370.     public int solve() {
  371.         if(!checkBoard())
  372.             throw new RuntimeException("Parsing Problem");
  373.         time = System.currentTimeMillis();
  374.         int res = solve(0);
  375.         time = System.currentTimeMillis() - time;
  376.         return res;
  377.     }
  378.  
  379.     /**
  380.      * Returns solved puzzle
  381.      * @return
  382.      */
  383.     public String getSolutionText() {
  384.         return gridToString(resultGrid);
  385.     }
  386.  
  387.     /**
  388.      * Returns time needed to solve puzzle
  389.      * @return
  390.      */
  391.     public long getElapsed() {
  392.         return time;
  393.     }
  394.  
  395.  
  396.     /**
  397.      * Returns default grid
  398.      * @return
  399.      */
  400.     @Override
  401.     public String toString(){
  402.         return gridToString(grid);
  403.     }
  404.  
  405.     /**
  406.      * Makes string from grid
  407.      * @param grid
  408.      * @return
  409.      */
  410.     private String gridToString(int[][] grid){
  411.         String res = "";
  412.         for(int i = 0; i < SIZE; i++){
  413.             for(int j = 0; j < SIZE; j++)
  414.                 res = res + grid[i][j] + " ";
  415.             res = res + "\n";
  416.         }
  417.         return res;
  418.     }
  419. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement