Day 18: Ram Run
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
C#
Part 1 was straight forward Dykstra with a cost of 1 for each move. Part 2 was a binary search from the number of corrupted bytes given to us for Part 1 (where we know a path can be found) to the total number of corrupted bytes.
using System.Collections.Immutable; using System.Diagnostics; using Common; namespace Day18; static class Program { static void Main() { var start = Stopwatch.GetTimestamp(); var sampleInput = ReceiveInput("sample.txt"); var sampleBounds = new Point(7,7); var programInput = ReceiveInput("input.txt"); var programBounds = new Point(71, 71); Console.WriteLine($"Part 1 sample: {Part1(sampleInput, 12, sampleBounds)}"); Console.WriteLine($"Part 1 input: {Part1(programInput, 1024, programBounds)}"); Console.WriteLine($"Part 2 sample: {Part2(sampleInput, 12, sampleBounds)}"); Console.WriteLine($"Part 2 input: {Part2(programInput, 1024, programBounds)}"); Console.WriteLine($"That took about {Stopwatch.GetElapsedTime(start)}"); } static int Part1(ImmutableArray<Point> input, int num, Point bounds) => FindBestPath( new Point(0, 0), new Point(bounds.Row - 1, bounds.Col - 1), input.Take(num).ToImmutableHashSet(), bounds); static object Part2(ImmutableArray<Point> input, int num, Point bounds) { var start = num; var end = input.Length; while (start != end) { var check = (start + end) / 2; if (Part1(input, check, bounds) < 0) end = check; else start = check + 1; } var lastPoint = input[start - 1]; return $"{lastPoint.Col},{lastPoint.Row}"; } record struct State(Point Location, int Steps); static int FindBestPath(Point start, Point end, ISet<Point> corruptedBytes, Point bounds) { var seenStates = new Dictionary<Point, int>(); var queue = new Queue<State>(); queue.Enqueue(new State(start, 0)); while (queue.TryDequeue(out var state)) { if (state.Location == end) return state.Steps; if (seenStates.TryGetValue(state.Location, out var bestSteps)) { if (state.Steps >= bestSteps) continue; } seenStates[state.Location] = state.Steps; queue.EnqueueRange(state.Location.GetCardinalMoves() .Where(p => p.IsInBounds(bounds) && !corruptedBytes.Contains(p)) .Select(p => new State(p, state.Steps + 1))); } return -1; } static ImmutableArray<Point> ReceiveInput(string file) => File.ReadAllLines(file) .Select(l => l.Split(',')) .Select(p => new Point(int.Parse(p[1]), int.Parse(p[0]))) .ToImmutableArray(); }