Skip to content

Commit 0927ae7

Browse files
committed
Day 12
1 parent 088a3c2 commit 0927ae7

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

src/test/java/com/macasaet/Day12.java

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package com.macasaet;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.util.ArrayList;
6+
import java.util.Collections;
7+
import java.util.HashMap;
8+
import java.util.List;
9+
import java.util.Objects;
10+
import java.util.PriorityQueue;
11+
import java.util.stream.StreamSupport;
12+
13+
/**
14+
* --- Day 12: Hill Climbing Algorithm ---
15+
* <a href="https://adventofcode.com/2022/day/12">https://adventofcode.com/2022/day/12</a>
16+
*/
17+
public class Day12 {
18+
19+
record Coordinate(int x, int y) {
20+
}
21+
22+
public record HeightMap(int[][] grid, Coordinate start, Coordinate end) {
23+
24+
public int lengthOfShortestPath() {
25+
return this.lengthOfShortestPath(this.start);
26+
}
27+
28+
public int lengthOfShortestPath(final Coordinate startingPoint) {
29+
final var cheapestCostToNode = new HashMap<Coordinate, Integer>();
30+
cheapestCostToNode.put(startingPoint, 0);
31+
final var estimatedCostToFinish = new HashMap<Coordinate, Integer>();
32+
estimatedCostToFinish.put(startingPoint, estimateDistance(startingPoint, this.end));
33+
final var openSet = new PriorityQueue<Coordinate>((x, y) -> {
34+
final var xScore = estimatedCostToFinish.getOrDefault(x, Integer.MAX_VALUE);
35+
final var yScore = estimatedCostToFinish.getOrDefault(y, Integer.MAX_VALUE);
36+
return xScore.compareTo(yScore);
37+
});
38+
openSet.add(startingPoint);
39+
while (!openSet.isEmpty()) {
40+
final var current = openSet.remove();
41+
if (current.equals(this.end)) {
42+
return cheapestCostToNode.get(current);
43+
}
44+
for (final var neighbour : neighbours(current)) {
45+
final var tentativeGScore = cheapestCostToNode.get(current) + 1;
46+
if (tentativeGScore < cheapestCostToNode.getOrDefault(neighbour, Integer.MAX_VALUE)) {
47+
cheapestCostToNode.put(neighbour, tentativeGScore);
48+
estimatedCostToFinish.put(neighbour, tentativeGScore + estimateDistance(neighbour, this.end));
49+
if (!openSet.contains(neighbour)) {
50+
openSet.add(neighbour);
51+
}
52+
}
53+
}
54+
}
55+
return Integer.MAX_VALUE;
56+
}
57+
58+
public List<Coordinate> getPotentialTrailHeads() {
59+
final var list = new ArrayList<Coordinate>();
60+
for(int i = this.grid().length; --i >= 0; ) {
61+
final var row = this.grid()[i];
62+
for(int j = row.length; --j >= 0; ) {
63+
if(row[j] == 0) {
64+
list.add(new Coordinate(i, j));
65+
}
66+
}
67+
}
68+
return Collections.unmodifiableList(list);
69+
}
70+
71+
int height(final Coordinate coordinate) {
72+
return this.grid[coordinate.x()][coordinate.y()];
73+
}
74+
75+
List<Coordinate> neighbours(final Coordinate coordinate) {
76+
final var list = new ArrayList<Coordinate>(4);
77+
if (coordinate.x() > 0) {
78+
final var up = new Coordinate(coordinate.x() - 1, coordinate.y());
79+
if (height(coordinate) + 1 >= height(up)) {
80+
list.add(up);
81+
}
82+
}
83+
if (coordinate.x() < this.grid.length - 1) {
84+
final var down = new Coordinate(coordinate.x() + 1, coordinate.y());
85+
if (height(coordinate) + 1 >= height(down)) {
86+
list.add(down);
87+
}
88+
}
89+
if (coordinate.y() > 0) {
90+
final var left = new Coordinate(coordinate.x(), coordinate.y() - 1);
91+
if (height(coordinate) + 1 >= height(left)) {
92+
list.add(left);
93+
}
94+
}
95+
final var row = this.grid[coordinate.x()];
96+
if (coordinate.y() < row.length - 1) {
97+
final var right = new Coordinate(coordinate.x(), coordinate.y() + 1);
98+
if (height(coordinate) + 1 >= height(right)) {
99+
list.add(right);
100+
}
101+
}
102+
return Collections.unmodifiableList(list);
103+
}
104+
105+
int estimateDistance(final Coordinate from, final Coordinate to) {
106+
return (int) Math.sqrt(Math.pow(from.x() - to.x(), 2.0) + Math.pow(from.y() - to.y(), 2.0));
107+
}
108+
109+
}
110+
111+
protected HeightMap getInput() {
112+
final var charGrid = StreamSupport.stream(new LineSpliterator("day-12.txt"), false).map(line -> {
113+
final var list = new ArrayList<Character>(line.length());
114+
for (final var c : line.toCharArray()) {
115+
list.add(c);
116+
}
117+
return list;
118+
}).toList();
119+
Coordinate origin = null;
120+
Coordinate destination = null;
121+
int[][] grid = new int[charGrid.size()][];
122+
for(int i = charGrid.size(); --i >= 0; ) {
123+
final var row = charGrid.get(i);
124+
grid[i] = new int[row.size()];
125+
for(int j = row.size(); --j >= 0; ) {
126+
final char c = row.get(j);
127+
if(c == 'S') {
128+
origin = new Coordinate(i, j);
129+
grid[i][j] = 0;
130+
} else if(c == 'E') {
131+
destination = new Coordinate(i, j);
132+
grid[i][j] = 'z' - 'a';
133+
} else {
134+
grid[i][j] = c - 'a';
135+
}
136+
}
137+
}
138+
Objects.requireNonNull(origin);
139+
Objects.requireNonNull(destination);
140+
return new HeightMap(grid, origin, destination);
141+
}
142+
143+
@Test
144+
public final void part1() {
145+
final var map = getInput();
146+
final var result = map.lengthOfShortestPath();
147+
System.out.println("Part 1: " + result);
148+
}
149+
150+
@Test
151+
public final void part2() {
152+
final var map = getInput();
153+
var result = Integer.MAX_VALUE;
154+
for(final var candidate : map.getPotentialTrailHeads()) {
155+
final var length = map.lengthOfShortestPath(candidate);
156+
if(length < result) {
157+
result = length;
158+
}
159+
}
160+
161+
System.out.println("Part 2: " + result);
162+
}
163+
164+
}

src/test/resources/sample/day-12.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Sabqponm
2+
abcryxxl
3+
accszExk
4+
acctuvwj
5+
abdefghi

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy