01020304050607080910111213141516171819202122232425

Advent of Code

2024/18

RAM Run

in C#

by encse

You and The Historians look a lot more pixelated than you remember. You're inside a computer at the North Pole!

Just as you're about to check out your surroundings, a program runs up to you. "This region of memory isn't safe! The User misunderstood what a pushdown automaton is and their algorithm is pushing whole bytes down on top of us! Run!"

Visit the website for the full story and full puzzle description.

We got a simple path finding problem for today. I implemented a binary search for the second part.

namespace AdventOfCode.Y2024.Day18;

using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Numerics;
using AngleSharp.Common;

[ProblemName("RAM Run")]
class Solution : Solver {

    public object PartOne(string input) => Distance(GetBlocks(input).Take(1024));

    public object PartTwo(string input) {
        // find the first block position that will cut off the goal position
        // we can use a binary search for this

        var blocks = GetBlocks(input);
        var (lo, hi) = (0, blocks.Length);
        while (hi - lo > 1) {
            var m = (lo + hi) / 2;
            if (Distance(blocks.Take(m)) == null) {
                hi = m;
            } else {
                lo = m;
            }
        }
        return $"{blocks[lo].Real},{blocks[lo].Imaginary}";
    }

    int? Distance(IEnumerable<Complex> blocks) {
        // our standard priority queue based path finding
        
        var size = 70;
        var (start, goal) = (0, size + size * Complex.ImaginaryOne);
        var blocked = blocks.Concat(start).ToHashSet();
    
        var q = new PriorityQueue<Complex, int>();
        q.Enqueue(start, 0);
        while (q.TryDequeue(out var pos, out var dist)) {
            if (pos == goal) {
                return dist;
            } 

            foreach (var dir in new[] { 1, -1, Complex.ImaginaryOne, -Complex.ImaginaryOne }) {
                var posT = pos + dir;
                if (!blocked.Contains(posT) &&
                    0 <= posT.Imaginary && posT.Imaginary <= size &&
                    0 <= posT.Real && posT.Real <= size
                ) {
                    q.Enqueue(posT, dist + 1);
                    blocked.Add(posT);
                }
            }
        }
        return null;
    }

    Complex[] GetBlocks(string input) => (
        from line in input.Split("\n")
        let nums = Regex.Matches(line, @"\d+").Select(m => int.Parse(m.Value)).ToArray()
        select nums[0] + nums[1] * Complex.ImaginaryOne
    ).ToArray();
}

Please ☆ my repo if you like it!

© 2025 Advent of Code is a registered trademark in the US Images provided by Bing image creator