Advertisement
heavenriver

FI2HW02.java (Fifteen game: minimum moves left calculator)

Jun 3rd, 2013
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.26 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.*;
  3.  
  4. class FI12HW02
  5.    
  6.     {
  7.    
  8.     private static HashSet<SearchNode> nodes; // Configuration nodes set
  9.    
  10.     // Main method
  11.    
  12.     public static void main(String[] args) throws Exception
  13.         {
  14.         System.out.println(solve());
  15.         }
  16.    
  17.     // Solving method (main), builds the structure and calls auxiliary method. Time: Unknown
  18.    
  19.     public static int solve() throws IOException
  20.         {
  21.         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  22.         String line = br.readLine();
  23.         StringTokenizer st = new StringTokenizer(line);
  24.         String nextToken = st.nextToken();
  25.         int[][] puzzle = new int[4][4];
  26.         for(int i = 0; i < 4; i++) // Building the initial matrix
  27.             {
  28.             for(int j = 0; j < 4; j++)
  29.                 {
  30.                 puzzle[i][j] = Integer.parseInt(nextToken);
  31.                 if(st.hasMoreTokens()) nextToken = st.nextToken();
  32.                 }
  33.             line = br.readLine();
  34.             if(line != null) st = new StringTokenizer(line);
  35.             if(st.hasMoreTokens()) nextToken = st.nextToken();
  36.             }
  37.         SearchNode first = new SearchNode(puzzle, 0, null); // Initializes first node in sequence to initial configuration
  38.         nodes = new HashSet<SearchNode>(20, 0.5f);
  39.         return minDistance(first); // Calculates the minimum number of moves necessary
  40.         }
  41.    
  42.     // Calculates minimum moves. Time: Unknown
  43.    
  44.     private static int minDistance(SearchNode n)
  45.         {
  46.         if(n.isFinal()) return n.moves;
  47.         int[][] up = moveUp(n.config);
  48.         int[][] down = moveDown(n.config);
  49.         int[][] left = moveLeft(n.config);
  50.         int[][] right = moveRight(n.config);
  51.         if((n.previous == null || !n.previous.notMoved(up)) && !n.notMoved(up)) nodes.add(new SearchNode(up, n.moves + 1, n));
  52.         if((n.previous == null || !n.previous.notMoved(down)) && !n.notMoved(down)) nodes.add(new SearchNode(down, n.moves + 1, n));
  53.         if((n.previous == null || !n.previous.notMoved(left)) && !n.notMoved(left)) nodes.add(new SearchNode(left, n.moves + 1, n));
  54.         if((n.previous == null || !n.previous.notMoved(right)) && !n.notMoved(right)) nodes.add(new SearchNode(right, n.moves + 1, n));
  55.         SearchNode next = removeMin();
  56.         return minDistance(next);
  57.         }
  58.    
  59.     // Takes an input configuration and returns the node containing the following configuration, moving up the first free square. Time: O(n^2)
  60.    
  61.     private static int[][] moveUp(int[][] m)
  62.         {
  63.         int[][] out = new int[4][4];
  64.         boolean substituted = false;
  65.         int switchedRow = -1;
  66.         int switchedColumn = -1;
  67.         for(int i = 0; i < 4; i++)
  68.             {
  69.             for(int j = 0; j < 4; j++)
  70.                 {
  71.                 if(m[i][j] == 0 && !substituted && i < 3)
  72.                     {
  73.                     out[i][j] = m[i + 1][j];
  74.                     out[i + 1][j] = 0;
  75.                     substituted = true;
  76.                     switchedRow = i + 1;
  77.                     switchedColumn = j;
  78.                     }
  79.                 else
  80.                     {
  81.                     if(i != switchedRow || j != switchedColumn)
  82.                         out[i][j] = m[i][j];
  83.                     }
  84.                 }
  85.             }
  86.         return out;
  87.         }
  88.    
  89.     // Takes an input configuration and returns the node containing the following configuration, moving down the first free square. Time: O(n^2)
  90.    
  91.     private static int[][] moveDown(int[][] m)
  92.         {
  93.         int[][] out = new int[4][4];
  94.         boolean substituted = false;
  95.         int switchedRow = -1;
  96.         int switchedColumn = -1;
  97.         for(int i = 0; i < 4; i++)
  98.             {
  99.             for(int j = 0; j < 4; j++)
  100.                 {
  101.                 if(m[i][j] == 0 && !substituted && i > 0)
  102.                     {
  103.                     out[i][j] = m[i - 1][j];
  104.                     out[i - 1][j] = 0;
  105.                     substituted = true;
  106.                     switchedRow = i - 1;
  107.                     switchedColumn = j;
  108.                     }
  109.                 else
  110.                     {
  111.                     if(i != switchedRow || j != switchedColumn)
  112.                         out[i][j] = m[i][j];
  113.                     }
  114.                 }
  115.             }
  116.         return out;
  117.         }
  118.    
  119.     // Takes an input configuration and returns the node containing the following configuration, moving left the first free square. Time: O(n^2)
  120.    
  121.     private static int[][] moveLeft(int[][] m)
  122.         {
  123.         int[][] out = new int[4][4];
  124.         boolean substituted = false;
  125.         int switchedRow = -1;
  126.         int switchedColumn = -1;
  127.         for(int i = 0; i < 4; i++)
  128.             {
  129.             for(int j = 0; j < 4; j++)
  130.                 {
  131.                 if(m[i][j] == 0 && !substituted && j < 3)
  132.                     {
  133.                     out[i][j] = m[i][j + 1];
  134.                     out[i][j + 1] = 0;
  135.                     substituted = true;
  136.                     switchedRow = i;
  137.                     switchedColumn = j + 1;
  138.                     }
  139.                 else
  140.                     {
  141.                     if(i != switchedRow || j != switchedColumn)
  142.                         out[i][j] = m[i][j];
  143.                     }
  144.                 }
  145.             }
  146.         return out;
  147.         }
  148.    
  149.     // Takes an input configuration and returns the node containing the following configuration, moving right the first free square. Time: O(n^2)
  150.    
  151.     private static int[][] moveRight(int[][] m)
  152.         {
  153.         int[][] out = new int[4][4];
  154.         boolean substituted = false;
  155.         int switchedRow = -1;
  156.         int switchedColumn = -1;
  157.         for(int i = 0; i < 4; i++)
  158.             {
  159.             for(int j = 0; j < 4; j++)
  160.                 {
  161.                 if(m[i][j] == 0 && !substituted && j > 0)
  162.                     {
  163.                     out[i][j] = m[i][j - 1];
  164.                     out[i][j - 1] = 0;
  165.                     substituted = true;
  166.                     switchedRow = i;
  167.                     switchedColumn = j - 1;
  168.                     }
  169.                 else
  170.                     {
  171.                     if(i != switchedRow || j != switchedColumn)
  172.                         out[i][j] = m[i][j];
  173.                     }
  174.                 }
  175.             }
  176.         return out;
  177.         }
  178.    
  179.     // Removes and returns the minimum distance node in the list. Time: O(n)
  180.    
  181.     private static SearchNode removeMin()
  182.         {
  183.         SearchNode out = null;
  184.         int manhMin = Integer.MAX_VALUE;
  185.         Iterator<SearchNode> it = nodes.iterator();
  186.         while(it.hasNext())
  187.             {
  188.             SearchNode n = (SearchNode)it.next();
  189.             if(n.manhattan + n.moves < manhMin)
  190.                 {
  191.                 out = n;
  192.                 manhMin = n.manhattan + n.moves;
  193.                 }
  194.             }
  195.         nodes.remove(out);
  196.         return out;
  197.         }
  198.    
  199.     // SearchNode class
  200.    
  201.     static class SearchNode
  202.         {
  203.        
  204.         int[][] config;
  205.         int moves;
  206.         SearchNode previous;
  207.         int manhattan;
  208.        
  209.         SearchNode(int[][] config, int moves, SearchNode previous)
  210.             {
  211.             this.config = config;
  212.             this.moves = moves;
  213.             this.previous = previous;
  214.             manhattan = manhattanDistance();
  215.             }
  216.        
  217.         // Checks if the given configuration is final. Time: O(1)
  218.        
  219.         boolean isFinal()
  220.             {
  221.             return (config[0][0] == 1 && config[0][1] == 2 && config[0][2] == 3 && config[0][3] == 4 &&
  222.                     config[1][0] == 5 && config[1][1] == 6 && config[1][2] == 7 && config[1][3] == 8 &&
  223.                     config[2][0] == 9 && config[2][1] == 10 && config[2][2] == 11 && config[2][3] == 12 &&
  224.                     config[3][0] == 13 && config[3][1] == 14 && config[3][2] == 15 && config[3][3] == 0);
  225.             }
  226.        
  227.         // Checks if the given node has the same configuration as the current node. Time: O(1)
  228.        
  229.         boolean notMoved(int[][] m)
  230.             {
  231.             return (config[0][0] == m[0][0] && config[0][1] == m[0][1] && config[0][2] == m[0][2] && config[0][3] == m[0][3] &&
  232.                     config[1][0] == m[1][0] && config[1][1] == m[1][1] && config[1][2] == m[1][2] && config[1][3] == m[1][3] &&
  233.                     config[2][0] == m[2][0] && config[2][1] == m[2][1] && config[2][2] == m[2][2] && config[2][3] == m[2][3] &&
  234.                     config[3][0] == m[3][0] && config[3][1] == m[3][1] && config[3][2] == m[3][2] && config[3][3] == m[3][3]);
  235.             }
  236.        
  237.         // Calculates the current node's Manhattan distance. Time: O(n^2)
  238.        
  239.         int manhattanDistance()
  240.             {
  241.             int manh = 0;
  242.             for(int i = 0; i < 4; i++)
  243.                 {
  244.                 for(int j = 0; j < 4; j++)
  245.                     {
  246.                     if(config[i][j] == 1)
  247.                         manh = manh + Math.abs(i) + Math.abs(j);
  248.                     else if(config[i][j] == 2)
  249.                         manh = manh + Math.abs(i) + Math.abs(j - 1);
  250.                     else if(config[i][j] == 3)
  251.                         manh = manh + Math.abs(i) + Math.abs(j - 2);
  252.                     else if(config[i][j] == 4)
  253.                         manh = manh + Math.abs(i) + Math.abs(j - 3);
  254.                     else if(config[i][j] == 5)
  255.                         manh = manh + Math.abs(i - 1) + Math.abs(j);
  256.                     else if(config[i][j] == 6)
  257.                         manh = manh + Math.abs(i - 1) + Math.abs(j - 1);
  258.                     else if(config[i][j] == 7)
  259.                         manh = manh + Math.abs(i - 1) + Math.abs(j - 2);
  260.                     else if(config[i][j] == 8)
  261.                         manh = manh + Math.abs(i - 1) + Math.abs(j - 3);
  262.                     else if(config[i][j] == 9)
  263.                         manh = manh + Math.abs(i - 2) + Math.abs(j);
  264.                     else if(config[i][j] == 10)
  265.                         manh = manh + Math.abs(i - 2) + Math.abs(j - 1);
  266.                     else if(config[i][j] == 11)
  267.                         manh = manh + Math.abs(i - 2) + Math.abs(j - 2);
  268.                     else if(config[i][j] == 12)
  269.                         manh = manh + Math.abs(i - 2) + Math.abs(j - 3);
  270.                     else if(config[i][j] == 13)
  271.                         manh = manh + Math.abs(i - 3) + Math.abs(j);
  272.                     else if(config[i][j] == 14)
  273.                         manh = manh + Math.abs(i - 3) + Math.abs(j - 1);
  274.                     else if(config[i][j] == 15)
  275.                         manh = manh + Math.abs(i - 3) + Math.abs(j - 2);
  276.                     else;
  277.                     }
  278.                 }
  279.             return manh;
  280.             }
  281.        
  282.         }
  283.    
  284.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement