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

Completed Year 2022 Day 12

parent b552498b
No related branches found
No related tags found
No related merge requests found
......@@ -477,5 +477,42 @@ Monkey 3 inspected items 103 times.
## Day 12
First, a closing thought on yesterday's problem.
The concept I stumbled upon is the [Chinese Remainder Theorem](https://en.wikipedia.org/wiki/Chinese_remainder_theorem)
which apparently has an [Advent](https://twitter.com/Lincoln81/status/1446897782351089675)
[of](https://twitter.com/fixedpointfae/status/1601842705541517313)
[Code](https://twitter.com/PeopleNArthax/status/1601936116055408640)
[reputation](https://twitter.com/DarkCisum/status/1338382928129224705).
And now on to today's adventure.
- [The problem](https://adventofcode.com/2022/day/12)
- [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day12.java)
### Part 1
Speaking of AOC staples, it looks like today we need to implement a shortest path algorithm.
The subproblems are
- Create locations and build a reachability graph (unweighted, directional)
- Compare heights
- Find the shortest path from the start to the finish
My critique of my part 1 solution
- I'm not thrilled that I'm storing the distance from the start as a `Location` attribute; I suppose the alternative is
to create a `Map<Location,Integer>`
### Part 2
The difference is that we're now examining many possible starting locations.
A naïve approach would be to run the algorithm I developed for part 1, which starts at `start`, using each 'a'
`Location` as a starting point, in turn.
Alternatively, we could work backwards from `finish` and find the distance of each `Location` to the `finish`.
Then look for the shortest distance to the finish from the 'a' `Location`s.
## Day 13
(coming soon)
package edu.unl.cse.bohn.year2022;
import edu.unl.cse.bohn.Puzzle;
import java.util.*;
import java.util.stream.Collectors;
@SuppressWarnings("unused")
public class Day12 extends Puzzle {
public Day12(boolean isProductionReady) {
super(isProductionReady);
//noinspection SpellCheckingInspection
sampleData = """
Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi""";
}
private Location start = null, finish = null;
private Set<Location> locations;
@Override
public long computePart1(List<String> data) {
buildReachabilityGraph(data);
computeDistancesToFinish(false);
return start.getDistanceToFinish();
}
@Override
public long computePart2(List<String> data) {
if (start == null) {
this.computePart1(data);
}
return locations.stream()
.filter(location -> location.getElevation() == 'a')
.map(Location::getDistanceToFinish)
.min(Integer::compareTo).orElseThrow();
}
private void computeDistancesToFinish(@SuppressWarnings("SameParameterValue") boolean verbose) {
int numberOfLocations = locations.size();
PriorityQueue<Location> locationsToVisit = new PriorityQueue<>();
finish.updateDistanceFromFinish(0);
locationsToVisit.add(finish);
Location currentLocation;
while (!locationsToVisit.isEmpty()) {
currentLocation = locationsToVisit.remove();
for (Location reachableLocation : currentLocation.getReachableLocations()) {
if (reachableLocation.updateDistanceFromFinish(currentLocation.getDistanceToFinish() + 1)) {
locationsToVisit.remove(reachableLocation); // just in case it's already there
locationsToVisit.add(reachableLocation);
}
if (verbose) {
System.out.println("Number of locations to visit = " + locationsToVisit.size()
+ " (out of " + numberOfLocations + ")");
}
if (locationsToVisit.size() > numberOfLocations) {
throw new IllegalStateException("The queue contains more locations (" + locationsToVisit.size()
+ ") than exist (" + numberOfLocations + ").");
}
}
}
}
private void buildReachabilityGraph(List<String> data) {
// create the locations
Location[][] locations = new Location[data.size()][data.get(0).length()];
for (int i = 0; i < data.size(); i++) {
for (int j = 0; j < data.get(i).length(); j++) {
char elevation = data.get(i).charAt(j);
switch (elevation) {
case 'S' -> {
locations[i][j] = new Location('a');
start = locations[i][j];
}
case 'E' -> {
locations[i][j] = new Location('z');
finish = locations[i][j];
}
default -> locations[i][j] = new Location(elevation);
}
}
}
// build the graph
for (int i = 0; i < locations.length; i++) {
for (int j = 0; j < locations[i].length; j++) {
if (i > 0) {
locations[i][j].setLocationAsReachableIfNotTooTall(locations[i - 1][j]);
}
if (i < locations.length - 1) {
locations[i][j].setLocationAsReachableIfNotTooTall(locations[i + 1][j]);
}
if (j > 0) {
locations[i][j].setLocationAsReachableIfNotTooTall(locations[i][j - 1]);
}
if (j < locations[i].length - 1) {
locations[i][j].setLocationAsReachableIfNotTooTall(locations[i][j + 1]);
}
}
}
this.locations = Arrays.stream(locations).flatMap(Arrays::stream).collect(Collectors.toSet());
}
private static class Location implements Comparable<Location> {
private final Set<Location> reachableLocations;
private final char elevation;
private int distanceToFinish;
public Location(char elevation) {
this.elevation = elevation;
this.reachableLocations = new HashSet<>();
this.distanceToFinish = Integer.MAX_VALUE;
}
public void setLocationAsReachableIfNotTooTall(Location otherLocation) {
if (this.elevation <= otherLocation.elevation + 1) {
reachableLocations.add(otherLocation);
}
}
public boolean updateDistanceFromFinish(int possiblyShorterDistance) {
boolean newDistanceIsShorter = possiblyShorterDistance < distanceToFinish;
distanceToFinish = newDistanceIsShorter ? possiblyShorterDistance : distanceToFinish;
return newDistanceIsShorter;
}
public int getDistanceToFinish() {
return distanceToFinish;
}
public boolean canReach(Location destination) {
return reachableLocations.contains(destination);
}
public Set<Location> getReachableLocations() {
return Collections.unmodifiableSet(reachableLocations);
}
public char getElevation() {
return elevation;
}
@Override
public int compareTo(Location other) {
return this.elevation - other.elevation;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment