From 5657b04bcb40f146a12e9a6f82aa42377f9196c2 Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 22 Dec 2024 08:13:46 +0100 Subject: [PATCH 01/13] feat: solve day 21 WIP --- .../flashk/day21/DirectionalKeypad.java | 79 ++++++++ .../flashk/day21/KeypadConundrum.java | 49 +++++ .../com/adventofcode/flashk/day21/Numpad.java | 182 ++++++++++++++++++ .../adventofcode/flashk/day21/PadEdge.java | 15 ++ .../adventofcode/flashk/day21/Day21Test.java | 8 +- .../flashk/day21/DirectionalKeypadTest.java | 108 +++++++++++ .../adventofcode/flashk/day21/NumpadTest.java | 43 +++++ src/test/resources/inputs | 2 +- 8 files changed, 483 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/adventofcode/flashk/day21/DirectionalKeypad.java create mode 100644 src/main/java/com/adventofcode/flashk/day21/KeypadConundrum.java create mode 100644 src/main/java/com/adventofcode/flashk/day21/Numpad.java create mode 100644 src/main/java/com/adventofcode/flashk/day21/PadEdge.java create mode 100644 src/test/java/com/adventofcode/flashk/day21/DirectionalKeypadTest.java create mode 100644 src/test/java/com/adventofcode/flashk/day21/NumpadTest.java diff --git a/src/main/java/com/adventofcode/flashk/day21/DirectionalKeypad.java b/src/main/java/com/adventofcode/flashk/day21/DirectionalKeypad.java new file mode 100644 index 0000000..22bbb06 --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/DirectionalKeypad.java @@ -0,0 +1,79 @@ +package com.adventofcode.flashk.day21; + +import lombok.Setter; +import org.jgrapht.Graph; +import org.jgrapht.GraphPath; +import org.jgrapht.alg.shortestpath.DijkstraShortestPath; +import org.jgrapht.graph.DirectedMultigraph; + + +public class DirectionalKeypad { + + public static final Character UP = '^'; + public static final Character DOWN = 'v'; + public static final Character LEFT = '<'; + public static final Character RIGHT = '>'; + public static final Character ACCEPT = 'A'; + public static final String ACCEPT_TO_LEFT = "v<<"; + public static final String LEFT_TO_ACCEPT = "^>>"; + public static final String DOWN_TO_ACCEPT = ">^"; + + private Graph graph = new DirectedMultigraph<>(PadEdge.class); + private DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath<>(graph); + + @Setter + private Character currentKey = ACCEPT; + + public DirectionalKeypad() { + graph.addVertex(LEFT); + graph.addVertex(DOWN); + graph.addVertex(UP); + graph.addVertex(RIGHT); + graph.addVertex(ACCEPT); + + graph.addEdge(LEFT, DOWN, new PadEdge(RIGHT)); + graph.addEdge(LEFT,ACCEPT, new PadEdge(LEFT_TO_ACCEPT)); + + graph.addEdge(DOWN, LEFT, new PadEdge(LEFT)); + graph.addEdge(DOWN, UP, new PadEdge(UP)); + graph.addEdge(DOWN, RIGHT, new PadEdge(RIGHT)); + graph.addEdge(DOWN, ACCEPT, new PadEdge(DOWN_TO_ACCEPT)); + + graph.addEdge(UP, DOWN, new PadEdge(DOWN)); + graph.addEdge(UP, ACCEPT, new PadEdge(RIGHT)); + + graph.addEdge(RIGHT, DOWN, new PadEdge(LEFT)); + graph.addEdge(RIGHT, ACCEPT, new PadEdge(UP)); + + graph.addEdge(ACCEPT, UP, new PadEdge(LEFT)); + graph.addEdge(ACCEPT, RIGHT, new PadEdge(DOWN)); + graph.addEdge(ACCEPT, LEFT, new PadEdge(ACCEPT_TO_LEFT)); // new + + } + + /// Enters a code, such as `029A`, returning a [String] representing the needed moves for it. + /// @param code the code to enter. + /// @return The String that represents the performed movements to enter that code at the numpad. + public String press(String code) { + char[] buttons = code.toCharArray(); + + StringBuilder sb = new StringBuilder(); + for(char button : buttons) { + sb.append(press(button)); + } + + return sb.toString(); + } + + private String press(char button) { + + GraphPath path = dijkstraShortestPath.getPath(currentKey, button); + StringBuilder sb = new StringBuilder(); + for(PadEdge edge : path.getEdgeList()) { + sb.append(edge.label()); + } + sb.append(ACCEPT); + currentKey = button; + return sb.toString(); + } +} diff --git a/src/main/java/com/adventofcode/flashk/day21/KeypadConundrum.java b/src/main/java/com/adventofcode/flashk/day21/KeypadConundrum.java new file mode 100644 index 0000000..435d794 --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/KeypadConundrum.java @@ -0,0 +1,49 @@ +package com.adventofcode.flashk.day21; + + +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +public class KeypadConundrum { + + private Numpad numpadRobot = new Numpad(); + private List directionalKeypads = new ArrayList<>(); + + private List codes; + + public KeypadConundrum(List inputs) { + codes = inputs; + } + + public long solveA() { + + long result = 0; + directionalKeypads.add(new DirectionalKeypad()); + directionalKeypads.add(new DirectionalKeypad()); + + + for(String code : codes) { + result += press(code); + } + + return result; + } + + private long press(String code) { + String movements = numpadRobot.press(code); + String directionalMovements = StringUtils.EMPTY; + + for(DirectionalKeypad directionalKeypad : directionalKeypads) { + + directionalMovements = directionalKeypad.press(movements); + movements = directionalMovements; + } + + long shortestSequenceLength = directionalMovements.length(); + long numericValue = Long.parseLong(code.replace("A", StringUtils.EMPTY)); + + return shortestSequenceLength * numericValue; + } +} diff --git a/src/main/java/com/adventofcode/flashk/day21/Numpad.java b/src/main/java/com/adventofcode/flashk/day21/Numpad.java new file mode 100644 index 0000000..07d5a4e --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/Numpad.java @@ -0,0 +1,182 @@ +package com.adventofcode.flashk.day21; + +import org.jgrapht.Graph; +import org.jgrapht.GraphPath; +import org.jgrapht.alg.shortestpath.DijkstraShortestPath; + +import org.jgrapht.graph.DirectedMultigraph; +import org.jgrapht.graph.DirectedWeightedMultigraph; + +import java.util.List; + +public class Numpad { + + public static final Character BUTTON_0 = '0'; + public static final Character BUTTON_1 = '1'; + public static final Character BUTTON_2 = '2'; + public static final Character BUTTON_3 = '3'; + public static final Character BUTTON_4 = '4'; + public static final Character BUTTON_5 = '5'; + public static final Character BUTTON_6 = '6'; + public static final Character BUTTON_7 = '7'; + public static final Character BUTTON_8 = '8'; + public static final Character BUTTON_9 = '9'; + public static final Character ACCEPT = 'A'; + private static final String BUTTON_2_TO_BUTTON_9 = ">^^"; + private static final String BUTTON_9_TO_BUTTON_2 = "vv<"; + + private Graph graph = new DirectedWeightedMultigraph<>(PadEdge.class); + + private DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath<>(graph); + + private Character currentKey = ACCEPT; + + public Numpad() { + + graph.addVertex(BUTTON_0); + graph.addVertex(BUTTON_1); + graph.addVertex(BUTTON_2); + graph.addVertex(BUTTON_3); + graph.addVertex(BUTTON_4); + graph.addVertex(BUTTON_5); + graph.addVertex(BUTTON_6); + graph.addVertex(BUTTON_7); + graph.addVertex(BUTTON_8); + graph.addVertex(BUTTON_9); + graph.addVertex(ACCEPT); + + + // TODO problema con los ejes + // Labeled edges in multigraph MUST BE unique, so an String or Character is not enough: + // https://jgrapht.org/guide/VertexAndEdgeTypes#labeled-edges-in-a-multigraph + + // modelar ejes con un record único. + + + // cada eje debería tener un nombre único + PadEdge padEdge; + + graph.addEdge(BUTTON_0, BUTTON_2, new PadEdge(DirectionalKeypad.UP)); + graph.setEdgeWeight(BUTTON_0, BUTTON_2, 2); + + graph.addEdge(BUTTON_0, ACCEPT, new PadEdge(DirectionalKeypad.RIGHT)); + graph.setEdgeWeight(BUTTON_0, ACCEPT, 1); + + graph.addEdge(BUTTON_1, BUTTON_2, new PadEdge(DirectionalKeypad.RIGHT)); + graph.setEdgeWeight(BUTTON_1, BUTTON_2, 2); + + graph.addEdge(BUTTON_1, BUTTON_4, new PadEdge(DirectionalKeypad.UP)); + graph.setEdgeWeight(BUTTON_1, BUTTON_4, 3); + + graph.addEdge(BUTTON_2, BUTTON_0, new PadEdge(DirectionalKeypad.DOWN)); + graph.setEdgeWeight(BUTTON_2, BUTTON_0, 2); + + graph.addEdge(BUTTON_2, BUTTON_1, new PadEdge(DirectionalKeypad.LEFT)); + graph.setEdgeWeight(BUTTON_2, BUTTON_1, 3); + + graph.addEdge(BUTTON_2, BUTTON_3, new PadEdge(DirectionalKeypad.RIGHT)); + graph.setEdgeWeight(BUTTON_2, BUTTON_3, 1); + + graph.addEdge(BUTTON_2, BUTTON_5, new PadEdge(DirectionalKeypad.UP)); + graph.setEdgeWeight(BUTTON_2, BUTTON_5, 2); + + graph.addEdge(BUTTON_3, BUTTON_2, new PadEdge(DirectionalKeypad.LEFT)); + graph.setEdgeWeight(BUTTON_3, BUTTON_2, 2); + + graph.addEdge(BUTTON_3, BUTTON_6, new PadEdge(DirectionalKeypad.UP)); + graph.setEdgeWeight(BUTTON_3, BUTTON_6, 1); + + graph.addEdge(BUTTON_3, ACCEPT, new PadEdge(DirectionalKeypad.DOWN)); + graph.setEdgeWeight(BUTTON_3, ACCEPT, 1); + + graph.addEdge(BUTTON_4, BUTTON_1, new PadEdge(DirectionalKeypad.DOWN)); + graph.setEdgeWeight(BUTTON_4, BUTTON_1, 3); + + graph.addEdge(BUTTON_4, BUTTON_5, new PadEdge(DirectionalKeypad.RIGHT)); + graph.setEdgeWeight(BUTTON_4, BUTTON_5, 2); + + graph.addEdge(BUTTON_4, BUTTON_7, new PadEdge(DirectionalKeypad.UP)); + graph.setEdgeWeight(BUTTON_4, BUTTON_7, 3); + + graph.addEdge(BUTTON_5, BUTTON_2, new PadEdge(DirectionalKeypad.DOWN)); + graph.setEdgeWeight(BUTTON_5, BUTTON_2, 2); + + graph.addEdge(BUTTON_5, BUTTON_4, new PadEdge(DirectionalKeypad.LEFT)); + graph.setEdgeWeight(BUTTON_5, BUTTON_4, 3); + + graph.addEdge(BUTTON_5, BUTTON_6, new PadEdge(DirectionalKeypad.RIGHT)); + graph.setEdgeWeight(BUTTON_5, BUTTON_6, 1); + + graph.addEdge(BUTTON_5, BUTTON_8, new PadEdge(DirectionalKeypad.UP)); + graph.setEdgeWeight(BUTTON_5, BUTTON_8, 2); + + graph.addEdge(BUTTON_6, BUTTON_3, new PadEdge(DirectionalKeypad.DOWN)); + graph.setEdgeWeight(BUTTON_6, BUTTON_3, 1); + + graph.addEdge(BUTTON_6, BUTTON_5, new PadEdge(DirectionalKeypad.LEFT)); + graph.setEdgeWeight(BUTTON_6, BUTTON_5, 2); + + graph.addEdge(BUTTON_6, BUTTON_9, new PadEdge(DirectionalKeypad.UP)); + graph.setEdgeWeight(BUTTON_6, BUTTON_9, 1); + + graph.addEdge(BUTTON_7, BUTTON_4, new PadEdge(DirectionalKeypad.DOWN)); + graph.setEdgeWeight(BUTTON_7, BUTTON_4, 3); + + graph.addEdge(BUTTON_7, BUTTON_8, new PadEdge(DirectionalKeypad.RIGHT)); + graph.setEdgeWeight(BUTTON_7, BUTTON_8, 2); + + graph.addEdge(BUTTON_8, BUTTON_5, new PadEdge(DirectionalKeypad.DOWN)); + graph.setEdgeWeight(BUTTON_8, BUTTON_5, 2); + + graph.addEdge(BUTTON_8, BUTTON_7, new PadEdge(DirectionalKeypad.LEFT)); + graph.setEdgeWeight(BUTTON_8, BUTTON_7, 3); + + graph.addEdge(BUTTON_8, BUTTON_9, new PadEdge(DirectionalKeypad.RIGHT)); + graph.setEdgeWeight(BUTTON_8, BUTTON_9, 1); + + graph.addEdge(BUTTON_9, BUTTON_6, new PadEdge(DirectionalKeypad.DOWN)); + graph.setEdgeWeight(BUTTON_9, BUTTON_6, 1); + + graph.addEdge(BUTTON_9, BUTTON_8, new PadEdge(DirectionalKeypad.LEFT)); + graph.setEdgeWeight(BUTTON_9, BUTTON_8, 2); + //graph.addEdge(BUTTON_9, BUTTON_2, new PadEdge(BUTTON_9_TO_BUTTON_2)); + + graph.addEdge(ACCEPT, BUTTON_0, new PadEdge(DirectionalKeypad.LEFT)); + graph.setEdgeWeight(ACCEPT, BUTTON_0, 1); + + graph.addEdge(ACCEPT, BUTTON_3, new PadEdge(DirectionalKeypad.UP)); + graph.setEdgeWeight(ACCEPT, BUTTON_3, 1); + + + } + + /// Enters a code, such as `029A`, returning a [String] representing the needed moves for it. + /// @param code the code to enter. + /// @return The String the instructions to be executed at a [DirectionalKeypad](DirectionalKeypad). + public String press(String code) { + char[] buttons = code.toCharArray(); + + StringBuilder sb = new StringBuilder(); + for(char button : buttons) { + sb.append(press(button)); + } + + return sb.toString(); + } + + private String press(char button) { + GraphPath path = dijkstraShortestPath.getPath(currentKey, button); + StringBuilder sb = new StringBuilder(); + for(PadEdge edge : path.getEdgeList()) { + sb.append(edge.label()); + } + sb.append(ACCEPT); + currentKey = button; + return sb.toString(); + } + + + public void reset() { + currentKey = ACCEPT; + } +} diff --git a/src/main/java/com/adventofcode/flashk/day21/PadEdge.java b/src/main/java/com/adventofcode/flashk/day21/PadEdge.java new file mode 100644 index 0000000..e978951 --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/PadEdge.java @@ -0,0 +1,15 @@ +package com.adventofcode.flashk.day21; + +public record PadEdge(String label, int id) { + + private static int idGenerator = 0; + + public PadEdge(Character label) { + this(String.valueOf(label), idGenerator++); + } + + public PadEdge(String label) { + this(label, idGenerator++); + } + +} diff --git a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java index bb077b0..e339eef 100644 --- a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java +++ b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java @@ -36,7 +36,10 @@ public void testSolvePart1Sample() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE); - assertEquals(0L,0L); + KeypadConundrum keypadConundrum = new KeypadConundrum(inputs); + + assertEquals(126384L, keypadConundrum.solveA()); + //assertEquals(0L,keypadConundrum.solveA()); } @Test @@ -49,7 +52,8 @@ public void testSolvePart1Input() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE); - System.out.println("Solution: "); + KeypadConundrum keypadConundrum = new KeypadConundrum(inputs); + System.out.println("Solution: "+keypadConundrum.solveA()); assertEquals(0L,0L); } diff --git a/src/test/java/com/adventofcode/flashk/day21/DirectionalKeypadTest.java b/src/test/java/com/adventofcode/flashk/day21/DirectionalKeypadTest.java new file mode 100644 index 0000000..992166b --- /dev/null +++ b/src/test/java/com/adventofcode/flashk/day21/DirectionalKeypadTest.java @@ -0,0 +1,108 @@ +package com.adventofcode.flashk.day21; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class DirectionalKeypadTest { + + + @Test + void pressFromAcceptTest() { + + DirectionalKeypad keypad = new DirectionalKeypad(); + + assertEquals("v<")); + + keypad.setCurrentKey(DirectionalKeypad.ACCEPT); + assertEquals("A", keypad.press("A")); + + keypad.setCurrentKey(DirectionalKeypad.UP); + assertEquals("vA", keypad.press(">")); + + keypad.setCurrentKey(DirectionalKeypad.UP); + assertEquals("vA", keypad.press("v")); + + } + + @Test + void pressFromLeftTest() { + + DirectionalKeypad keypad = new DirectionalKeypad(); + + keypad.setCurrentKey(DirectionalKeypad.LEFT); + assertEquals("^>>A", keypad.press("A")); + + keypad.setCurrentKey(DirectionalKeypad.LEFT); + assertEquals(">>A", keypad.press(">")); + + keypad.setCurrentKey(DirectionalKeypad.LEFT); + assertEquals(">^A", keypad.press("^")); + + keypad.setCurrentKey(DirectionalKeypad.LEFT); + assertEquals(">A", keypad.press("v")); + + } + + @Test + void pressFromDownToATest() { + + DirectionalKeypad keypad = new DirectionalKeypad(); + + keypad.setCurrentKey(DirectionalKeypad.DOWN); + assertEquals(">^A", keypad.press("A")); + + keypad.setCurrentKey(DirectionalKeypad.DOWN); + assertEquals("A", keypad.press(">")); + + keypad.setCurrentKey(DirectionalKeypad.DOWN); + assertEquals("^A", keypad.press("^")); + } + + @Test + void pressFromRightTest() { + + DirectionalKeypad keypad = new DirectionalKeypad(); + + keypad.setCurrentKey(DirectionalKeypad.RIGHT); + assertEquals("^A", keypad.press("A")); + + keypad.setCurrentKey(DirectionalKeypad.RIGHT); + assertEquals("< Date: Sat, 28 Dec 2024 19:22:18 +0100 Subject: [PATCH 02/13] feat: solve day 21 part 1 --- pom.xml | 6 + .../com/adventofcode/flashk/common/Input.java | 34 ++++ .../flashk/common/jgrapht/LabeledEdge.java | 34 ++++ .../flashk/day21/redesign/Key.java | 41 +++++ .../flashk/day21/redesign/Keypad.java | 152 ++++++++++++++++++ .../day21/redesign/KeypadConundrum2.java | 63 ++++++++ .../flashk/day21/redesign/KeypadPress.java | 4 + .../resources/day21/directional_mappings.txt | 10 ++ src/main/resources/day21/numpad_mappings.txt | 30 ++++ .../adventofcode/flashk/day21/Day21Test.java | 26 +-- .../adventofcode/flashk/day21/KeyTest.java | 16 ++ 11 files changed, 398 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/adventofcode/flashk/common/Input.java create mode 100644 src/main/java/com/adventofcode/flashk/common/jgrapht/LabeledEdge.java create mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/Key.java create mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java create mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java create mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/KeypadPress.java create mode 100644 src/main/resources/day21/directional_mappings.txt create mode 100644 src/main/resources/day21/numpad_mappings.txt create mode 100644 src/test/java/com/adventofcode/flashk/day21/KeyTest.java diff --git a/pom.xml b/pom.xml index 360800a..b9410d4 100644 --- a/pom.xml +++ b/pom.xml @@ -78,6 +78,12 @@ commons-math3 3.6.1 + + + com.google.guava + guava + 33.4.0-jre + org.jetbrains annotations diff --git a/src/main/java/com/adventofcode/flashk/common/Input.java b/src/main/java/com/adventofcode/flashk/common/Input.java new file mode 100644 index 0000000..6db5a24 --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/common/Input.java @@ -0,0 +1,34 @@ +package com.adventofcode.flashk.common; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public final class Input { + + private static final String PATH_INPUTS = "src/main/resources"; + + private Input() { + } + + public static List readStringLines(String inputFolder, String inputFile) { + + List input; + + try { + Path path = Paths.get(PATH_INPUTS, inputFolder, inputFile).toAbsolutePath(); + input = Files.lines(path).collect(Collectors.toList()); + + } catch (IOException e) { + input = new ArrayList<>(); + e.printStackTrace(); + } + + return input; + } + +} diff --git a/src/main/java/com/adventofcode/flashk/common/jgrapht/LabeledEdge.java b/src/main/java/com/adventofcode/flashk/common/jgrapht/LabeledEdge.java new file mode 100644 index 0000000..45d7f6b --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/common/jgrapht/LabeledEdge.java @@ -0,0 +1,34 @@ +package com.adventofcode.flashk.common.jgrapht; + +import org.jgrapht.graph.DefaultEdge; +import org.jgrapht.nio.Attribute; +import org.jgrapht.nio.AttributeType; + +/// Labeled edge class based on [JGraphT LabeledEdges](https://jgrapht.org/guide/LabeledEdges) +/// +/// Allows creating an edge with label. +/// +/// It also implements the JGraphT Attribute interface to allow exporting the labels in DOT representation +public class LabeledEdge extends DefaultEdge implements Attribute { + + private final String label; + + public LabeledEdge(String label) { + this.label = label; + } + + @Override + public String getValue() { + return label; + } + + @Override + public AttributeType getType() { + return AttributeType.STRING; + } + + @Override + public String toString() { + return "(" + getSource() + " : " + getTarget() + " : " + label + ")"; + } +} diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Key.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Key.java new file mode 100644 index 0000000..dc915ec --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/Key.java @@ -0,0 +1,41 @@ +package com.adventofcode.flashk.day21.redesign; + + +import lombok.Getter; + +public enum Key { + + NUMBER_0("0"), + NUMBER_1("1"), + NUMBER_2("2"), + NUMBER_3("3"), + NUMBER_4("4"), + NUMBER_5("5"), + NUMBER_6("6"), + NUMBER_7("7"), + NUMBER_8("8"), + NUMBER_9("9"), + ARROW_LEFT("<"), + ARROW_DOWN("v"), + ARROW_UP("^"), + ARROW_RIGHT(">"), + ACCEPT("A"); + + @Getter + private final String value; + + Key(String value) { + this.value = value; + } + + /* + public static Key getKey(String value) { + for(Key key : values()) { + if(key.getValue().equals(value)) { + return key; + } + } + throw new IllegalArgumentException("Unknown enum value for: "+value); + }*/ + +} diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java new file mode 100644 index 0000000..9d2e4d6 --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java @@ -0,0 +1,152 @@ +package com.adventofcode.flashk.day21.redesign; + +import com.adventofcode.flashk.common.Input; +import com.adventofcode.flashk.common.jgrapht.LabeledEdge; +import com.adventofcode.flashk.day25.Key; +import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; +import org.jgrapht.Graph; +import org.jgrapht.GraphPath; +import org.jgrapht.alg.shortestpath.AllDirectedPaths; +import org.jgrapht.graph.DirectedMultigraph; +import org.jgrapht.nio.dot.DOTExporter; + +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +public class Keypad { + + private static final String FILE_DIRECTIONAL_MAPPINGS = "directional_mappings.txt"; + private static final String FILE_NUMPAD_MAPPINGS = "numpad_mappings.txt"; + + private final Graph graph = new DirectedMultigraph<>(LabeledEdge.class); + private final boolean directional; + private static final Map> memo = new HashMap<>(); + + // TODO opción 2: caché a nivel de code en lugar de button + + private String currentButton = "A"; + + + public Keypad(boolean isDirectional) { + + // Create the graph using mappings files + + // Each line of the mappings files is a comma delimited list which represents: + // source_vertex,edge_label,target_vertex + + // This allows to create a complete graph based on the contents of the graph. + directional = isDirectional; + + // Read the key mappings from the file + String filename = directional ? FILE_DIRECTIONAL_MAPPINGS : FILE_NUMPAD_MAPPINGS; + List lines = Input.readStringLines("day21", filename); + + // Create the vertexes and edges described at each line + for(String line : lines) { + + String[] parts = line.split(","); + String vertexSource = parts[0]; + String edgeLabel = parts[1]; + String vertexTarget = parts[2]; + + if(!graph.containsVertex(vertexSource)) { + graph.addVertex(vertexSource); + } + + if(!graph.containsVertex(vertexTarget)) { + graph.addVertex(vertexTarget); + } + + graph.addEdge(vertexSource, vertexTarget, new LabeledEdge(edgeLabel)); + + } + + } + + /// Enters a code to be pressed at the pad returning a [String] representing the needed moves for it. + /// + /// The code can be either an alphanumeric value as such as `029A` to be pressed at a numeric pad or an + /// alphanumeric value such as `^AvvvA` to be pressed at a directional keypad. + /// + /// @param code the code to enter. + /// @return A list of possible instructions to be executed by the next robot + public Set press(String code) { + char[] buttons = code.toCharArray(); + + List> allButtonPaths = new ArrayList<>(); + for(char button : buttons) { + + if(directional) { + button = switch(button) { + case '<' -> 'L'; + case '>' -> 'R'; + case '^' -> 'U'; + case 'v' -> 'D'; + case 'A' -> 'A'; + default -> throw new IllegalStateException("Unexpected button value: " + button); + }; + } + + // Generate a memoization status for this key press + KeypadPress state = new KeypadPress(currentButton, button); + + // Obtain from memo or compute. Add it to memoization if it didn't exist. + List buttonPaths = memo.getOrDefault(state, press(button)); + memo.putIfAbsent(state, buttonPaths); + + // + allButtonPaths.add(buttonPaths); + } + + // Create all the possible path combinations + List> cartesianList = Lists.cartesianProduct(allButtonPaths); + Set paths = new HashSet<>(); + for(List possiblePaths : cartesianList) { + paths.add(String.join(StringUtils.EMPTY, possiblePaths)); + } + + return paths; + } + + /// Presses the specified button retrieving a list of minimum cost directional key presses to achieve that key press. + /// + /// @param button the button to press. + /// @return a list of different paths as String to achieve that key press from the current button position. + public List press(char button) { + AllDirectedPaths adp = new AllDirectedPaths<>(graph); + + List> graphPaths = adp.getAllPaths(currentButton, String.valueOf(button), + true,4); + + int shortestPathSize = Integer.MAX_VALUE; + + List paths = new ArrayList<>(); + for(GraphPath graphPath : graphPaths) { + String path = graphPath.getEdgeList().stream().map(LabeledEdge::getValue).collect(Collectors.joining()) + "A"; + shortestPathSize = Math.min(path.length(), shortestPathSize); + paths.add(path); + } + + this.currentButton = String.valueOf(button); + int finalShortestPathSize = shortestPathSize; + return paths.stream().filter(p -> p.length() == finalShortestPathSize).toList(); + } + + public void paint() { + + DOTExporter exporter = new DOTExporter<>(v -> v); + exporter.setEdgeAttributeProvider(e -> Map.of("label", e)); + + Writer writer = new StringWriter(); + exporter.exportGraph(graph, writer); + System.out.println(writer.toString()); + } +} diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java new file mode 100644 index 0000000..9ffb424 --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java @@ -0,0 +1,63 @@ +package com.adventofcode.flashk.day21.redesign; + + + +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; +import java.util.Set; + +public class KeypadConundrum2 { + + private List codes; + + private Deque keypads = new ArrayDeque<>(); + + public KeypadConundrum2(List inputs, int keypadsNumber) { + codes = inputs; + keypads.add(new Keypad(false)); + for(int i = 0; i < keypadsNumber; i++) { + keypads.add(new Keypad(true)); + } + } + + public long solveA() { + + long result = 0; + for(String code : codes) { + result += press(code); + } + + return result; + } + + private long press(String code) { + long shortestSequenceLength = pressCode(code); + long numericValue = Long.parseLong(code.replace("A", StringUtils.EMPTY)); + return shortestSequenceLength * numericValue; + } + + private long pressCode(String code) { + + if(keypads.isEmpty()) { + return code.length(); + } + + long shortestSequence = Long.MAX_VALUE; + + Keypad nextKeypad = keypads.pollFirst(); + + Set keyPressesList = nextKeypad.press(code); + for(String keyPresses : keyPressesList) { + long sequence = pressCode(keyPresses); + shortestSequence = Math.min(shortestSequence, sequence); + } + + keypads.addFirst(nextKeypad); + + return shortestSequence; + } + +} diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadPress.java b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadPress.java new file mode 100644 index 0000000..eca073b --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadPress.java @@ -0,0 +1,4 @@ +package com.adventofcode.flashk.day21.redesign; + +public record KeypadPress(String currentButton, char nextButton) { +} diff --git a/src/main/resources/day21/directional_mappings.txt b/src/main/resources/day21/directional_mappings.txt new file mode 100644 index 0000000..10271eb --- /dev/null +++ b/src/main/resources/day21/directional_mappings.txt @@ -0,0 +1,10 @@ +U,v,D +U,>,A +A,<,U +A,v,R +L,>,D +D,<,L +D,^,U +D,>,R +R,<,D +R,^,A \ No newline at end of file diff --git a/src/main/resources/day21/numpad_mappings.txt b/src/main/resources/day21/numpad_mappings.txt new file mode 100644 index 0000000..24ca858 --- /dev/null +++ b/src/main/resources/day21/numpad_mappings.txt @@ -0,0 +1,30 @@ +7,>,8 +7,v,4 +8,<,7 +8,>,9 +8,v,5 +9,<,8 +9,v,6 +4,^,7 +4,>,5 +4,v,1 +5,<,4 +5,^,8 +5,>,6 +5,v,2 +6,<,5 +6,^,9 +6,v,3 +1,>,2 +1,^,4 +2,<,1 +2,^,5 +2,>,3 +2,v,0 +3,<,2 +3,^,6 +3,v,A +0,>,A +0,^,2 +A,<,0 +A,^,3 \ No newline at end of file diff --git a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java index 0bfe5ce..c2fbc89 100644 --- a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java +++ b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java @@ -2,6 +2,7 @@ import java.util.List; +import com.adventofcode.flashk.day21.redesign.KeypadConundrum2; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; @@ -22,7 +23,7 @@ @DisplayName(TestDisplayName.DAY_21) @TestMethodOrder(OrderAnnotation.class) @Disabled("[Disabled] Day 21 - Work in Progress") -public class Day21Test extends PuzzleTest { +public class Day21Test { private static final String INPUT_FOLDER = TestFolder.DAY_21; @@ -36,7 +37,7 @@ public void testSolvePart1Sample() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE); - KeypadConundrum keypadConundrum = new KeypadConundrum(inputs); + KeypadConundrum2 keypadConundrum = new KeypadConundrum2(inputs, 2); assertEquals(126384L, keypadConundrum.solveA()); //assertEquals(0L,keypadConundrum.solveA()); @@ -52,23 +53,10 @@ public void testSolvePart1Input() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE); - KeypadConundrum keypadConundrum = new KeypadConundrum(inputs); - System.out.println("Solution: "+keypadConundrum.solveA()); - assertEquals(0L,0L); - - } + KeypadConundrum2 keypadConundrum = new KeypadConundrum2(inputs, 2); - @Test - @Order(3) - @Tag(TestTag.PART_2) - @Tag(TestTag.SAMPLE) - @DisplayName(TestDisplayName.PART_2_SAMPLE) - public void testSolvePart2Sample() { + assertEquals(206798L,keypadConundrum.solveA()); - // Read input file - List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE); - - assertEquals(0L,0L); } @Test @@ -81,7 +69,9 @@ public void testSolvePart2Input() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE); - System.out.println("Solution: "); + KeypadConundrum2 keypadConundrum = new KeypadConundrum2(inputs, 25); + + System.out.println("Solution: "+ keypadConundrum.solveA()); assertEquals(0L,0L); } diff --git a/src/test/java/com/adventofcode/flashk/day21/KeyTest.java b/src/test/java/com/adventofcode/flashk/day21/KeyTest.java new file mode 100644 index 0000000..746fbaa --- /dev/null +++ b/src/test/java/com/adventofcode/flashk/day21/KeyTest.java @@ -0,0 +1,16 @@ +package com.adventofcode.flashk.day21; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class KeyTest { + + @Test + void values() { + } + + @Test + void valueOf() { + } +} \ No newline at end of file From 5a77f5a1005aaffad1c4ea408b7921c7d567fc6e Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 09:36:01 +0100 Subject: [PATCH 03/13] refactor: prepare for refactor --- .../flashk/day21/redesign/CharacterPress.java | 4 ++ .../flashk/day21/redesign/CodePress.java | 4 ++ .../flashk/day21/redesign/Keypad.java | 40 ++++++++++++------- .../day21/redesign/KeypadConundrum2.java | 5 +-- .../flashk/day21/redesign/KeypadPress.java | 4 -- 5 files changed, 36 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java create mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/CodePress.java delete mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/KeypadPress.java diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java b/src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java new file mode 100644 index 0000000..435e827 --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java @@ -0,0 +1,4 @@ +package com.adventofcode.flashk.day21.redesign; + +public record CharacterPress(String currentButton, char nextButton) { +} diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/CodePress.java b/src/main/java/com/adventofcode/flashk/day21/redesign/CodePress.java new file mode 100644 index 0000000..1328b48 --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/CodePress.java @@ -0,0 +1,4 @@ +package com.adventofcode.flashk.day21.redesign; + +public record CodePress(String currentButton, String code) { +} diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java index 9d2e4d6..1fd3cbf 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java @@ -2,7 +2,6 @@ import com.adventofcode.flashk.common.Input; import com.adventofcode.flashk.common.jgrapht.LabeledEdge; -import com.adventofcode.flashk.day25.Key; import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; import org.jgrapht.Graph; @@ -28,7 +27,8 @@ public class Keypad { private final Graph graph = new DirectedMultigraph<>(LabeledEdge.class); private final boolean directional; - private static final Map> memo = new HashMap<>(); + private static final Map> memo = new HashMap<>(); + private static final Map> memoCode = new HashMap<>(); // TODO opción 2: caché a nivel de code en lugar de button @@ -79,24 +79,16 @@ public Keypad(boolean isDirectional) { /// @param code the code to enter. /// @return A list of possible instructions to be executed by the next robot public Set press(String code) { + char[] buttons = code.toCharArray(); List> allButtonPaths = new ArrayList<>(); for(char button : buttons) { - if(directional) { - button = switch(button) { - case '<' -> 'L'; - case '>' -> 'R'; - case '^' -> 'U'; - case 'v' -> 'D'; - case 'A' -> 'A'; - default -> throw new IllegalStateException("Unexpected button value: " + button); - }; - } + button = mapDirectionalButton(button); // Generate a memoization status for this key press - KeypadPress state = new KeypadPress(currentButton, button); + CharacterPress state = new CharacterPress(currentButton, button); // Obtain from memo or compute. Add it to memoization if it didn't exist. List buttonPaths = memo.getOrDefault(state, press(button)); @@ -107,6 +99,11 @@ public Set press(String code) { } // Create all the possible path combinations + + // TODO java.lang.IllegalArgumentException: Cartesian product too large; must have size at most Integer.MAX_VALUE + // TODO con 33 elementos en la lista con tamaño mínimo 2 se intenta generar una lista con 2^3 = 8589934592 items + + List> cartesianList = Lists.cartesianProduct(allButtonPaths); Set paths = new HashSet<>(); for(List possiblePaths : cartesianList) { @@ -116,6 +113,21 @@ public Set press(String code) { return paths; } + private char mapDirectionalButton(char button) { + if(directional) { + return switch(button) { + case '<' -> 'L'; + case '>' -> 'R'; + case '^' -> 'U'; + case 'v' -> 'D'; + case 'A' -> 'A'; + default -> throw new IllegalStateException("Unexpected button value: " + button); + }; + } + + return button; + } + /// Presses the specified button retrieving a list of minimum cost directional key presses to achieve that key press. /// /// @param button the button to press. @@ -127,7 +139,7 @@ public List press(char button) { true,4); int shortestPathSize = Integer.MAX_VALUE; - + List paths = new ArrayList<>(); for(GraphPath graphPath : graphPaths) { String path = graphPath.getEdgeList().stream().map(LabeledEdge::getValue).collect(Collectors.joining()) + "A"; diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java index 9ffb424..a947e01 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java @@ -11,9 +11,8 @@ public class KeypadConundrum2 { - private List codes; - - private Deque keypads = new ArrayDeque<>(); + private final List codes; + private final Deque keypads = new ArrayDeque<>(); public KeypadConundrum2(List inputs, int keypadsNumber) { codes = inputs; diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadPress.java b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadPress.java deleted file mode 100644 index eca073b..0000000 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadPress.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.adventofcode.flashk.day21.redesign; - -public record KeypadPress(String currentButton, char nextButton) { -} From a3d9a1711818555d236bc3cd9517497451d05027 Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 16:42:42 +0100 Subject: [PATCH 04/13] refactor: improve part 1 times for day 21 --- .../flashk/day21/redesign/Keypad.java | 30 ++++++++++++++----- .../day21/redesign/KeypadConundrum2.java | 24 ++++++++++----- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java index 1fd3cbf..c05a220 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java @@ -3,6 +3,7 @@ import com.adventofcode.flashk.common.Input; import com.adventofcode.flashk.common.jgrapht.LabeledEdge; import com.google.common.collect.Lists; +import lombok.Setter; import org.apache.commons.lang3.StringUtils; import org.jgrapht.Graph; import org.jgrapht.GraphPath; @@ -28,12 +29,14 @@ public class Keypad { private final Graph graph = new DirectedMultigraph<>(LabeledEdge.class); private final boolean directional; private static final Map> memo = new HashMap<>(); - private static final Map> memoCode = new HashMap<>(); + private static final Map memoCode = new HashMap<>(); // TODO opción 2: caché a nivel de code en lugar de button private String currentButton = "A"; + @Setter + private Keypad nextKeypad; public Keypad(boolean isDirectional) { @@ -78,11 +81,11 @@ public Keypad(boolean isDirectional) { /// /// @param code the code to enter. /// @return A list of possible instructions to be executed by the next robot - public Set press(String code) { + public long press(String code) { char[] buttons = code.toCharArray(); - List> allButtonPaths = new ArrayList<>(); + long minimumLength = 0; for(char button : buttons) { button = mapDirectionalButton(button); @@ -94,8 +97,19 @@ public Set press(String code) { List buttonPaths = memo.getOrDefault(state, press(button)); memo.putIfAbsent(state, buttonPaths); - // - allButtonPaths.add(buttonPaths); + long minimumButtonLength = Long.MAX_VALUE; + for(String buttonPath : buttonPaths) { + if(nextKeypad != null) { + long buttonLength = nextKeypad.press(buttonPath); + minimumButtonLength = Math.min(buttonLength, minimumButtonLength); + } else { + long buttonLength = buttonPath.length(); + minimumButtonLength = Math.min(buttonLength, minimumButtonLength); + } + + } + + minimumLength += minimumButtonLength; } // Create all the possible path combinations @@ -104,13 +118,13 @@ public Set press(String code) { // TODO con 33 elementos en la lista con tamaño mínimo 2 se intenta generar una lista con 2^3 = 8589934592 items - List> cartesianList = Lists.cartesianProduct(allButtonPaths); + /*List> cartesianList = Lists.cartesianProduct(allButtonPaths); Set paths = new HashSet<>(); for(List possiblePaths : cartesianList) { paths.add(String.join(StringUtils.EMPTY, possiblePaths)); - } + }*/ - return paths; + return minimumLength; } private char mapDirectionalButton(char button) { diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java index a947e01..e8c4ae7 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java @@ -4,22 +4,31 @@ import org.apache.commons.lang3.StringUtils; -import java.util.ArrayDeque; -import java.util.Deque; import java.util.List; import java.util.Set; public class KeypadConundrum2 { private final List codes; - private final Deque keypads = new ArrayDeque<>(); + + private final Keypad numpad; public KeypadConundrum2(List inputs, int keypadsNumber) { codes = inputs; - keypads.add(new Keypad(false)); + + // Create all keypad robots and link between them + Keypad previousRobot = null; + for(int i = 0; i < keypadsNumber; i++) { - keypads.add(new Keypad(true)); + Keypad currentRobot = new Keypad(true); + if(previousRobot != null) { + currentRobot.setNextKeypad(previousRobot); + } + previousRobot = currentRobot; } + + numpad = new Keypad(false); + numpad.setNextKeypad(previousRobot); } public long solveA() { @@ -33,11 +42,12 @@ public long solveA() { } private long press(String code) { - long shortestSequenceLength = pressCode(code); + long shortestSequenceLength = numpad.press(code); long numericValue = Long.parseLong(code.replace("A", StringUtils.EMPTY)); return shortestSequenceLength * numericValue; } + /* private long pressCode(String code) { if(keypads.isEmpty()) { @@ -57,6 +67,6 @@ private long pressCode(String code) { keypads.addFirst(nextKeypad); return shortestSequence; - } + }*/ } From 7c3108a8f7b540821fc8aeb59961ca82001f3c3f Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 17:01:11 +0100 Subject: [PATCH 05/13] refactor: rename memo and methods --- .../flashk/day21/redesign/Keypad.java | 47 +++++++++---------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java index c05a220..f384cc3 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java @@ -15,7 +15,6 @@ import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -28,8 +27,8 @@ public class Keypad { private final Graph graph = new DirectedMultigraph<>(LabeledEdge.class); private final boolean directional; - private static final Map> memo = new HashMap<>(); - private static final Map memoCode = new HashMap<>(); + private static final Map> memoGetPaths = new HashMap<>(); + private static final Map,Long> memoShortestPath = new HashMap<>(); // TODO opción 2: caché a nivel de code en lugar de button @@ -83,6 +82,11 @@ public Keypad(boolean isDirectional) { /// @return A list of possible instructions to be executed by the next robot public long press(String code) { +/* + if(memoCode.containsKey(code)) { + return memoCode.get(code); + } +*/ char[] buttons = code.toCharArray(); long minimumLength = 0; @@ -94,35 +98,26 @@ public long press(String code) { CharacterPress state = new CharacterPress(currentButton, button); // Obtain from memo or compute. Add it to memoization if it didn't exist. - List buttonPaths = memo.getOrDefault(state, press(button)); - memo.putIfAbsent(state, buttonPaths); + Set buttonPaths = memoGetPaths.getOrDefault(state, getPaths(button)); + memoGetPaths.putIfAbsent(state, buttonPaths); long minimumButtonLength = Long.MAX_VALUE; - for(String buttonPath : buttonPaths) { - if(nextKeypad != null) { - long buttonLength = nextKeypad.press(buttonPath); - minimumButtonLength = Math.min(buttonLength, minimumButtonLength); - } else { - long buttonLength = buttonPath.length(); - minimumButtonLength = Math.min(buttonLength, minimumButtonLength); - } + for (String buttonPath : buttonPaths) { + long buttonLength = nextKeypad != null ? nextKeypad.press(buttonPath) : buttonPath.length(); + minimumButtonLength = Math.min(buttonLength, minimumButtonLength); } minimumLength += minimumButtonLength; - } - - // Create all the possible path combinations - - // TODO java.lang.IllegalArgumentException: Cartesian product too large; must have size at most Integer.MAX_VALUE - // TODO con 33 elementos en la lista con tamaño mínimo 2 se intenta generar una lista con 2^3 = 8589934592 items + } - /*List> cartesianList = Lists.cartesianProduct(allButtonPaths); - Set paths = new HashSet<>(); - for(List possiblePaths : cartesianList) { - paths.add(String.join(StringUtils.EMPTY, possiblePaths)); - }*/ + /* + long updateLength = memoCode.getOrDefault(code, minimumLength); + if(minimumLength < updateLength) { + memoCode.put(code, minimumLength); + } + */ return minimumLength; } @@ -146,7 +141,7 @@ private char mapDirectionalButton(char button) { /// /// @param button the button to press. /// @return a list of different paths as String to achieve that key press from the current button position. - public List press(char button) { + public Set getPaths(char button) { AllDirectedPaths adp = new AllDirectedPaths<>(graph); List> graphPaths = adp.getAllPaths(currentButton, String.valueOf(button), @@ -163,7 +158,7 @@ public List press(char button) { this.currentButton = String.valueOf(button); int finalShortestPathSize = shortestPathSize; - return paths.stream().filter(p -> p.length() == finalShortestPathSize).toList(); + return paths.stream().filter(p -> p.length() == finalShortestPathSize).collect(Collectors.toSet()); } public void paint() { From b74c761678900ee24664630f9e097ba835350762 Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 17:14:58 +0100 Subject: [PATCH 06/13] refactor: extract button press to method to ease memoization --- .../flashk/day21/redesign/Keypad.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java index f384cc3..202dad9 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java @@ -82,31 +82,13 @@ public Keypad(boolean isDirectional) { /// @return A list of possible instructions to be executed by the next robot public long press(String code) { -/* - if(memoCode.containsKey(code)) { - return memoCode.get(code); - } -*/ char[] buttons = code.toCharArray(); long minimumLength = 0; for(char button : buttons) { button = mapDirectionalButton(button); - - // Generate a memoization status for this key press - CharacterPress state = new CharacterPress(currentButton, button); - - // Obtain from memo or compute. Add it to memoization if it didn't exist. - Set buttonPaths = memoGetPaths.getOrDefault(state, getPaths(button)); - memoGetPaths.putIfAbsent(state, buttonPaths); - - long minimumButtonLength = Long.MAX_VALUE; - - for (String buttonPath : buttonPaths) { - long buttonLength = nextKeypad != null ? nextKeypad.press(buttonPath) : buttonPath.length(); - minimumButtonLength = Math.min(buttonLength, minimumButtonLength); - } + long minimumButtonLength = getMinimumButtonLength(button); minimumLength += minimumButtonLength; @@ -122,6 +104,24 @@ public long press(String code) { return minimumLength; } + private long getMinimumButtonLength(char button) { + + // Generate a memoization status for this key press + CharacterPress state = new CharacterPress(currentButton, button); + + // Obtain from memo or compute. Add it to memoization if it didn't exist. + Set buttonPaths = memoGetPaths.getOrDefault(state, getPaths(button)); + memoGetPaths.putIfAbsent(state, buttonPaths); + + long minimumButtonLength = Long.MAX_VALUE; + + for (String buttonPath : buttonPaths) { + long buttonLength = nextKeypad != null ? nextKeypad.press(buttonPath) : buttonPath.length(); + minimumButtonLength = Math.min(buttonLength, minimumButtonLength); + } + return minimumButtonLength; + } + private char mapDirectionalButton(char button) { if(directional) { return switch(button) { From 29827b3eda3dde37e9d30e58d875d908491082a4 Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 17:18:27 +0100 Subject: [PATCH 07/13] refactor: remove currentButton usage to allow memoization --- .../flashk/day21/redesign/CharacterPress.java | 2 +- .../flashk/day21/redesign/Keypad.java | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java b/src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java index 435e827..7fa882f 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java @@ -1,4 +1,4 @@ package com.adventofcode.flashk.day21.redesign; -public record CharacterPress(String currentButton, char nextButton) { +public record CharacterPress(char currentButton, char nextButton) { } diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java index 202dad9..c9527d9 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java @@ -32,7 +32,7 @@ public class Keypad { // TODO opción 2: caché a nivel de code en lugar de button - private String currentButton = "A"; + //private String currentButton = "A"; @Setter private Keypad nextKeypad; @@ -85,11 +85,15 @@ public long press(String code) { char[] buttons = code.toCharArray(); long minimumLength = 0; + + char previousButton = 'A'; + for(char button : buttons) { button = mapDirectionalButton(button); - long minimumButtonLength = getMinimumButtonLength(button); - + long minimumButtonLength = getMinimumButtonLength(previousButton, button); + previousButton = button; + minimumLength += minimumButtonLength; } @@ -104,13 +108,13 @@ public long press(String code) { return minimumLength; } - private long getMinimumButtonLength(char button) { + private long getMinimumButtonLength(char previousButton, char button) { // Generate a memoization status for this key press - CharacterPress state = new CharacterPress(currentButton, button); + CharacterPress state = new CharacterPress(previousButton, button); // Obtain from memo or compute. Add it to memoization if it didn't exist. - Set buttonPaths = memoGetPaths.getOrDefault(state, getPaths(button)); + Set buttonPaths = memoGetPaths.getOrDefault(state, getPaths(previousButton, button)); memoGetPaths.putIfAbsent(state, buttonPaths); long minimumButtonLength = Long.MAX_VALUE; @@ -137,14 +141,10 @@ private char mapDirectionalButton(char button) { return button; } - /// Presses the specified button retrieving a list of minimum cost directional key presses to achieve that key press. - /// - /// @param button the button to press. - /// @return a list of different paths as String to achieve that key press from the current button position. - public Set getPaths(char button) { + public Set getPaths(char origin, char destination) { AllDirectedPaths adp = new AllDirectedPaths<>(graph); - List> graphPaths = adp.getAllPaths(currentButton, String.valueOf(button), + List> graphPaths = adp.getAllPaths(String.valueOf(origin), String.valueOf(destination), true,4); int shortestPathSize = Integer.MAX_VALUE; @@ -156,7 +156,7 @@ public Set getPaths(char button) { paths.add(path); } - this.currentButton = String.valueOf(button); + //this.currentButton = String.valueOf(button); int finalShortestPathSize = shortestPathSize; return paths.stream().filter(p -> p.length() == finalShortestPathSize).collect(Collectors.toSet()); } From 6bdb82145888f77879ba60bee2ddf0697c66ee6a Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 17:21:34 +0100 Subject: [PATCH 08/13] refactor: improve getPaths memoization --- .../flashk/day21/redesign/Keypad.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java index c9527d9..ab2f733 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java @@ -15,6 +15,7 @@ import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -93,7 +94,7 @@ public long press(String code) { button = mapDirectionalButton(button); long minimumButtonLength = getMinimumButtonLength(previousButton, button); previousButton = button; - + minimumLength += minimumButtonLength; } @@ -110,12 +111,8 @@ public long press(String code) { private long getMinimumButtonLength(char previousButton, char button) { - // Generate a memoization status for this key press - CharacterPress state = new CharacterPress(previousButton, button); - // Obtain from memo or compute. Add it to memoization if it didn't exist. - Set buttonPaths = memoGetPaths.getOrDefault(state, getPaths(previousButton, button)); - memoGetPaths.putIfAbsent(state, buttonPaths); + Set buttonPaths = getPaths(previousButton, button); long minimumButtonLength = Long.MAX_VALUE; @@ -142,6 +139,13 @@ private char mapDirectionalButton(char button) { } public Set getPaths(char origin, char destination) { + + // Use cache first + CharacterPress state = new CharacterPress(origin, destination); + if(memoGetPaths.containsKey(state)) { + return memoGetPaths.get(state); + } + AllDirectedPaths adp = new AllDirectedPaths<>(graph); List> graphPaths = adp.getAllPaths(String.valueOf(origin), String.valueOf(destination), @@ -149,7 +153,7 @@ public Set getPaths(char origin, char destination) { int shortestPathSize = Integer.MAX_VALUE; - List paths = new ArrayList<>(); + Set paths = new HashSet<>(); for(GraphPath graphPath : graphPaths) { String path = graphPath.getEdgeList().stream().map(LabeledEdge::getValue).collect(Collectors.joining()) + "A"; shortestPathSize = Math.min(path.length(), shortestPathSize); @@ -158,7 +162,12 @@ public Set getPaths(char origin, char destination) { //this.currentButton = String.valueOf(button); int finalShortestPathSize = shortestPathSize; - return paths.stream().filter(p -> p.length() == finalShortestPathSize).collect(Collectors.toSet()); + paths = paths.stream().filter(p -> p.length() == finalShortestPathSize).collect(Collectors.toSet()); + + // Memoize paths + memoGetPaths.put(state, paths); + + return paths; } public void paint() { From ebb52c06520b461019c8bcc6a2bf0a6d119e13d3 Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 23:17:50 +0100 Subject: [PATCH 09/13] feat: solve day 21 part 2 --- .../flashk/day21/redesign/Keypad.java | 25 ++++++++++--------- .../day21/redesign/KeypadConundrum2.java | 22 ---------------- .../adventofcode/flashk/day21/Day21Test.java | 5 ++-- 3 files changed, 15 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java index ab2f733..2923a84 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java @@ -28,12 +28,10 @@ public class Keypad { private final Graph graph = new DirectedMultigraph<>(LabeledEdge.class); private final boolean directional; - private static final Map> memoGetPaths = new HashMap<>(); - private static final Map,Long> memoShortestPath = new HashMap<>(); - - // TODO opción 2: caché a nivel de code en lugar de button - //private String currentButton = "A"; + // Memoization maps + private static final Map> memoGetPaths = new HashMap<>(); + private final Map memoMinButtonLength = new HashMap<>(); @Setter private Keypad nextKeypad; @@ -99,18 +97,17 @@ public long press(String code) { } - /* - long updateLength = memoCode.getOrDefault(code, minimumLength); - if(minimumLength < updateLength) { - memoCode.put(code, minimumLength); - } - */ - return minimumLength; } private long getMinimumButtonLength(char previousButton, char button) { + // Memoization + CharacterPress state = new CharacterPress(previousButton, button); + if(memoMinButtonLength.containsKey(state)) { + return memoMinButtonLength.get(state); + } + // Obtain from memo or compute. Add it to memoization if it didn't exist. Set buttonPaths = getPaths(previousButton, button); @@ -120,6 +117,10 @@ private long getMinimumButtonLength(char previousButton, char button) { long buttonLength = nextKeypad != null ? nextKeypad.press(buttonPath) : buttonPath.length(); minimumButtonLength = Math.min(buttonLength, minimumButtonLength); } + + // Memoization + memoMinButtonLength.put(state, minimumButtonLength); + return minimumButtonLength; } diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java index e8c4ae7..e77966a 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java +++ b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java @@ -5,7 +5,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.List; -import java.util.Set; public class KeypadConundrum2 { @@ -47,26 +46,5 @@ private long press(String code) { return shortestSequenceLength * numericValue; } - /* - private long pressCode(String code) { - - if(keypads.isEmpty()) { - return code.length(); - } - - long shortestSequence = Long.MAX_VALUE; - - Keypad nextKeypad = keypads.pollFirst(); - - Set keyPressesList = nextKeypad.press(code); - for(String keyPresses : keyPressesList) { - long sequence = pressCode(keyPresses); - shortestSequence = Math.min(shortestSequence, sequence); - } - - keypads.addFirst(nextKeypad); - - return shortestSequence; - }*/ } diff --git a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java index c2fbc89..a2235ce 100644 --- a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java +++ b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java @@ -70,9 +70,8 @@ public void testSolvePart2Input() { List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE); KeypadConundrum2 keypadConundrum = new KeypadConundrum2(inputs, 25); - - System.out.println("Solution: "+ keypadConundrum.solveA()); - assertEquals(0L,0L); + + assertEquals(251508572750680L,keypadConundrum.solveA()); } From a1f67cbe70e47b95e88d7d90c2c50f5da656e93b Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 23:40:01 +0100 Subject: [PATCH 10/13] refactor: remove not needed classes for day 21 --- README.md | 2 +- .../day21/{redesign => }/CharacterPress.java | 2 +- .../flashk/day21/DirectionalKeypad.java | 79 -------- .../flashk/day21/{redesign => }/Keypad.java | 5 +- .../flashk/day21/KeypadConundrum.java | 41 ++-- .../com/adventofcode/flashk/day21/Numpad.java | 182 ------------------ .../adventofcode/flashk/day21/PadEdge.java | 15 -- .../com/adventofcode/flashk/day21/README.md | 2 +- .../flashk/day21/redesign/CodePress.java | 4 - .../flashk/day21/redesign/Key.java | 41 ---- .../day21/redesign/KeypadConundrum2.java | 50 ----- .../adventofcode/flashk/day21/Day21Test.java | 10 +- .../flashk/day21/DirectionalKeypadTest.java | 108 ----------- .../adventofcode/flashk/day21/KeyTest.java | 16 -- .../adventofcode/flashk/day21/NumpadTest.java | 43 ----- 15 files changed, 29 insertions(+), 571 deletions(-) rename src/main/java/com/adventofcode/flashk/day21/{redesign => }/CharacterPress.java (59%) delete mode 100644 src/main/java/com/adventofcode/flashk/day21/DirectionalKeypad.java rename src/main/java/com/adventofcode/flashk/day21/{redesign => }/Keypad.java (97%) delete mode 100644 src/main/java/com/adventofcode/flashk/day21/Numpad.java delete mode 100644 src/main/java/com/adventofcode/flashk/day21/PadEdge.java delete mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/CodePress.java delete mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/Key.java delete mode 100644 src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java delete mode 100644 src/test/java/com/adventofcode/flashk/day21/DirectionalKeypadTest.java delete mode 100644 src/test/java/com/adventofcode/flashk/day21/KeyTest.java delete mode 100644 src/test/java/com/adventofcode/flashk/day21/NumpadTest.java diff --git a/README.md b/README.md index bafce84..cf1a931 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ - [Day 18 - RAM Run](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day18) - [Day 19 - Linen Layout](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day19) - [Day 20 - Race Condition](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day20) -- [Day 21](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day21) +- [Day 21 - Keypad Conundrum](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day21) - [Day 22 - Monkey Market](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day22) - [Day 23 - LAN Party](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day23) - [Day 24 - Crossed Wires](https://github.com/Flashky/advent-of-code-2024/tree/master/src/main/java/com/adventofcode/flashk/day24) diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java b/src/main/java/com/adventofcode/flashk/day21/CharacterPress.java similarity index 59% rename from src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java rename to src/main/java/com/adventofcode/flashk/day21/CharacterPress.java index 7fa882f..5fa956e 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/CharacterPress.java +++ b/src/main/java/com/adventofcode/flashk/day21/CharacterPress.java @@ -1,4 +1,4 @@ -package com.adventofcode.flashk.day21.redesign; +package com.adventofcode.flashk.day21; public record CharacterPress(char currentButton, char nextButton) { } diff --git a/src/main/java/com/adventofcode/flashk/day21/DirectionalKeypad.java b/src/main/java/com/adventofcode/flashk/day21/DirectionalKeypad.java deleted file mode 100644 index 22bbb06..0000000 --- a/src/main/java/com/adventofcode/flashk/day21/DirectionalKeypad.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.adventofcode.flashk.day21; - -import lombok.Setter; -import org.jgrapht.Graph; -import org.jgrapht.GraphPath; -import org.jgrapht.alg.shortestpath.DijkstraShortestPath; -import org.jgrapht.graph.DirectedMultigraph; - - -public class DirectionalKeypad { - - public static final Character UP = '^'; - public static final Character DOWN = 'v'; - public static final Character LEFT = '<'; - public static final Character RIGHT = '>'; - public static final Character ACCEPT = 'A'; - public static final String ACCEPT_TO_LEFT = "v<<"; - public static final String LEFT_TO_ACCEPT = "^>>"; - public static final String DOWN_TO_ACCEPT = ">^"; - - private Graph graph = new DirectedMultigraph<>(PadEdge.class); - private DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath<>(graph); - - @Setter - private Character currentKey = ACCEPT; - - public DirectionalKeypad() { - graph.addVertex(LEFT); - graph.addVertex(DOWN); - graph.addVertex(UP); - graph.addVertex(RIGHT); - graph.addVertex(ACCEPT); - - graph.addEdge(LEFT, DOWN, new PadEdge(RIGHT)); - graph.addEdge(LEFT,ACCEPT, new PadEdge(LEFT_TO_ACCEPT)); - - graph.addEdge(DOWN, LEFT, new PadEdge(LEFT)); - graph.addEdge(DOWN, UP, new PadEdge(UP)); - graph.addEdge(DOWN, RIGHT, new PadEdge(RIGHT)); - graph.addEdge(DOWN, ACCEPT, new PadEdge(DOWN_TO_ACCEPT)); - - graph.addEdge(UP, DOWN, new PadEdge(DOWN)); - graph.addEdge(UP, ACCEPT, new PadEdge(RIGHT)); - - graph.addEdge(RIGHT, DOWN, new PadEdge(LEFT)); - graph.addEdge(RIGHT, ACCEPT, new PadEdge(UP)); - - graph.addEdge(ACCEPT, UP, new PadEdge(LEFT)); - graph.addEdge(ACCEPT, RIGHT, new PadEdge(DOWN)); - graph.addEdge(ACCEPT, LEFT, new PadEdge(ACCEPT_TO_LEFT)); // new - - } - - /// Enters a code, such as `029A`, returning a [String] representing the needed moves for it. - /// @param code the code to enter. - /// @return The String that represents the performed movements to enter that code at the numpad. - public String press(String code) { - char[] buttons = code.toCharArray(); - - StringBuilder sb = new StringBuilder(); - for(char button : buttons) { - sb.append(press(button)); - } - - return sb.toString(); - } - - private String press(char button) { - - GraphPath path = dijkstraShortestPath.getPath(currentKey, button); - StringBuilder sb = new StringBuilder(); - for(PadEdge edge : path.getEdgeList()) { - sb.append(edge.label()); - } - sb.append(ACCEPT); - currentKey = button; - return sb.toString(); - } -} diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/Keypad.java similarity index 97% rename from src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java rename to src/main/java/com/adventofcode/flashk/day21/Keypad.java index 2923a84..c71f892 100644 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java +++ b/src/main/java/com/adventofcode/flashk/day21/Keypad.java @@ -1,10 +1,8 @@ -package com.adventofcode.flashk.day21.redesign; +package com.adventofcode.flashk.day21; import com.adventofcode.flashk.common.Input; import com.adventofcode.flashk.common.jgrapht.LabeledEdge; -import com.google.common.collect.Lists; import lombok.Setter; -import org.apache.commons.lang3.StringUtils; import org.jgrapht.Graph; import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.AllDirectedPaths; @@ -13,7 +11,6 @@ import java.io.StringWriter; import java.io.Writer; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; diff --git a/src/main/java/com/adventofcode/flashk/day21/KeypadConundrum.java b/src/main/java/com/adventofcode/flashk/day21/KeypadConundrum.java index 435d794..4394c78 100644 --- a/src/main/java/com/adventofcode/flashk/day21/KeypadConundrum.java +++ b/src/main/java/com/adventofcode/flashk/day21/KeypadConundrum.java @@ -1,29 +1,38 @@ package com.adventofcode.flashk.day21; + import org.apache.commons.lang3.StringUtils; -import java.util.ArrayList; import java.util.List; public class KeypadConundrum { - private Numpad numpadRobot = new Numpad(); - private List directionalKeypads = new ArrayList<>(); + private final List codes; - private List codes; + private final Keypad numpad; - public KeypadConundrum(List inputs) { + public KeypadConundrum(List inputs, int keypadsNumber) { codes = inputs; + + // Create all keypad robots and link between them + Keypad previousRobot = null; + + for(int i = 0; i < keypadsNumber; i++) { + Keypad currentRobot = new Keypad(true); + if(previousRobot != null) { + currentRobot.setNextKeypad(previousRobot); + } + previousRobot = currentRobot; + } + + numpad = new Keypad(false); + numpad.setNextKeypad(previousRobot); } public long solveA() { long result = 0; - directionalKeypads.add(new DirectionalKeypad()); - directionalKeypads.add(new DirectionalKeypad()); - - for(String code : codes) { result += press(code); } @@ -32,18 +41,10 @@ public long solveA() { } private long press(String code) { - String movements = numpadRobot.press(code); - String directionalMovements = StringUtils.EMPTY; - - for(DirectionalKeypad directionalKeypad : directionalKeypads) { - - directionalMovements = directionalKeypad.press(movements); - movements = directionalMovements; - } - - long shortestSequenceLength = directionalMovements.length(); + long shortestSequenceLength = numpad.press(code); long numericValue = Long.parseLong(code.replace("A", StringUtils.EMPTY)); - return shortestSequenceLength * numericValue; } + + } diff --git a/src/main/java/com/adventofcode/flashk/day21/Numpad.java b/src/main/java/com/adventofcode/flashk/day21/Numpad.java deleted file mode 100644 index 07d5a4e..0000000 --- a/src/main/java/com/adventofcode/flashk/day21/Numpad.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.adventofcode.flashk.day21; - -import org.jgrapht.Graph; -import org.jgrapht.GraphPath; -import org.jgrapht.alg.shortestpath.DijkstraShortestPath; - -import org.jgrapht.graph.DirectedMultigraph; -import org.jgrapht.graph.DirectedWeightedMultigraph; - -import java.util.List; - -public class Numpad { - - public static final Character BUTTON_0 = '0'; - public static final Character BUTTON_1 = '1'; - public static final Character BUTTON_2 = '2'; - public static final Character BUTTON_3 = '3'; - public static final Character BUTTON_4 = '4'; - public static final Character BUTTON_5 = '5'; - public static final Character BUTTON_6 = '6'; - public static final Character BUTTON_7 = '7'; - public static final Character BUTTON_8 = '8'; - public static final Character BUTTON_9 = '9'; - public static final Character ACCEPT = 'A'; - private static final String BUTTON_2_TO_BUTTON_9 = ">^^"; - private static final String BUTTON_9_TO_BUTTON_2 = "vv<"; - - private Graph graph = new DirectedWeightedMultigraph<>(PadEdge.class); - - private DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath<>(graph); - - private Character currentKey = ACCEPT; - - public Numpad() { - - graph.addVertex(BUTTON_0); - graph.addVertex(BUTTON_1); - graph.addVertex(BUTTON_2); - graph.addVertex(BUTTON_3); - graph.addVertex(BUTTON_4); - graph.addVertex(BUTTON_5); - graph.addVertex(BUTTON_6); - graph.addVertex(BUTTON_7); - graph.addVertex(BUTTON_8); - graph.addVertex(BUTTON_9); - graph.addVertex(ACCEPT); - - - // TODO problema con los ejes - // Labeled edges in multigraph MUST BE unique, so an String or Character is not enough: - // https://jgrapht.org/guide/VertexAndEdgeTypes#labeled-edges-in-a-multigraph - - // modelar ejes con un record único. - - - // cada eje debería tener un nombre único - PadEdge padEdge; - - graph.addEdge(BUTTON_0, BUTTON_2, new PadEdge(DirectionalKeypad.UP)); - graph.setEdgeWeight(BUTTON_0, BUTTON_2, 2); - - graph.addEdge(BUTTON_0, ACCEPT, new PadEdge(DirectionalKeypad.RIGHT)); - graph.setEdgeWeight(BUTTON_0, ACCEPT, 1); - - graph.addEdge(BUTTON_1, BUTTON_2, new PadEdge(DirectionalKeypad.RIGHT)); - graph.setEdgeWeight(BUTTON_1, BUTTON_2, 2); - - graph.addEdge(BUTTON_1, BUTTON_4, new PadEdge(DirectionalKeypad.UP)); - graph.setEdgeWeight(BUTTON_1, BUTTON_4, 3); - - graph.addEdge(BUTTON_2, BUTTON_0, new PadEdge(DirectionalKeypad.DOWN)); - graph.setEdgeWeight(BUTTON_2, BUTTON_0, 2); - - graph.addEdge(BUTTON_2, BUTTON_1, new PadEdge(DirectionalKeypad.LEFT)); - graph.setEdgeWeight(BUTTON_2, BUTTON_1, 3); - - graph.addEdge(BUTTON_2, BUTTON_3, new PadEdge(DirectionalKeypad.RIGHT)); - graph.setEdgeWeight(BUTTON_2, BUTTON_3, 1); - - graph.addEdge(BUTTON_2, BUTTON_5, new PadEdge(DirectionalKeypad.UP)); - graph.setEdgeWeight(BUTTON_2, BUTTON_5, 2); - - graph.addEdge(BUTTON_3, BUTTON_2, new PadEdge(DirectionalKeypad.LEFT)); - graph.setEdgeWeight(BUTTON_3, BUTTON_2, 2); - - graph.addEdge(BUTTON_3, BUTTON_6, new PadEdge(DirectionalKeypad.UP)); - graph.setEdgeWeight(BUTTON_3, BUTTON_6, 1); - - graph.addEdge(BUTTON_3, ACCEPT, new PadEdge(DirectionalKeypad.DOWN)); - graph.setEdgeWeight(BUTTON_3, ACCEPT, 1); - - graph.addEdge(BUTTON_4, BUTTON_1, new PadEdge(DirectionalKeypad.DOWN)); - graph.setEdgeWeight(BUTTON_4, BUTTON_1, 3); - - graph.addEdge(BUTTON_4, BUTTON_5, new PadEdge(DirectionalKeypad.RIGHT)); - graph.setEdgeWeight(BUTTON_4, BUTTON_5, 2); - - graph.addEdge(BUTTON_4, BUTTON_7, new PadEdge(DirectionalKeypad.UP)); - graph.setEdgeWeight(BUTTON_4, BUTTON_7, 3); - - graph.addEdge(BUTTON_5, BUTTON_2, new PadEdge(DirectionalKeypad.DOWN)); - graph.setEdgeWeight(BUTTON_5, BUTTON_2, 2); - - graph.addEdge(BUTTON_5, BUTTON_4, new PadEdge(DirectionalKeypad.LEFT)); - graph.setEdgeWeight(BUTTON_5, BUTTON_4, 3); - - graph.addEdge(BUTTON_5, BUTTON_6, new PadEdge(DirectionalKeypad.RIGHT)); - graph.setEdgeWeight(BUTTON_5, BUTTON_6, 1); - - graph.addEdge(BUTTON_5, BUTTON_8, new PadEdge(DirectionalKeypad.UP)); - graph.setEdgeWeight(BUTTON_5, BUTTON_8, 2); - - graph.addEdge(BUTTON_6, BUTTON_3, new PadEdge(DirectionalKeypad.DOWN)); - graph.setEdgeWeight(BUTTON_6, BUTTON_3, 1); - - graph.addEdge(BUTTON_6, BUTTON_5, new PadEdge(DirectionalKeypad.LEFT)); - graph.setEdgeWeight(BUTTON_6, BUTTON_5, 2); - - graph.addEdge(BUTTON_6, BUTTON_9, new PadEdge(DirectionalKeypad.UP)); - graph.setEdgeWeight(BUTTON_6, BUTTON_9, 1); - - graph.addEdge(BUTTON_7, BUTTON_4, new PadEdge(DirectionalKeypad.DOWN)); - graph.setEdgeWeight(BUTTON_7, BUTTON_4, 3); - - graph.addEdge(BUTTON_7, BUTTON_8, new PadEdge(DirectionalKeypad.RIGHT)); - graph.setEdgeWeight(BUTTON_7, BUTTON_8, 2); - - graph.addEdge(BUTTON_8, BUTTON_5, new PadEdge(DirectionalKeypad.DOWN)); - graph.setEdgeWeight(BUTTON_8, BUTTON_5, 2); - - graph.addEdge(BUTTON_8, BUTTON_7, new PadEdge(DirectionalKeypad.LEFT)); - graph.setEdgeWeight(BUTTON_8, BUTTON_7, 3); - - graph.addEdge(BUTTON_8, BUTTON_9, new PadEdge(DirectionalKeypad.RIGHT)); - graph.setEdgeWeight(BUTTON_8, BUTTON_9, 1); - - graph.addEdge(BUTTON_9, BUTTON_6, new PadEdge(DirectionalKeypad.DOWN)); - graph.setEdgeWeight(BUTTON_9, BUTTON_6, 1); - - graph.addEdge(BUTTON_9, BUTTON_8, new PadEdge(DirectionalKeypad.LEFT)); - graph.setEdgeWeight(BUTTON_9, BUTTON_8, 2); - //graph.addEdge(BUTTON_9, BUTTON_2, new PadEdge(BUTTON_9_TO_BUTTON_2)); - - graph.addEdge(ACCEPT, BUTTON_0, new PadEdge(DirectionalKeypad.LEFT)); - graph.setEdgeWeight(ACCEPT, BUTTON_0, 1); - - graph.addEdge(ACCEPT, BUTTON_3, new PadEdge(DirectionalKeypad.UP)); - graph.setEdgeWeight(ACCEPT, BUTTON_3, 1); - - - } - - /// Enters a code, such as `029A`, returning a [String] representing the needed moves for it. - /// @param code the code to enter. - /// @return The String the instructions to be executed at a [DirectionalKeypad](DirectionalKeypad). - public String press(String code) { - char[] buttons = code.toCharArray(); - - StringBuilder sb = new StringBuilder(); - for(char button : buttons) { - sb.append(press(button)); - } - - return sb.toString(); - } - - private String press(char button) { - GraphPath path = dijkstraShortestPath.getPath(currentKey, button); - StringBuilder sb = new StringBuilder(); - for(PadEdge edge : path.getEdgeList()) { - sb.append(edge.label()); - } - sb.append(ACCEPT); - currentKey = button; - return sb.toString(); - } - - - public void reset() { - currentKey = ACCEPT; - } -} diff --git a/src/main/java/com/adventofcode/flashk/day21/PadEdge.java b/src/main/java/com/adventofcode/flashk/day21/PadEdge.java deleted file mode 100644 index e978951..0000000 --- a/src/main/java/com/adventofcode/flashk/day21/PadEdge.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.adventofcode.flashk.day21; - -public record PadEdge(String label, int id) { - - private static int idGenerator = 0; - - public PadEdge(Character label) { - this(String.valueOf(label), idGenerator++); - } - - public PadEdge(String label) { - this(label, idGenerator++); - } - -} diff --git a/src/main/java/com/adventofcode/flashk/day21/README.md b/src/main/java/com/adventofcode/flashk/day21/README.md index 9915c2a..78b5c2d 100644 --- a/src/main/java/com/adventofcode/flashk/day21/README.md +++ b/src/main/java/com/adventofcode/flashk/day21/README.md @@ -1,3 +1,3 @@ -# Day 21: +# Day 21: Keypad Conundrum [https://adventofcode.com/2024/day/21](https://adventofcode.com/2024/day/21) diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/CodePress.java b/src/main/java/com/adventofcode/flashk/day21/redesign/CodePress.java deleted file mode 100644 index 1328b48..0000000 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/CodePress.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.adventofcode.flashk.day21.redesign; - -public record CodePress(String currentButton, String code) { -} diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/Key.java b/src/main/java/com/adventofcode/flashk/day21/redesign/Key.java deleted file mode 100644 index dc915ec..0000000 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/Key.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.adventofcode.flashk.day21.redesign; - - -import lombok.Getter; - -public enum Key { - - NUMBER_0("0"), - NUMBER_1("1"), - NUMBER_2("2"), - NUMBER_3("3"), - NUMBER_4("4"), - NUMBER_5("5"), - NUMBER_6("6"), - NUMBER_7("7"), - NUMBER_8("8"), - NUMBER_9("9"), - ARROW_LEFT("<"), - ARROW_DOWN("v"), - ARROW_UP("^"), - ARROW_RIGHT(">"), - ACCEPT("A"); - - @Getter - private final String value; - - Key(String value) { - this.value = value; - } - - /* - public static Key getKey(String value) { - for(Key key : values()) { - if(key.getValue().equals(value)) { - return key; - } - } - throw new IllegalArgumentException("Unknown enum value for: "+value); - }*/ - -} diff --git a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java b/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java deleted file mode 100644 index e77966a..0000000 --- a/src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.adventofcode.flashk.day21.redesign; - - - -import org.apache.commons.lang3.StringUtils; - -import java.util.List; - -public class KeypadConundrum2 { - - private final List codes; - - private final Keypad numpad; - - public KeypadConundrum2(List inputs, int keypadsNumber) { - codes = inputs; - - // Create all keypad robots and link between them - Keypad previousRobot = null; - - for(int i = 0; i < keypadsNumber; i++) { - Keypad currentRobot = new Keypad(true); - if(previousRobot != null) { - currentRobot.setNextKeypad(previousRobot); - } - previousRobot = currentRobot; - } - - numpad = new Keypad(false); - numpad.setNextKeypad(previousRobot); - } - - public long solveA() { - - long result = 0; - for(String code : codes) { - result += press(code); - } - - return result; - } - - private long press(String code) { - long shortestSequenceLength = numpad.press(code); - long numericValue = Long.parseLong(code.replace("A", StringUtils.EMPTY)); - return shortestSequenceLength * numericValue; - } - - -} diff --git a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java index a2235ce..416472b 100644 --- a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java +++ b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java @@ -2,7 +2,6 @@ import java.util.List; -import com.adventofcode.flashk.day21.redesign.KeypadConundrum2; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; @@ -15,7 +14,6 @@ import com.adventofcode.flashk.common.test.constants.TestFilename; import com.adventofcode.flashk.common.test.constants.TestFolder; import com.adventofcode.flashk.common.test.constants.TestTag; -import com.adventofcode.flashk.common.test.utils.PuzzleTest; import com.adventofcode.flashk.common.test.utils.Input; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -37,7 +35,7 @@ public void testSolvePart1Sample() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE); - KeypadConundrum2 keypadConundrum = new KeypadConundrum2(inputs, 2); + KeypadConundrum keypadConundrum = new KeypadConundrum(inputs, 2); assertEquals(126384L, keypadConundrum.solveA()); //assertEquals(0L,keypadConundrum.solveA()); @@ -53,7 +51,7 @@ public void testSolvePart1Input() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE); - KeypadConundrum2 keypadConundrum = new KeypadConundrum2(inputs, 2); + KeypadConundrum keypadConundrum = new KeypadConundrum(inputs, 2); assertEquals(206798L,keypadConundrum.solveA()); @@ -69,8 +67,8 @@ public void testSolvePart2Input() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE); - KeypadConundrum2 keypadConundrum = new KeypadConundrum2(inputs, 25); - + KeypadConundrum keypadConundrum = new KeypadConundrum(inputs, 25); + assertEquals(251508572750680L,keypadConundrum.solveA()); } diff --git a/src/test/java/com/adventofcode/flashk/day21/DirectionalKeypadTest.java b/src/test/java/com/adventofcode/flashk/day21/DirectionalKeypadTest.java deleted file mode 100644 index 992166b..0000000 --- a/src/test/java/com/adventofcode/flashk/day21/DirectionalKeypadTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.adventofcode.flashk.day21; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class DirectionalKeypadTest { - - - @Test - void pressFromAcceptTest() { - - DirectionalKeypad keypad = new DirectionalKeypad(); - - assertEquals("v<")); - - keypad.setCurrentKey(DirectionalKeypad.ACCEPT); - assertEquals("A", keypad.press("A")); - - keypad.setCurrentKey(DirectionalKeypad.UP); - assertEquals("vA", keypad.press(">")); - - keypad.setCurrentKey(DirectionalKeypad.UP); - assertEquals("vA", keypad.press("v")); - - } - - @Test - void pressFromLeftTest() { - - DirectionalKeypad keypad = new DirectionalKeypad(); - - keypad.setCurrentKey(DirectionalKeypad.LEFT); - assertEquals("^>>A", keypad.press("A")); - - keypad.setCurrentKey(DirectionalKeypad.LEFT); - assertEquals(">>A", keypad.press(">")); - - keypad.setCurrentKey(DirectionalKeypad.LEFT); - assertEquals(">^A", keypad.press("^")); - - keypad.setCurrentKey(DirectionalKeypad.LEFT); - assertEquals(">A", keypad.press("v")); - - } - - @Test - void pressFromDownToATest() { - - DirectionalKeypad keypad = new DirectionalKeypad(); - - keypad.setCurrentKey(DirectionalKeypad.DOWN); - assertEquals(">^A", keypad.press("A")); - - keypad.setCurrentKey(DirectionalKeypad.DOWN); - assertEquals("A", keypad.press(">")); - - keypad.setCurrentKey(DirectionalKeypad.DOWN); - assertEquals("^A", keypad.press("^")); - } - - @Test - void pressFromRightTest() { - - DirectionalKeypad keypad = new DirectionalKeypad(); - - keypad.setCurrentKey(DirectionalKeypad.RIGHT); - assertEquals("^A", keypad.press("A")); - - keypad.setCurrentKey(DirectionalKeypad.RIGHT); - assertEquals("< Date: Sun, 29 Dec 2024 23:45:37 +0100 Subject: [PATCH 11/13] refactor: final code cleanups --- .../com/adventofcode/flashk/day21/Keypad.java | 20 ------------- .../adventofcode/flashk/day21/Day21Test.java | 29 +++++++++++++++---- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/adventofcode/flashk/day21/Keypad.java b/src/main/java/com/adventofcode/flashk/day21/Keypad.java index c71f892..77c0f89 100644 --- a/src/main/java/com/adventofcode/flashk/day21/Keypad.java +++ b/src/main/java/com/adventofcode/flashk/day21/Keypad.java @@ -7,10 +7,7 @@ import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.AllDirectedPaths; import org.jgrapht.graph.DirectedMultigraph; -import org.jgrapht.nio.dot.DOTExporter; -import java.io.StringWriter; -import java.io.Writer; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -69,13 +66,6 @@ public Keypad(boolean isDirectional) { } - /// Enters a code to be pressed at the pad returning a [String] representing the needed moves for it. - /// - /// The code can be either an alphanumeric value as such as `029A` to be pressed at a numeric pad or an - /// alphanumeric value such as `^AvvvA` to be pressed at a directional keypad. - /// - /// @param code the code to enter. - /// @return A list of possible instructions to be executed by the next robot public long press(String code) { char[] buttons = code.toCharArray(); @@ -158,7 +148,6 @@ public Set getPaths(char origin, char destination) { paths.add(path); } - //this.currentButton = String.valueOf(button); int finalShortestPathSize = shortestPathSize; paths = paths.stream().filter(p -> p.length() == finalShortestPathSize).collect(Collectors.toSet()); @@ -168,13 +157,4 @@ public Set getPaths(char origin, char destination) { return paths; } - public void paint() { - - DOTExporter exporter = new DOTExporter<>(v -> v); - exporter.setEdgeAttributeProvider(e -> Map.of("label", e)); - - Writer writer = new StringWriter(); - exporter.exportGraph(graph, writer); - System.out.println(writer.toString()); - } } diff --git a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java index 416472b..27b4e00 100644 --- a/src/test/java/com/adventofcode/flashk/day21/Day21Test.java +++ b/src/test/java/com/adventofcode/flashk/day21/Day21Test.java @@ -21,7 +21,7 @@ @DisplayName(TestDisplayName.DAY_21) @TestMethodOrder(OrderAnnotation.class) @Disabled("[Disabled] Day 21 - Work in Progress") -public class Day21Test { +class Day21Test { private static final String INPUT_FOLDER = TestFolder.DAY_21; @@ -30,7 +30,7 @@ public class Day21Test { @Tag(TestTag.PART_1) @Tag(TestTag.SAMPLE) @DisplayName(TestDisplayName.PART_1_SAMPLE) - public void testSolvePart1Sample() { + void part1SampleTest() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE); @@ -38,7 +38,7 @@ public void testSolvePart1Sample() { KeypadConundrum keypadConundrum = new KeypadConundrum(inputs, 2); assertEquals(126384L, keypadConundrum.solveA()); - //assertEquals(0L,keypadConundrum.solveA()); + } @Test @@ -46,7 +46,7 @@ public void testSolvePart1Sample() { @Tag(TestTag.PART_1) @Tag(TestTag.INPUT) @DisplayName(TestDisplayName.PART_1_INPUT) - public void testSolvePart1Input() { + void part1InputTest() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE); @@ -57,12 +57,31 @@ public void testSolvePart1Input() { } + + @Test + @Order(4) + @Tag(TestTag.PART_2) + @Tag(TestTag.INPUT) + @DisplayName(TestDisplayName.PART_2_SAMPLE) + void part2SampleTest() { + + // Read input file + List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE); + + KeypadConundrum keypadConundrum = new KeypadConundrum(inputs, 25); + + // Source: https://www.reddit.com/r/adventofcode/comments/1hjb7hh/2024_day_21_part_2_can_someone_share_what_the/ + + assertEquals(154115708116294L,keypadConundrum.solveA()); + + } + @Test @Order(4) @Tag(TestTag.PART_2) @Tag(TestTag.INPUT) @DisplayName(TestDisplayName.PART_2_INPUT) - public void testSolvePart2Input() { + void part2InputTest() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE); From 7c430c30679d58b326c3c6b9d99a71842b1d3861 Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 23:46:57 +0100 Subject: [PATCH 12/13] feat: update docs --- src/test/resources/inputs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/resources/inputs b/src/test/resources/inputs index 3bf2878..0ccf298 160000 --- a/src/test/resources/inputs +++ b/src/test/resources/inputs @@ -1 +1 @@ -Subproject commit 3bf2878c9e1f0bfea9c7e80f21eaec94b3cfa0fd +Subproject commit 0ccf2981ffc899cecc246d2a797b9a16903ffaff From 22645bfa6048e00a57ea16d4a0cadc6a60bf877d Mon Sep 17 00:00:00 2001 From: Flashk Date: Sun, 29 Dec 2024 23:53:50 +0100 Subject: [PATCH 13/13] docs: update READMEs --- src/test/resources/inputs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/resources/inputs b/src/test/resources/inputs index 0ccf298..ee864be 160000 --- a/src/test/resources/inputs +++ b/src/test/resources/inputs @@ -1 +1 @@ -Subproject commit 0ccf2981ffc899cecc246d2a797b9a16903ffaff +Subproject commit ee864be598efda7b1ad56a5ec1af75bd01d82dfb