diff --git a/src/AdventOfCode/Day18.cs b/src/AdventOfCode/Day18.cs new file mode 100644 index 0000000..0efc5cb --- /dev/null +++ b/src/AdventOfCode/Day18.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using AdventOfCode.Utilities; + +namespace AdventOfCode +{ + /// + /// Solver for Day 18 + /// + public class Day18 + { + public int Part1(string[] input) + { + HashSet points = new(); + Point2D current = (0, 0); + + points.Add(current); + + foreach (string line in input) + { + Bearing direction = line[0] switch + { + 'U' => Bearing.North, + 'D' => Bearing.South, + 'R' => Bearing.East, + 'L' => Bearing.West, + _ => throw new ArgumentOutOfRangeException() + }; + + int steps = line.Numbers().First(); + + foreach (Point2D next in Dig(current, direction, steps)) + { + points.Add(next); + current = next; + } + } + + int minX = points.MinBy(p => p.X).X; + int maxX = points.MaxBy(p => p.X).X; + int minY = points.MinBy(p => p.Y).Y; + int maxY = points.MaxBy(p => p.Y).Y; + + StringBuilder s = new(); + + for (int y = minY; y <= maxY; y++) + { + s.Append($"{y:D4}: "); + + for (int x = minX; x <= maxX; x++) + { + s.Append(points.Contains((x, y)) ? '#' : '.'); + } + + s.AppendLine(); + } + + Debug.WriteLine(s.ToString()); + + // from visual inspection, flood fill will work instead of the parity checking style from a previous day + + Point2D point = (Enumerable.Range(minX, maxX - minX).First(x => points.Contains((x, 0)) && !points.Contains((x + 1, 0))) + 1, 0); + + Queue queue = new(); + queue.Enqueue(point); + + while (queue.Count > 0) + { + point = queue.Dequeue(); + + if (points.Contains(point)) + { + continue; + } + + points.Add(point); + + foreach (Point2D next in point.Adjacent4().Where(n => !points.Contains(n))) + { + queue.Enqueue(next); + } + } + + return points.Count; + } + + public int Part2(string[] input) + { + foreach (string line in input) + { + throw new NotImplementedException("Part 2 not implemented"); + } + + return 0; + } + + private static IEnumerable Dig(Point2D start, Bearing direction, int steps) + { + Point2D current = start; + + for (int i = 0; i < steps; i++) + { + current = current.Move(direction); + yield return current; + } + } + } +} diff --git a/src/AdventOfCode/inputs/day18.txt b/src/AdventOfCode/inputs/day18.txt new file mode 100644 index 0000000..cf56975 Binary files /dev/null and b/src/AdventOfCode/inputs/day18.txt differ diff --git a/tests/AdventOfCode.Tests/Day18Tests.cs b/tests/AdventOfCode.Tests/Day18Tests.cs new file mode 100644 index 0000000..c8f8dec --- /dev/null +++ b/tests/AdventOfCode.Tests/Day18Tests.cs @@ -0,0 +1,65 @@ +using System.IO; +using Xunit; +using Xunit.Abstractions; + + +namespace AdventOfCode.Tests +{ + public class Day18Tests + { + private readonly ITestOutputHelper output; + private readonly Day18 solver; + + public Day18Tests(ITestOutputHelper output) + { + this.output = output; + this.solver = new Day18(); + } + + private static string[] GetRealInput() + { + string[] input = File.ReadAllLines("inputs/day18.txt"); + return input; + } + + private static string[] GetSampleInput() + { + return new string[] + { + + }; + } + + [Fact] + public void Part1_RealInput_ProducesCorrectResponse() + { + var expected = 46394; + + var result = solver.Part1(GetRealInput()); + output.WriteLine($"Day 18 - Part 1 - {result}"); + + Assert.Equal(expected, result); + } + + [Fact] + public void Part2_SampleInput_ProducesCorrectResponse() + { + var expected = -1; + + var result = solver.Part2(GetSampleInput()); + + Assert.Equal(expected, result); + } + + [Fact] + public void Part2_RealInput_ProducesCorrectResponse() + { + var expected = -1; + + var result = solver.Part2(GetRealInput()); + output.WriteLine($"Day 18 - Part 2 - {result}"); + + Assert.Equal(expected, result); + } + } +}