Last active
December 25, 2020 04:22
-
-
Save PulseBeat02/2d37d80662c7ec88ace49748dba8c060 to your computer and use it in GitHub Desktop.
LobbyLayout.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.github.pulsebeat02; | |
| import java.io.BufferedReader; | |
| import java.io.FileReader; | |
| import java.io.IOException; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.HashMap; | |
| import java.util.HashSet; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.Objects; | |
| import java.util.Set; | |
| public class LobbyLayout { | |
| public static void main(String[] args) throws IOException { | |
| BufferedReader br = new BufferedReader(new FileReader("lobbylayout.txt")); | |
| List<List<Instruction>> instructions = new ArrayList<>(); | |
| String line = br.readLine(); | |
| while (line != null) { | |
| List<Instruction> inner = new ArrayList<>(); | |
| for (int i = 0; i < line.length(); i++) { | |
| if (line.charAt(i) == 's') { | |
| if (line.charAt(i + 1) == 'e') { | |
| inner.add(Instruction.SE); | |
| i++; | |
| } else if (line.charAt(i + 1) == 'w') { | |
| inner.add(Instruction.SW); | |
| i++; | |
| } | |
| } else if (line.charAt(i) == 'n') { | |
| if (line.charAt(i + 1) == 'e') { | |
| inner.add(Instruction.NE); | |
| i++; | |
| } else if (line.charAt(i + 1) == 'w') { | |
| inner.add(Instruction.NW); | |
| i++; | |
| } | |
| } else if (line.charAt(i) == 'e') { | |
| inner.add(Instruction.E); | |
| } else if (line.charAt(i) == 'w') { | |
| inner.add(Instruction.W); | |
| } | |
| } | |
| instructions.add(inner); | |
| line = br.readLine(); | |
| } | |
| System.out.println("Part One: " + partOne(instructions)); | |
| System.out.println("Part Two: " + partTwo(instructions)); | |
| } | |
| private static int partTwo(List<List<Instruction>> instructions) { | |
| Map<String, HexagonalTile> map = getFlippedTiles(instructions); | |
| Map<HexagonalTile, Integer> counts = new HashMap<>(); | |
| Set<HexagonalTile> livingGrid = new HashSet<>(); | |
| for (HexagonalTile tile : map.values()) { | |
| if (!tile.toggled) { | |
| livingGrid.add(tile); | |
| counts.put(tile, 1); | |
| } else { | |
| counts.put(tile, 0); | |
| } | |
| } | |
| for (int i = 0; i < 100; i++) { | |
| Map<HexagonalTile, Integer> copy = new HashMap<>(); | |
| for (HexagonalTile tile : counts.keySet()) { | |
| for (HexagonalTile adjacent : tile.getAdjacentTiles()) { | |
| for (HexagonalTile key : copy.keySet()) { | |
| if (adjacent.x == key.x && adjacent.y == key.y && adjacent.z == key.z) { | |
| copy.replace(key, copy.get(key) + 1); | |
| } | |
| } | |
| } | |
| } | |
| Set<HexagonalTile> tmp = new HashSet<>(); | |
| for (HexagonalTile tile : copy.keySet()) { | |
| if (copy.get(tile) == 2 && !livingGrid.contains(tile)) { | |
| tmp.add(tile); | |
| } | |
| } | |
| for (HexagonalTile tile : copy.keySet()) { | |
| int count = copy.get(tile); | |
| if (count == 1 || count == 2) { | |
| tmp.add(tile); | |
| } | |
| } | |
| livingGrid = tmp; | |
| } | |
| return livingGrid.size(); | |
| } | |
| private static int partOne(List<List<Instruction>> instructions) { | |
| // See: https://www.redblobgames.com/grids/hexagons/#coordinates | |
| // Cube Coordinates Implementation | |
| Map<String, HexagonalTile> tiles = getFlippedTiles(instructions); | |
| int count = 0; | |
| for (HexagonalTile tile : tiles.values()) { | |
| count += !tile.toggled ? 1 : 0; | |
| } | |
| return count; | |
| } | |
| private static Map<String, HexagonalTile> getFlippedTiles(List<List<Instruction>> instructions) { | |
| Map<String, HexagonalTile> tiles = new HashMap<>(); | |
| tiles.put("0 0 0", new HexagonalTile(0, 0, 0)); | |
| for (List<Instruction> instructionsList : instructions) { | |
| int currentX = 0; | |
| int currentY = 0; | |
| int currentZ = 0; | |
| String key = ""; | |
| for (Instruction instruction : instructionsList) { | |
| switch (instruction) { | |
| case E: | |
| currentX++; | |
| currentY--; | |
| break; | |
| case SE: | |
| currentZ++; | |
| currentY--; | |
| break; | |
| case SW: | |
| currentX--; | |
| currentZ++; | |
| break; | |
| case W: | |
| currentX--; | |
| currentY++; | |
| break; | |
| case NW: | |
| currentZ--; | |
| currentY++; | |
| break; | |
| case NE: | |
| currentX++; | |
| currentZ--; | |
| break; | |
| } | |
| key = currentX + " " + currentY + " " + currentZ; | |
| if (!tiles.containsKey(key)) { | |
| HexagonalTile tile = new HexagonalTile(currentX, currentY, currentZ); | |
| tiles.put(key, tile); | |
| } | |
| } | |
| tiles.get(key).toggled ^= true; | |
| } | |
| return tiles; | |
| } | |
| private static class HexagonalTile { | |
| private boolean toggled; | |
| private final int x; | |
| private final int y; | |
| private final int z; | |
| public HexagonalTile(int x, int y, int z) { | |
| this.toggled = true; | |
| this.x = x; | |
| this.y = y; | |
| this.z = z; | |
| } | |
| private Set<HexagonalTile> getAdjacentTiles() { | |
| return new HashSet<>(Arrays.asList( | |
| new HexagonalTile(x + 1, y - 1, z), | |
| new HexagonalTile(x, y - 1, z + 1), | |
| new HexagonalTile(x - 1, y, z + 1), | |
| new HexagonalTile(x - 1, y + 1, z), | |
| new HexagonalTile(x, y + 1, z - 1), | |
| new HexagonalTile(x + 1, y, z - 1) | |
| )); | |
| } | |
| @Override | |
| public int hashCode() { | |
| return Objects.hash(x, y, z); | |
| } | |
| @Override | |
| public boolean equals(Object obj) { | |
| if (!(obj instanceof HexagonalTile)) { | |
| return false; | |
| } | |
| HexagonalTile tile = (HexagonalTile) obj; | |
| if (tile.x == x && tile.y == y && tile.z == z) { | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| } | |
| } | |
| private enum Instruction { | |
| E, SE, SW, W, NW, NE | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment