Skip to content
Snippets Groups Projects
Commit e188270c authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Day 16 underway

parent 2b3ac36e
No related branches found
No related tags found
No related merge requests found
......@@ -606,5 +606,22 @@ I don't think I'll do that, though, since I can optimize the part 2 solution for
## Day 16
- [The problem](https://adventofcode.com/2022/day/16)
- [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day16.java)
### Part 1
The subproblems are
- Parse the input to determine how much flow is possible with each valve and to create a graph of the tunnels
- Find the (partial) walk that maximizes the flow within the allotted time
I'm feeling a dynamic programming solution is in order.
### Part 2
...
## Day 17
(coming soon)
package edu.unl.cse.bohn.year2022;
import edu.unl.cse.bohn.Puzzle;
import java.util.*;
@SuppressWarnings("unused")
public class Day16 extends Puzzle {
public static final int TIME_REMAINING = 30;
public Day16(boolean isProductionReady) {
super(isProductionReady);
sampleData = """
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
Valve BB has flow rate=13; tunnels lead to valves CC, AA
Valve CC has flow rate=2; tunnels lead to valves DD, BB
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
Valve EE has flow rate=3; tunnels lead to valves FF, DD
Valve FF has flow rate=0; tunnels lead to valves EE, GG
Valve GG has flow rate=0; tunnels lead to valves FF, HH
Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II""";
}
@Override
public long computePart1(List<String> data) {
Valve.createValveNetwork(data);
String startingLocation = data.get(0).substring(6, 8);
return Valve.getOptimalFlow(TIME_REMAINING, "AA", false);
}
@Override
public long computePart2(List<String> data) {
return 0;
}
private static class Valve {
private static Map<String, Valve> valves = null;
private static Map<Integer, Map<String, Map<Boolean, Integer>>> optimalFlows = null;
@SuppressWarnings("FieldCanBeLocal")
private final String name;
private final int flowRate;
private final Set<String> adjacentValves;
private Valve(String name, int flowRate, String[] adjacentValves) {
this.name = name;
this.flowRate = flowRate;
this.adjacentValves = Set.of(adjacentValves);
}
public static void createValveNetwork(List<String> descriptions) {
valves = new HashMap<>();
optimalFlows = new HashMap<>();
for (String description : descriptions) {
String name = description.substring(6, 8);
String[] descriptionHalves = description.split(";");
int flowRate = Integer.parseInt(descriptionHalves[0].split("=")[1]);
String neighborsString = descriptionHalves[1].split("valve")[1].strip();
if (neighborsString.startsWith("s ")) {
neighborsString = neighborsString.substring(2);
}
String[] adjacentValves = neighborsString.split(", ");
valves.put(name, new Valve(name, flowRate, adjacentValves));
}
}
public static int getOptimalFlow(int timeRemaining, String valveName, boolean valveIsAlreadyOpen) {
if (optimalFlows == null) {
throw new IllegalStateException("Cannot calculate optimal flow without creating valve network first.");
}
int depthPreviouslyCalculated = optimalFlows.size();
if (timeRemaining < depthPreviouslyCalculated) {
return optimalFlows.get(timeRemaining).get(valveName).get(valveIsAlreadyOpen);
}
/* TODO: incorporate time to determine "eventual total pressure release" */
for (int t = depthPreviouslyCalculated; t <= timeRemaining; t++) {
HashMap<String, Map<Boolean, Integer>> depthOptima = new HashMap<>();
for (String valve : valves.keySet()) {
HashMap<Boolean, Integer> valveOptima = new HashMap<>();
if (t == 0) {
valveOptima.put(true, 0);
valveOptima.put(false, 0);
} else {
int depth = t - 1;
// if the valve is already open then we must move
int optimalFlow = valves.get(valve).adjacentValves.stream()
.map(name -> optimalFlows.get(depth).get(name).get(true))
.max(Integer::compareTo).orElseThrow();
valveOptima.put(true, optimalFlow);
// if the valve is still closed then...
// option 1: move to an adjacent valve
int optimalFlowByMoving = valves.get(valve).adjacentValves.stream()
.map(name -> optimalFlows.get(depth).get(name).get(false))
.max(Integer::compareTo).orElseThrow();
// option 2: turn the current valve
int optimalFlowByOpeningValve = valves.get(valve).flowRate
+ optimalFlows.get(depth).get(valve).get(true);
valveOptima.put(false, Math.max(optimalFlowByMoving, optimalFlowByOpeningValve));
}
depthOptima.put(valve, valveOptima);
}
optimalFlows.put(t, depthOptima);
}
return optimalFlows.get(timeRemaining).get(valveName).get(valveIsAlreadyOpen);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment