mirror of
https://github.com/parnic/advent-of-code-2022.git
synced 2025-06-16 13:40:13 -05:00
Day 12 solution
This is quite slow, at least for part 2 (and part 1 is slower than I want it to be, event parse takes longer than I thought it should). I need a better approach to the second part. Probably need to mark all nodes' distances from the goal point instead of one-by-one plotting a path from each possible start to the end, but that requires an adjustment to how I'm building the graph in the first place.
This commit is contained in:
@ -57,6 +57,7 @@
|
|||||||
<EmbeddedResource Include="inputs\11a.txt" />
|
<EmbeddedResource Include="inputs\11a.txt" />
|
||||||
<EmbeddedResource Include="inputs\12.txt" />
|
<EmbeddedResource Include="inputs\12.txt" />
|
||||||
<None Remove="inputs\13.txt" />
|
<None Remove="inputs\13.txt" />
|
||||||
|
<EmbeddedResource Include="inputs\12a.txt" />
|
||||||
<EmbeddedResource Include="inputs\13.txt" />
|
<EmbeddedResource Include="inputs\13.txt" />
|
||||||
<None Remove="inputs\14.txt" />
|
<None Remove="inputs\14.txt" />
|
||||||
<EmbeddedResource Include="inputs\14.txt" />
|
<EmbeddedResource Include="inputs\14.txt" />
|
||||||
|
@ -1,24 +1,41 @@
|
|||||||
rf-RL
|
abcccaaaaaaccccccccaaaaaccccccaaaaaaccccccaaaaaaaacccaaaaaaaccaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa
|
||||||
rf-wz
|
abcccaaaaaacccccccaaaaaaccccaaaaaaaacccccccaaaaaaaaaaaaaaaaccaaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa
|
||||||
wz-RL
|
abccccaaaaacaaaccaaaaaaaacccaaaaaaaaacccccccaaaaaaaaaaaaaaaacaaaaaacccccccccaaacccccccccccaaaaaaaaccccccccccaaccccccccccccccccaaaaaa
|
||||||
AV-mh
|
abccccaaaaccaaaaaaaaaaaaacccaaaaaaaaaacccccaaaaaaaaaaaaaaaaaaacaaaacccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccccccccccccccccccaaa
|
||||||
end-wz
|
abcccccccccaaaaaacccaacccccccccaaacaaaccccccaacccccccaaaaaaaaacaacccccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccacaaccccccccccccaaa
|
||||||
end-dm
|
abcccccccccaaaaaacccaacccccccccaaacccccccccccccccccccaaaacaaaacccccccaacaaccaaaccccccccccaccaaaaacacccccccccaaaacaaaaccccccccccccaac
|
||||||
wz-gy
|
abccccccccccaaaaacccccccccccccccacccaaaacccccccccccccaaaacccccccccccccaaaacccccccccccaacccccaaaaccccccccjjjjaaaaaaaaaccccccccccccccc
|
||||||
wz-dm
|
abccccccccccaaaacccccccccccccccccccaaaaacccccccccccccaaaccccccccccccccaaaaacccccccccaaaaaacccaaccccccccjjjjjjkkaaaacccccccccaacccccc
|
||||||
cg-AV
|
abcccccaaccccccccccccccccccccccccccaaaaaacccccccccccccaacccccccccccccaaaaaaccccccccccaaaaaccccccccccccjjjjjjjkkkkaacccccaacaaacccccc
|
||||||
rf-AV
|
abccaaaacccccccccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccaaaacaccccccccaaaaaaaccccaacccccjjjjoooookkkkkkkklllaaaaaaacccc
|
||||||
rf-gy
|
abccaaaaaacccccccccccccccccccccccccaaaaacccccccccccccccccccccccccccccccaaccccccccccaaaaaaaaccaaaaccccjjjoooooookkkkkkkllllaaaaaacccc
|
||||||
end-mh
|
abcccaaaaacccccccccccccccccccccccccccaaaccccccccaaaacccccccccccccccccccccccccccccccaaaaaaaaccaaaaccccjjooooooooppkkppplllllaccaacccc
|
||||||
cg-gy
|
abccaaaaaccccccccccccaccccccccccccccccccccccccccaaaacccccccccccccccccccccccccccccccccaaacacccaaaacccijjooouuuuoppppppppplllccccccccc
|
||||||
cg-RL
|
abcccccaacccccccccccaaaaaaaaccccccccccccccccccccaaaaccccaaccccccccaaacccccccccccccaacaaccccccccccccciijoouuuuuuppppppppplllcccaccccc
|
||||||
gy-RL
|
abcccccccccccccccccccaaaaaaccccccccccccccccccccccaaccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiiiootuuuuuupuuuvvpppllccccccccc
|
||||||
VI-gy
|
abcccccccccccccccccccaaaaaaccaaaaacccccccccccccccccccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiinnotuuxxxuuuuvvvpppllccccccccc
|
||||||
AV-gy
|
abccccccccccccccacccaaaaaaaacaaaaaaacccccccccccccccccccaaaacccccccaaacccccaaaaccaaaaaccccaaccccccciiiinnnttxxxxuuyyyvvqqqllccccccccc
|
||||||
dm-rf
|
abcccccccccccaaaaccaaaaaaaaaaaaaaaaaaccaacccccccccccccccccccccccccccccccccaaaacccaaaaaccaaacccccciiinnnnnttxxxxxyyyyvvqqqllccccccccc
|
||||||
start-cg
|
abaaaacccccccaaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccaaaacccaaaaaacaaaccccciiinnnnttttxxxxxyyyyvvqqmmmccccccccc
|
||||||
start-RL
|
abaaaaccccccccaaaaacccaaaaacaaaaaacaaaaaaccccccccccccccccaaccccccccccccccccaacccccccaaaaaaaaaaciiinnnnttttxxxxxyyyyvvqqqmmmccccccccc
|
||||||
rf-mh
|
SbaaaacccccccaaaaaccccaaaaaccaaaaaaaaaaaccccccccccccccccaaacaacccccccccccccccccccccccaaaaaaaaachhhnnntttxxxEzzzzyyvvvqqqmmmccccccccc
|
||||||
AV-start
|
abaaaacccccccaacaacccccaaaaaaaacaaaaaaaaaccccccccccccccccaaaaaccccccccccccccccccccccccaaaaaaacchhhnnntttxxxxxyyyyyyvvvqqmmmdddcccccc
|
||||||
qk-mh
|
abaaaacccccccccccccccccccaaaaaacaaaaaaaaaacccccccccccccaaaaaaccccccccaaaccccccccccccccaaaaaaccchhhnnntttxxxxywyyyyyyvvvqqmmmdddccccc
|
||||||
wz-mh
|
abaacccccccccccccccccccaaaaaaacccccaaaaaaacccccccccccccaaaaaaaacccccaaaacccccccccccccaaaaaaacaahhhmmmttttxxwwyyyyyyyvvvqqmmmdddccccc
|
||||||
|
abcccccccccccccccccccccaaaaaaacaaccaaacccccccccccccccccaacaaaaacccccaaaacccccccccccccaaacaaaaaahhhmmmmtsssswwyywwwwvvvvqqqmmdddccccc
|
||||||
|
abcccccccccccccccaaaccccaaaaaaaaaacaaccaaccccccccccccccccaaacaccccccaaaacccccccccccccccccaaaaacahhhmmmmmsssswwywwwwwvvrrqqmmdddccccc
|
||||||
|
abcccccccccccccaaaaaaccccaaaaaaaaaccaaaacccccccccccccccccaacccccccccccccccccccccccaaaccccaaaaaaahhhhhmmmmssswwwwwrrrrrrrrmmmmddccccc
|
||||||
|
abcccccccccccccaaaaaaccccaaaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaacccccaaaaachhhhhmmmmsswwwwrrrrrrrrrkkmdddccccc
|
||||||
|
abccccccccccccccaaaaaccccccaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaaccccaaaaacccchhggmmmssswwrrrrrkkkkkkkkdddacccc
|
||||||
|
abccaaaacccccccaaaaacccccccccaaaaaacaaaaacccccccccccccccccccccccccccccccccccccccaaaaaaccccaacaaaccccggggmmsssssrrlkkkkkkkkkdddaccccc
|
||||||
|
abccaaaacccccccaaaaacccccccccaaaaaaccccaacccccccccccccccccccccccccccccccccccccccaaaaaccccccccaaccccccgggmllssssrllkkkkkkkeeeddaccccc
|
||||||
|
abccaaaacccccccaaacccccccccccaaaaaacccccccccccccccccccaacccccccccccccccccccccccaaaaaacccccccccccccccccggllllssslllkkeeeeeeeeeaaacccc
|
||||||
|
abcccaaccccccccaaacaaaccccccaaaaaaaaaaacccccccccccccaaaaaacccccccccccccccccccccaaacaaacccccaacccccccccggglllllllllfeeeeeeeeaaaaacccc
|
||||||
|
abccccccccccaaaaaaaaaaccccccccccccaccaaaccacccccccccaaaaaaccccaaccaacccaaccccccaaaaaaacccccaaccccccccccggglllllllfffeeecccaaaaaacccc
|
||||||
|
abccccccccccaaaaaaaaacccccccccccccccaaaaaaaccccccccccaaaaaccccaaaaaacccaaaaaaccaaaaaacccaaaaaaaacccccccggggllllfffffccccccaacccccccc
|
||||||
|
abcccccccccccaaaaaaacccccccccccccccccaaaaaaccaacccccaaaaaccccccaaaaacccaaaaaacaaaaaaacccaaaaaaaaccccccccgggffffffffccccccccccccccccc
|
||||||
|
abccccccccccccaaaaaaacccccccccccccaaaaaaaaacaaaaccccaaaaacaaaaaaaaaacaaaaaaacaaaaaaaaaccccaaaacccccccccccggffffffacccccccccccccccaaa
|
||||||
|
abccccccccccccaaaaaaacaaccccccccccaaaaaaaaacaaaacccccaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaacccaaaaacccccccccccaffffaaaaccccccccccccccaaa
|
||||||
|
abccccccccccccaaacaaaaaacccccccccccaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaacccaaacaaaccaaaaaacccccccccccccccccaaaccccccccccccccaaa
|
||||||
|
abccccccccccccaaccaaaaaccccccccccccccaaaaaaaccccaaaaaaaaaaaaccccaacccccaaaaaacccaaaccccccaaccaacccccccccccccccccaaacccccccccccaaaaaa
|
||||||
|
abcccccccccccccccaaaaaaaaccccccccccccaacccacccccccaaaaaaaaaaccccaacccccaaccccccccaccccccccccccccccccccccccccccccccccccccccccccaaaaaa
|
5
inputs/12a.txt
Normal file
5
inputs/12a.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Sabqponm
|
||||||
|
abcryxxl
|
||||||
|
accszExk
|
||||||
|
acctuvwj
|
||||||
|
abdefghi
|
211
src/12.cs
Normal file
211
src/12.cs
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
namespace aoc2022;
|
||||||
|
|
||||||
|
internal class Day12 : Day
|
||||||
|
{
|
||||||
|
class point : IEquatable<point>
|
||||||
|
{
|
||||||
|
public bool Equals(point? other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, other)) return false;
|
||||||
|
if (ReferenceEquals(this, other)) return true;
|
||||||
|
return x == other.x && y == other.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => HashCode.Combine(x, y);
|
||||||
|
|
||||||
|
public readonly int x;
|
||||||
|
public readonly int y;
|
||||||
|
|
||||||
|
public static point operator +(point p, point other) => new(p.x + other.x, p.y + other.y);
|
||||||
|
public static bool operator ==(point p, point other) => p.x == other.x && p.y == other.y;
|
||||||
|
public static bool operator !=(point p, point other) => !(p == other);
|
||||||
|
public override bool Equals(object? obj) => obj is point p && p == this;
|
||||||
|
public override string ToString() => $"{x},{y}";
|
||||||
|
|
||||||
|
public point(int _x, int _y)
|
||||||
|
{
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DNode : IEquatable<DNode>
|
||||||
|
{
|
||||||
|
public bool Equals(DNode? other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, other)) return false;
|
||||||
|
if (ReferenceEquals(this, other)) return true;
|
||||||
|
return neighbors.Equals(other.neighbors)
|
||||||
|
&& distance == other.distance
|
||||||
|
&& location.Equals(other.location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
if (obj.GetType() != this.GetType()) return false;
|
||||||
|
return Equals((DNode) obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(DNode? left, DNode? right)
|
||||||
|
{
|
||||||
|
return Equals(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(DNode? left, DNode? right)
|
||||||
|
{
|
||||||
|
return !Equals(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly List<DNode> neighbors = new();
|
||||||
|
public readonly point location;
|
||||||
|
public long? distance;
|
||||||
|
|
||||||
|
public DNode(point loc)
|
||||||
|
{
|
||||||
|
location = loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => HashCode.Combine(neighbors, location);
|
||||||
|
public override string ToString() => $"{location}, {neighbors.Count} neighbor{(neighbors.Count == 1 ? "" : "s")}, dist: {distance ?? -1}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly HashSet<DNode> allNodes = new();
|
||||||
|
private DNode? startNode;
|
||||||
|
private DNode? goalNode;
|
||||||
|
|
||||||
|
private int[][]? heights;
|
||||||
|
private point? start;
|
||||||
|
private point? goal;
|
||||||
|
|
||||||
|
private readonly point[] offsets = new point[]
|
||||||
|
{
|
||||||
|
new(-1, 0),
|
||||||
|
new(1, 0),
|
||||||
|
new(0, -1),
|
||||||
|
new(0, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
internal override void Parse()
|
||||||
|
{
|
||||||
|
var lines = new List<string>(Util.Parsing.ReadAllLines("12"));
|
||||||
|
heights = new int[lines.Count][];
|
||||||
|
for (int x = 0; x < lines.Count; x++)
|
||||||
|
{
|
||||||
|
var line = lines[x];
|
||||||
|
heights[x] = new int[line.Length];
|
||||||
|
for (int y = 0; y < line.Length; y++)
|
||||||
|
{
|
||||||
|
var ch = line[y];
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 'S':
|
||||||
|
start = new(x, y);
|
||||||
|
ch = 'a';
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
goal = new(x, y);
|
||||||
|
ch = 'z';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
heights[x][y] = ch - 'a';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startNode = new DNode(start!);
|
||||||
|
allNodes.Add(startNode);
|
||||||
|
|
||||||
|
var unvisited = new HashSet<DNode>(allNodes);
|
||||||
|
DNode? current = startNode;
|
||||||
|
while (current != null)
|
||||||
|
{
|
||||||
|
var currHeight = heights[current.location.x][current.location.y];
|
||||||
|
foreach (var offset in offsets)
|
||||||
|
{
|
||||||
|
var test = current.location + offset;
|
||||||
|
if (test.x < 0 || test.y < 0 || test.x >= heights.Length || test.y >= heights[0].Length)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var testHeight = heights[test.x][test.y];
|
||||||
|
if (testHeight <= currHeight + 1)
|
||||||
|
{
|
||||||
|
var found = allNodes.FirstOrDefault(n => n.location == test);
|
||||||
|
if (found == null)
|
||||||
|
{
|
||||||
|
found = new DNode(test);
|
||||||
|
allNodes.Add(found);
|
||||||
|
unvisited.Add(found);
|
||||||
|
}
|
||||||
|
current.neighbors.Add(found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unvisited.Remove(current);
|
||||||
|
current = unvisited.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
goalNode = allNodes.First(n => n.location == goal!);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long? FindDistance(DNode from, DNode to)
|
||||||
|
{
|
||||||
|
long? distance = null;
|
||||||
|
|
||||||
|
allNodes.ForEach(n =>
|
||||||
|
{
|
||||||
|
n.distance = null;
|
||||||
|
});
|
||||||
|
from.distance = 0;
|
||||||
|
|
||||||
|
var unvisited = new HashSet<DNode>(allNodes);
|
||||||
|
DNode? current = from;
|
||||||
|
while (current != null)
|
||||||
|
{
|
||||||
|
foreach (var n in current.neighbors.Where(n => unvisited.Contains(n)))
|
||||||
|
{
|
||||||
|
if (n.distance == null || n.distance > current.distance + 1)
|
||||||
|
{
|
||||||
|
n.distance = current.distance + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unvisited.Remove(current);
|
||||||
|
if (current == to)
|
||||||
|
{
|
||||||
|
distance = current.distance;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = unvisited.MinBy(n => n.distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override string Part1()
|
||||||
|
{
|
||||||
|
var dist = FindDistance(startNode!, goalNode!);
|
||||||
|
|
||||||
|
return $"Shortest distance from start to end: <+white>{dist ?? -1}";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override string Part2()
|
||||||
|
{
|
||||||
|
long? shortestDist = null;
|
||||||
|
var aNodes = allNodes.Where(n => heights![n.location.x][n.location.y] == 0);
|
||||||
|
foreach (var n in aNodes)
|
||||||
|
{
|
||||||
|
var dist = FindDistance(n, goalNode!);
|
||||||
|
if (shortestDist == null || dist < shortestDist)
|
||||||
|
{
|
||||||
|
shortestDist = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"Shortest distance from any minimum-height point to end: <+white>{shortestDist}";
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user