diff --git a/src/14.cs b/src/14.cs index 8585875..062d840 100644 --- a/src/14.cs +++ b/src/14.cs @@ -2,38 +2,72 @@ internal class Day14 : Day { - private record point(int x, int y); - // Parses a string in the form "x,y" into a point - private static point ParsePoint(string str) + class point : IEquatable { - var parts = str.Trim().Split(','); - if (parts.Length != 2) + public bool Equals(point? other) { - throw new Exception($"found {parts.Length} pieces of input string, expected 2"); + return x == other?.x && y == other.y; } - var x = int.Parse(parts[0].Trim()); - var y = int.Parse(parts[1].Trim()); - return new point(x, y); + public override bool Equals(object? obj) + { + return Equals((point?) obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(x, y); + } + + public static bool operator ==(point? left, point? right) + { + return Equals(left, right); + } + + public static bool operator !=(point? left, point? right) + { + return !Equals(left, right); + } + + public point(int _x, int _y) + { + x = _x; + y = _y; + } + + public override string ToString() + { + return $"{x},{y}"; + } + + public int x; + public int y; + + // Parses a string in the form "x,y" into a point + public static point Parse(string str) + { + var parts = str.Trim().Split(','); + if (parts.Length != 2) + { + throw new Exception($"found {parts.Length} pieces of input string, expected 2"); + } + + var x = int.Parse(parts[0].Trim()); + var y = int.Parse(parts[1].Trim()); + return new point(x, y); + } } - enum cellType - { - sand, - wall, - } - - private readonly Dictionary grid = new(); + private readonly HashSet grid = new(); internal override void Parse() { foreach (var line in Util.Parsing.ReadAllLines("14")) { point? lastPoint = null; - var parts = line.Split(" -> "); - foreach (var part in parts) + var parts = line.Split(" -> ").Select(point.Parse); + foreach (var p in parts) { - var p = ParsePoint(part); if (lastPoint == null) { lastPoint = p; @@ -44,17 +78,16 @@ internal class Day14 : Day { for (int i = lastPoint.x; i != p.x; i += Math.Sign(p.x - lastPoint.x)) { - grid[p with {x = i}] = cellType.wall; + grid.Add(new point(i, p.y)); } } else if (p.y != lastPoint.y) { for (int i = lastPoint.y; i != p.y; i += Math.Sign(p.y - lastPoint.y)) { - grid[p with {y = i}] = cellType.wall; + grid.Add(new point(p.x, i)); } } - grid[p] = cellType.wall; lastPoint = p; } } @@ -62,26 +95,30 @@ internal class Day14 : Day internal override string Part1() { - var g = new Dictionary(grid); - int lowestY = g.MaxBy(pair => pair.Key.y).Key.y; + var g = new HashSet(grid); + int lowestY = g.MaxBy(p => p.y)!.y; point dropPoint = new point(500, 0); bool hitVoid = false; int numDroppedSand = 0; + point sandLoc = new point(dropPoint.x, dropPoint.y); + point nextPoint = new point(sandLoc.x, sandLoc.y + 1); while (!hitVoid) { bool atRest = false; - point sandLoc = dropPoint with {y = dropPoint.y + 1}; + sandLoc.x = dropPoint.x; + sandLoc.y = dropPoint.y; while (!atRest) { - var nextPoint = sandLoc with {y = sandLoc.y + 1}; - if (g.ContainsKey(nextPoint)) + nextPoint.x = sandLoc.x; + nextPoint.y = sandLoc.y + 1; + if (g.Contains(nextPoint)) { - nextPoint = nextPoint with {x = sandLoc.x - 1}; - if (g.ContainsKey(nextPoint)) + nextPoint.x = sandLoc.x - 1; + if (g.Contains(nextPoint)) { - nextPoint = nextPoint with {x = sandLoc.x + 1}; - if (g.ContainsKey(nextPoint)) + nextPoint.x = sandLoc.x + 1; + if (g.Contains(nextPoint)) { atRest = true; } @@ -90,7 +127,8 @@ internal class Day14 : Day if (!atRest) { - sandLoc = nextPoint; + sandLoc.x = nextPoint.x; + sandLoc.y = nextPoint.y; } if (nextPoint.y > lowestY) @@ -103,7 +141,7 @@ internal class Day14 : Day if (!hitVoid) { numDroppedSand++; - g[sandLoc] = cellType.sand; + g.Add(new point(sandLoc.x, sandLoc.y)); } } @@ -112,31 +150,36 @@ internal class Day14 : Day internal override string Part2() { - var g = new Dictionary(grid); - int lowestY = g.MaxBy(pair => pair.Key.y).Key.y; + var g = new HashSet(grid); + int lowestY = g.MaxBy(p => p.y)!.y; int floor = 2 + lowestY; point dropPoint = new point(500, 0); int numDroppedSand = 0; + point sandLoc = new point(dropPoint.x, dropPoint.y); + point nextPoint = new point(sandLoc.x, sandLoc.y + 1); while (true) { bool atRest = false; - point sandLoc = dropPoint; + sandLoc.x = dropPoint.x; + sandLoc.y = dropPoint.y; while (!atRest) { - var nextPoint = sandLoc with {y = sandLoc.y + 1}; + nextPoint.x = sandLoc.x; + nextPoint.y = sandLoc.y + 1; + if (nextPoint.y == floor) { break; } - if (g.ContainsKey(nextPoint)) + if (g.Contains(nextPoint)) { - nextPoint = nextPoint with {x = sandLoc.x - 1}; - if (g.ContainsKey(nextPoint)) + nextPoint.x = sandLoc.x - 1; + if (g.Contains(nextPoint)) { - nextPoint = nextPoint with {x = sandLoc.x + 1}; - if (g.ContainsKey(nextPoint)) + nextPoint.x = sandLoc.x + 1; + if (g.Contains(nextPoint)) { atRest = true; } @@ -145,11 +188,12 @@ internal class Day14 : Day if (!atRest) { - sandLoc = nextPoint; + sandLoc.x = nextPoint.x; + sandLoc.y = nextPoint.y; } } - g[sandLoc] = cellType.sand; + g.Add(new point(sandLoc.x, sandLoc.y)); numDroppedSand++; if (sandLoc == dropPoint)