generated from Flashky/advent-of-code-yyyy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
398 additions
and
18 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String> readStringLines(String inputFolder, String inputFile) { | ||
|
||
List<String> 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; | ||
} | ||
|
||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/com/adventofcode/flashk/common/jgrapht/LabeledEdge.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 + ")"; | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
src/main/java/com/adventofcode/flashk/day21/redesign/Key.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
}*/ | ||
|
||
} |
152 changes: 152 additions & 0 deletions
152
src/main/java/com/adventofcode/flashk/day21/redesign/Keypad.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String, LabeledEdge> graph = new DirectedMultigraph<>(LabeledEdge.class); | ||
private final boolean directional; | ||
private static final Map<KeypadPress,List<String>> 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<String> 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 `<A^A^>^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<String> press(String code) { | ||
char[] buttons = code.toCharArray(); | ||
|
||
List<List<String>> 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<String> buttonPaths = memo.getOrDefault(state, press(button)); | ||
memo.putIfAbsent(state, buttonPaths); | ||
|
||
// | ||
allButtonPaths.add(buttonPaths); | ||
} | ||
|
||
// Create all the possible path combinations | ||
List<List<String>> cartesianList = Lists.cartesianProduct(allButtonPaths); | ||
Set<String> paths = new HashSet<>(); | ||
for(List<String> 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<String> press(char button) { | ||
AllDirectedPaths<String, LabeledEdge> adp = new AllDirectedPaths<>(graph); | ||
|
||
List<GraphPath<String, LabeledEdge>> graphPaths = adp.getAllPaths(currentButton, String.valueOf(button), | ||
true,4); | ||
|
||
int shortestPathSize = Integer.MAX_VALUE; | ||
|
||
List<String> paths = new ArrayList<>(); | ||
for(GraphPath<String, LabeledEdge> 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<String, LabeledEdge> 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()); | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
src/main/java/com/adventofcode/flashk/day21/redesign/KeypadConundrum2.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String> codes; | ||
|
||
private Deque<Keypad> keypads = new ArrayDeque<>(); | ||
|
||
public KeypadConundrum2(List<String> 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<String> keyPressesList = nextKeypad.press(code); | ||
for(String keyPresses : keyPressesList) { | ||
long sequence = pressCode(keyPresses); | ||
shortestSequence = Math.min(shortestSequence, sequence); | ||
} | ||
|
||
keypads.addFirst(nextKeypad); | ||
|
||
return shortestSequence; | ||
} | ||
|
||
} |
4 changes: 4 additions & 0 deletions
4
src/main/java/com/adventofcode/flashk/day21/redesign/KeypadPress.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package com.adventofcode.flashk.day21.redesign; | ||
|
||
public record KeypadPress(String currentButton, char nextButton) { | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.