Advertisement
Guest User

State.java

a guest
May 17th, 2021
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 13.29 KB | None | 0 0
  1. //  Sokoban brute solver.
  2. //  2021, May, B@R5uk
  3. //  Discussion: https://dxdy.ru/topic144781.html
  4.  
  5. import java.util.*;
  6.  
  7. public class State implements Comparable <State> {
  8.    
  9.     private static int activeCellsNumber, arraySize;
  10.     private static short [] cellsAdjValues;
  11.     private static int   [] cellsAdjIndices, lastEqual1, lastEqual2;
  12.     private static SortedSet <int []> flagsCollection;
  13.     private static List <State> stateList;
  14.    
  15.     private short porterCell, move, moveCount, pushCount;
  16.     private int [] cellFlags;
  17.     private State previousState;
  18.     int pathCount;
  19.     private boolean obsolete, expanded;
  20.    
  21.     public static void init (CellsAdjacency cellsAdjacency) {
  22.        
  23.         activeCellsNumber = cellsAdjacency .getActiveCellsNumber ();
  24.         arraySize = (activeCellsNumber >> 5) + (0 == (activeCellsNumber & 31) ? 0 : 1);
  25.         cellsAdjValues  = cellsAdjacency .getValues ();
  26.         cellsAdjIndices = cellsAdjacency .getIndices ();
  27.         lastEqual1 = null;
  28.         lastEqual2 = null;
  29.         flagsCollection = new TreeSet   <> (new ArrayComparator ());
  30.         stateList       = new ArrayList <> ();
  31.     }
  32.    
  33.     public State (short porterCell, short [] stateCells) {
  34.         int k, cell;
  35.        
  36.         this .porterCell = porterCell;
  37.         move = Short .MIN_VALUE;
  38.         moveCount = 0;
  39.         pushCount = 0;
  40.         cellFlags = new int [arraySize];
  41.        
  42.         for (k = 0; stateCells .length > k; ++k) {
  43.             cell = stateCells [k];
  44.             cellFlags [cell >> 5] |= 1 << (cell & 31);
  45.         }
  46.         if (flagsCollection .isEmpty ()) {
  47.             flagsCollection .add (cellFlags);
  48.         } else {
  49.             cellFlags = checkMasksCollection (cellFlags);
  50.         }
  51.         previousState = null;
  52.         pathCount = 1;
  53.         obsolete = false;
  54.         expanded = false;
  55.     }
  56.    
  57.     public State getPreviousState () {
  58.         return previousState;
  59.     }
  60.    
  61.     public short getMove () {
  62.         return move;
  63.     }
  64.    
  65.     public boolean isSamePlacementAs (State state) {
  66.         return cellFlags == state .cellFlags;
  67.     }
  68.    
  69.     public static int getPlacementCount () {
  70.         return flagsCollection .size ();
  71.     }
  72.    
  73.     public short getMoveCount () {
  74.         return moveCount;
  75.     }
  76.    
  77.     public short getPushCount () {
  78.         return pushCount;
  79.     }
  80.    
  81.     public short getPorterCell () {
  82.         return porterCell;
  83.     }
  84.    
  85.     public short [] getStateCells () {
  86.         int k, value, mask;
  87.         short cell;
  88.         ArrayList <Short> cellsList = new ArrayList <> ();
  89.         short [] result;
  90.        
  91.         cell = 0;
  92.         for (k = 0; arraySize > k; ++k) {
  93.             value = cellFlags [k];
  94.             for (mask = 1; 0 != mask; mask <<= 1, ++cell) {
  95.                 if (0 != (value & mask)) {
  96.                     cellsList .add (cell);
  97.                 }
  98.             }
  99.         }
  100.        
  101.         value = cellsList .size ();
  102.         result = new short [value];
  103.        
  104.         for (k = 0; value > k; ++k) {
  105.             result [k] = cellsList .get (k);
  106.         }
  107.        
  108.         return result;
  109.     }
  110.    
  111.     public void updatePathCountWith (State state) {
  112.         if (expanded) {
  113.             throw new IllegalArgumentException ("\n\nImpossible error: expanded state was updated.\n");
  114.         }
  115.         pathCount += state .pathCount;
  116.         if (0 > pathCount) {
  117.             pathCount = Integer .MAX_VALUE;
  118.         }
  119.     }
  120.    
  121.     public int getPathCount () {
  122.         return pathCount;
  123.     }
  124.    
  125.     public State selectRandomState (State state, Random rng) {
  126.         State result;
  127.         if (expanded || state .expanded) {
  128.             throw new IllegalArgumentException ("\n\nImpossible error: expanded state was updated.\n");
  129.         }
  130.         pathCount += state .pathCount;
  131.         if (0 > pathCount) {
  132.             pathCount = Integer .MAX_VALUE;
  133.             if (0 == rng .nextInt (2)) {
  134.                 result = state;
  135.             } else {
  136.                 result = this;
  137.             }
  138.         } else {
  139.             if (state .pathCount > rng .nextInt (pathCount)) {
  140.                 result = state;
  141.             } else {
  142.                 result = this;
  143.             }
  144.         }
  145.         state .pathCount = pathCount;
  146.         return result;
  147.     }
  148.    
  149.     public void markObsolete () {
  150.         if (expanded) {
  151.             throw new IllegalArgumentException ("\n\nImpossible error: expanded state was updated.\n");
  152.         }
  153.         obsolete = true;
  154.     }
  155.    
  156.     public boolean isObsolete () {
  157.         return obsolete;
  158.     }
  159.    
  160.     public boolean isExpanded () {
  161.         return expanded;
  162.     }
  163.    
  164.     private State (short porterCell, short move, short moveCount, short pushCount,
  165.                                 int [] cellFlags, State previousState, int pathCount) {
  166.         this .porterCell    = porterCell;
  167.         this .move          = move;
  168.         this .moveCount     = moveCount;
  169.         this .pushCount     = pushCount;
  170.         this .cellFlags     = cellFlags;
  171.         this .previousState = previousState;
  172.         this .pathCount     = pathCount;
  173.         obsolete = false;
  174.         expanded = false;
  175.     }
  176.    
  177.     public State [] expandForth () {
  178.         int positionIndex, indexLimit;
  179.         int maskAdress_1, cllFlgMask_1, flagsValue_1;
  180.         int maskAdress_2, cllFlgMask_2, flagsValue_2;
  181.         short move, cell_1, cell_2;
  182.         int [] newCellFlags;
  183.        
  184.         expanded = true;
  185.        
  186.         stateList .clear ();
  187.         positionIndex = cellsAdjIndices [porterCell];
  188.         indexLimit    = cellsAdjIndices [porterCell + 1];
  189.        
  190.         while (indexLimit > positionIndex) {
  191.             move   = cellsAdjValues [positionIndex];
  192.             ++positionIndex;
  193.             cell_1 = cellsAdjValues [positionIndex];
  194.             if (activeCellsNumber <= cell_1) {
  195.                 positionIndex += 3;
  196.                 stateList .add (new State (
  197.                         cell_1, move,
  198.                         (short) (moveCount + 1), pushCount, cellFlags, this, pathCount));
  199.                 continue;
  200.             }
  201.             maskAdress_1 = cell_1 >> 5;
  202.             cllFlgMask_1 = 1 << (cell_1 & 31);
  203.             flagsValue_1 = cellFlags [maskAdress_1];
  204.             if (0 == (flagsValue_1 & cllFlgMask_1)) {
  205.                 positionIndex += 3;
  206.                 stateList .add (new State (
  207.                         cell_1, move,
  208.                         (short) (moveCount + 1), pushCount, cellFlags, this, pathCount));
  209.                 continue;
  210.             }
  211.             ++positionIndex;
  212.             cell_2 = cellsAdjValues [positionIndex];
  213.             positionIndex += 2;
  214.             if (0 > cell_2) {
  215.                 continue;
  216.             }
  217.             maskAdress_2 = cell_2 >> 5;
  218.             cllFlgMask_2   = 1 << (cell_2 & 31);
  219.             if (maskAdress_1 == maskAdress_2) {
  220.                 if (0 != (flagsValue_1 & cllFlgMask_2)) {
  221.                     continue;
  222.                 }
  223.                 newCellFlags = Arrays .copyOf (cellFlags, arraySize);
  224.                 newCellFlags [maskAdress_1] = flagsValue_1 ^ cllFlgMask_1 ^ cllFlgMask_2;
  225.             } else {
  226.                 flagsValue_2 = cellFlags [maskAdress_2];
  227.                 if (0 != (flagsValue_2 & cllFlgMask_2)) {
  228.                     continue;
  229.                 }
  230.                 newCellFlags = Arrays .copyOf (cellFlags, arraySize);
  231.                 newCellFlags [maskAdress_1] = flagsValue_1 ^ cllFlgMask_1;
  232.                 newCellFlags [maskAdress_2] = flagsValue_2 ^ cllFlgMask_2;
  233.             }
  234.             stateList .add (new State (
  235.                     cell_1, (short) (-move - 1),
  236.                     (short) (moveCount + 1),
  237.                     (short) (pushCount + 1), checkMasksCollection (newCellFlags), this, pathCount));
  238.         }
  239.        
  240.         return stateList .toArray (new State [stateList .size ()]);
  241.     }
  242.    
  243.     public State [] expandBack () {
  244.         int positionIndex, indexLimit;
  245.         int maskAdress_1, cllFlgMask_1, flagsValue_1;
  246.         int maskAdress_2, cllFlgMask_2, flagsValue_2;
  247.         int maskAdress_3, cllFlgMask_3;
  248.         short move, cell_1, cell_2;
  249.         int [] newCellFlags;
  250.        
  251.         expanded = true;
  252.        
  253.         stateList .clear ();
  254.         positionIndex = cellsAdjIndices [porterCell];
  255.         indexLimit    = cellsAdjIndices [porterCell + 1];
  256.        
  257.         while (indexLimit > positionIndex) {
  258.             move   = cellsAdjValues [positionIndex];
  259.             ++positionIndex;
  260.             cell_1 = cellsAdjValues [positionIndex];
  261.             maskAdress_1 = -1;
  262.             flagsValue_1 = 0;
  263.             if (activeCellsNumber > cell_1) {
  264.                 maskAdress_1 = cell_1 >> 5;
  265.                 cllFlgMask_1 = 1 << (cell_1 & 31);
  266.                 flagsValue_1 = cellFlags [maskAdress_1];
  267.                 if (0 != (flagsValue_1 & cllFlgMask_1)) {
  268.                     positionIndex += 3;
  269.                     continue;
  270.                 }
  271.             }
  272.             stateList .add (new State (
  273.                     cell_1, move,
  274.                     (short) (moveCount + 1), pushCount, cellFlags, this, pathCount));
  275.             positionIndex += 2;
  276.             cell_2 = cellsAdjValues [positionIndex];
  277.             ++positionIndex;
  278.             if (0 > cell_2) {
  279.                 continue;
  280.             }
  281.             maskAdress_2 = cell_2 >> 5;
  282.             cllFlgMask_2 = 1 << (cell_2 & 31);
  283.             if (maskAdress_1 == maskAdress_2) {
  284.                 flagsValue_2 = flagsValue_1;
  285.             } else {
  286.                 flagsValue_2 = cellFlags [maskAdress_2];
  287.             }
  288.             if (0 == (flagsValue_2 & cllFlgMask_2)) {
  289.                 continue;
  290.             }
  291.             newCellFlags = Arrays .copyOf (cellFlags, arraySize);
  292.             maskAdress_3 = porterCell >> 5;
  293.             cllFlgMask_3 = 1 << (porterCell & 31);
  294.             if (maskAdress_2 == maskAdress_3) {
  295.                 newCellFlags [maskAdress_2] = flagsValue_2 ^ cllFlgMask_2 ^ cllFlgMask_3;
  296.             } else {
  297.                 newCellFlags [maskAdress_2] = flagsValue_2 ^ cllFlgMask_2;
  298.                 newCellFlags [maskAdress_3] ^=               cllFlgMask_3;
  299.             }
  300.             stateList .add (new State (
  301.                     cell_1, (short) (-move - 1),
  302.                     (short) (moveCount + 1),
  303.                     (short) (pushCount + 1), checkMasksCollection (newCellFlags), this, pathCount));
  304.         }
  305.        
  306.         return stateList .toArray (new State [stateList .size ()]);
  307.     }
  308.    
  309.     @Override
  310.     public int compareTo (State state) {
  311.         int k, value1, value2;
  312.        
  313.         if (cellFlags != state .cellFlags) {
  314.             for (k = 0; arraySize > k; ++k) {
  315.                 value1 =        cellFlags [k];
  316.                 value2 = state .cellFlags [k];
  317.                 if (value1 > value2) {
  318.                     return 1;
  319.                 }
  320.                 if (value1 < value2) {
  321.                     return -1;
  322.                 }
  323.             }
  324.         }
  325.         if (porterCell > state .porterCell) {
  326.             return 1;
  327.         }
  328.         if (porterCell < state .porterCell) {
  329.             return -1;
  330.         }
  331.         return 0;
  332.     }
  333.    
  334.     public boolean equals (State state) {
  335.        
  336.         if (porterCell != state .porterCell) {
  337.             return false;
  338.         }
  339.         if (cellFlags != state .cellFlags) {
  340.             for (int k = 0; arraySize > k; ++k) {
  341.                 if (cellFlags [k] != state .cellFlags [k]) {
  342.                     return false;
  343.                 }
  344.             }
  345.         }
  346.         return true;
  347.     }
  348.    
  349.     private static int [] checkMasksCollection (int [] newMask) {
  350.        
  351.         if (flagsCollection .contains (newMask)) {
  352.             if (newMask == lastEqual1) {
  353.                 return lastEqual2;
  354.             }
  355.             return lastEqual1;
  356.         }
  357.         flagsCollection .add (newMask);
  358.         return newMask;
  359.     }
  360.    
  361.     private static class ArrayComparator implements Comparator <int []> {
  362.  
  363.         @Override
  364.         public int compare (int [] array1, int [] array2) {
  365.             int k, value1, value2;
  366.            
  367.             for (k = 0; arraySize > k; ++k) {
  368.                 value1 = array1 [k];
  369.                 value2 = array2 [k];
  370.                 if (value1 > value2) {
  371.                     return 1;
  372.                 }
  373.                 if (value1 < value2) {
  374.                     return -1;
  375.                 }
  376.             }
  377.             lastEqual1 = array1;
  378.             lastEqual2 = array2;
  379.             return 0;
  380.         }
  381.     }
  382.    
  383.     public static class MovePriorityComparator implements Comparator <State> {
  384.  
  385.         @Override
  386.         public int compare (State state1, State state2) {
  387.             int value = state1 .moveCount - state2 .moveCount;
  388.             if (0 != value) {
  389.                 return value;
  390.             }
  391.             return state1 .pushCount - state2 .pushCount;
  392.         }
  393.        
  394.     }
  395.    
  396.     public static class PushPriorityComparator implements Comparator <State> {
  397.  
  398.         @Override
  399.         public int compare (State state1, State state2) {
  400.             int value = state1 .pushCount - state2 .pushCount;
  401.             if (0 != value) {
  402.                 return value;
  403.             }
  404.             return state1 .moveCount - state2 .moveCount;
  405.         }
  406.        
  407.     }
  408. }
  409.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement