Advertisement
Guest User

Untitled

a guest
Dec 22nd, 2022
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.67 KB | None | 0 0
  1. public static boolean isInMapBounds(String[] map, Point p)
  2. {
  3. return Utilities.isInBounds(map, p.y, p.x) && map[p.y].charAt(p.x) != ' ';
  4. }
  5.  
  6. public static class MapState
  7. {
  8. public static final int[] RIGHT_FACE = {2, 0, 3, 1};
  9. public static final int[] TURN_RIGHT = {3, 0, 1, 2};
  10. public static final int[] TURN_LEFT = {1, 2, 3, 0};
  11.  
  12. public final int[] permutation;
  13. public final Point p;
  14.  
  15. public MapState(int[] permutation, Point p)
  16. {
  17. this.permutation = permutation.clone();
  18. this.p = (Point) p.clone();
  19. }
  20.  
  21. public MapState moveForward()
  22. {
  23. Point newPoint = new Point(p);
  24. int[] newPerm = permutation.clone();
  25. if (++newPoint.x == MAP_SIZE)
  26. {
  27. newPoint.x = 0;
  28. newPerm = compose(permutation, RIGHT_FACE);
  29. }
  30. return new MapState(newPerm, newPoint);
  31. }
  32.  
  33. public MapState turnRight()
  34. {
  35. Point newPoint = new Point();
  36. newPoint.x = p.y;
  37. newPoint.y = MAP_SIZE - 1 - p.x;
  38.  
  39. int[] newPerm = compose(permutation, TURN_RIGHT);
  40.  
  41. return new MapState(newPerm, newPoint);
  42. }
  43.  
  44. public MapState turnLeft()
  45. {
  46. Point newPoint = new Point();
  47. newPoint.x = MAP_SIZE - 1 - p.y;
  48. newPoint.y = p.x;
  49.  
  50. int[] newPerm = compose(permutation, TURN_LEFT);
  51.  
  52. return new MapState(newPerm, newPoint);
  53. }
  54.  
  55. @Override
  56. public boolean equals(Object obj)
  57. {
  58. if (!(obj instanceof MapState))
  59. return false;
  60. MapState ms = (MapState) obj;
  61. return Arrays.equals(permutation, ms.permutation) && p.equals(ms.p);
  62. }
  63.  
  64. public static int[] compose(int[]... perms)
  65. {
  66. int[] newPerm = new int[4];
  67. for (int i = 0; i < 4; i++)
  68. {
  69. int image = i;
  70. for (int j = perms.length - 1; j >= 0; j--)
  71. image = perms[j][image];
  72. newPerm[i] = image;
  73. }
  74. return newPerm;
  75. }
  76. }
  77.  
  78. public static final int MAP_SIZE = 50;
  79.  
  80. @Override
  81. public Object partTwo(InputStream input) throws IOException
  82. {
  83. String[] map;
  84. String instructions;
  85. try (Scanner in = new Scanner(input))
  86. {
  87. in.useDelimiter("\n\n");
  88. map = in.next().split("\n");
  89. instructions = in.next();
  90. }
  91.  
  92. // Find start location
  93. Point start = new Point();
  94. while (map[0].charAt(start.x) == ' ')
  95. start.x++;
  96.  
  97. // Find a representation of each side
  98. MapState[] sides = new MapState[6];
  99. sides[0] = new MapState(new int[] {0, 1, 2, 3}, start);
  100. int nextSide = 1;
  101. for (int i = 0; nextSide < 6; i++)
  102. {
  103. Point up = new Point(sides[i].p.x, sides[i].p.y - MAP_SIZE);
  104. if (isInMapBounds(map, up))
  105. {
  106. int[] newPerm = MapState.compose(sides[i].permutation, MapState.TURN_LEFT, MapState.RIGHT_FACE, MapState.TURN_RIGHT);
  107. MapState newState = new MapState(newPerm, up);
  108. if (!Arrays.stream(sides).anyMatch(newState::equals))
  109. sides[nextSide++] = newState;
  110. }
  111.  
  112. Point down = new Point(sides[i].p.x, sides[i].p.y + MAP_SIZE);
  113. if (isInMapBounds(map, down))
  114. {
  115. int[] newPerm = MapState.compose(sides[i].permutation, MapState.TURN_RIGHT, MapState.RIGHT_FACE, MapState.TURN_LEFT);
  116. MapState newState = new MapState(newPerm, down);
  117. if (!Arrays.stream(sides).anyMatch(newState::equals))
  118. sides[nextSide++] = newState;
  119. }
  120.  
  121. Point left = new Point(sides[i].p.x - MAP_SIZE, sides[i].p.y);
  122. if (isInMapBounds(map, left))
  123. {
  124. int[] newPerm = MapState.compose(sides[i].permutation, MapState.TURN_LEFT, MapState.TURN_LEFT,
  125. MapState.RIGHT_FACE, MapState.TURN_RIGHT, MapState.TURN_RIGHT);
  126. MapState newState = new MapState(newPerm, left);
  127. if (!Arrays.stream(sides).anyMatch(newState::equals))
  128. sides[nextSide++] = newState;
  129. }
  130.  
  131. Point right = new Point(sides[i].p.x + MAP_SIZE, sides[i].p.y);
  132. if (isInMapBounds(map, right))
  133. {
  134. int[] newPerm = MapState.compose(sides[i].permutation, MapState.RIGHT_FACE);
  135. MapState newState = new MapState(newPerm, right);
  136. if (!Arrays.stream(sides).anyMatch(newState::equals))
  137. sides[nextSide++] = newState;
  138. }
  139. }
  140.  
  141. // construct the map
  142. Map<String, boolean[][]> cube = new Hashtable<>();
  143. for (int i = 0; i < 6; i++)
  144. {
  145. boolean[][] thisFace = new boolean[MAP_SIZE][MAP_SIZE];
  146. for (int j = 0; j < MAP_SIZE; j++)
  147. for (int k = 0; k < MAP_SIZE; k++)
  148. thisFace[j][k] = map[j + sides[i].p.y].charAt(k + sides[i].p.x) == '#';
  149. int[] perm = sides[i].permutation;
  150.  
  151. cube.put(Arrays.toString(perm), thisFace);
  152. for (int j = 0; j < 3; j++)
  153. {
  154. boolean[][] newFace = new boolean[MAP_SIZE][MAP_SIZE];
  155. for (int k = 0; k < MAP_SIZE; k++)
  156. for (int l = 0; l < MAP_SIZE; l++)
  157. newFace[k][l] = thisFace[l][MAP_SIZE - 1 - k];
  158. thisFace = newFace;
  159. perm = MapState.compose(perm, MapState.TURN_RIGHT);
  160. cube.put(Arrays.toString(perm), thisFace);
  161. }
  162. }
  163.  
  164. // follow instructions
  165. Matcher m = Pattern.compile("(\\d+)([LR]|$)").matcher(instructions);
  166. MapState position = new MapState(new int[] {0, 1, 2, 3}, new Point());
  167. while (m.find())
  168. {
  169. int steps = Integer.parseInt(m.group(1));
  170. for (int i = 0; i < steps; i++)
  171. {
  172. MapState newPos = position.moveForward();
  173. if (cube.get(Arrays.toString(newPos.permutation))[newPos.p.y][newPos.p.x])
  174. break;
  175. position = newPos;
  176. }
  177.  
  178. switch (m.group(2))
  179. {
  180. case "R":
  181. position = position.turnRight();
  182. break;
  183. case "L":
  184. position = position.turnLeft();
  185. break;
  186. }
  187. }
  188.  
  189. // find the original rotation
  190. int i, dir = 0;
  191. w: while (true)
  192. {
  193. for (i = 0; i < 6; i++)
  194. if (Arrays.equals(sides[i].permutation, position.permutation))
  195. break w;
  196.  
  197. position = position.turnLeft();
  198. dir++;
  199. }
  200.  
  201. return (position.p.y + sides[i].p.y) * 1000 + (position.p.x + sides[i].p.x) * 4 + dir + 1004;
  202. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement