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

  • SteveDinn@lemmy.ca
    link
    fedilink
    arrow-up
    2
    ·
    4 days ago

    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();
    }