this post was submitted on 17 Dec 2024
9 points (100.0% liked)

Advent Of Code

995 readers
4 users here now

An unofficial home for the advent of code community on programming.dev!

Advent of Code is an annual Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

AoC 2024

Solution Threads

M T W T F S S
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25

Rules/Guidelines

Relevant Communities

Relevant Links

Credits

Icon base by Lorc under CC BY 3.0 with modifications to add a gradient

console.log('Hello World')

founded 1 year ago
MODERATORS
 

Day 17: Chronospatial Computer

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

you are viewing a single comment's thread
view the rest of the comments
[–] [email protected] 3 points 2 weeks ago

C#

This one is mostly thanks to reading @mykl@[email protected]'s code to understand WTF was going on for part 2, and then once I understood the basics, finally got to solving it myself. Instructions were read in as long because I didn't want to deal with int vs. long all the time.

using System.Collections.Immutable;
using System.Diagnostics;
using Common;

namespace Day17;

static class Program
{
    public record State(long A, long B, long C, int InstPtr, ImmutableList<long> Output);

    static void Main()
    {
        var start = Stopwatch.GetTimestamp();

        var (sampleReg, sampleInst) = ReceiveInput("sample.txt");
        var (inputReg, inputInst) = ReceiveInput("input.txt");

        Console.WriteLine($"Part 1 sample: {Part1(sampleReg, sampleInst)}");
        Console.WriteLine($"Part 1 input: {Part1(inputReg, inputInst)}");

        (sampleReg, sampleInst) = ReceiveInput("sample2.txt");
        Console.WriteLine($"Part 2 sample: {Part2(sampleReg, sampleInst)}");
        Console.WriteLine($"Part 2 input: {Part2(inputReg, inputInst)}");

        Console.WriteLine($"That took about {Stopwatch.GetElapsedTime(start)}");
    }

    static object Part1(State state, ImmutableArray<long> instructions) =>
        Execute(instructions, state).Output.StringifyAndJoin(",");

    static object Part2(State state, ImmutableArray<long> instructions) =>
        RecursiveSolve(instructions, state with { A = 0 }, []).First();

    static IEnumerable<long> RecursiveSolve(ImmutableArray<long> instructions, State state, ImmutableList<long> soFar) =>
        (soFar.Count == instructions.Length) ? [state.A] :
        Enumerable.Range(0, 8)
            .Select(a => state with { A = (state.A << 3) + a })
            .Where(newState => newState.A != state.A)
            .Select(newState => new { newState, Execute(instructions, newState).Output, })
            .Where(states => states.Output.SequenceEqual(instructions.TakeLast(states.Output.Count)))
            .SelectMany(states => RecursiveSolve(instructions, states.newState, states.Output));

    static State Execute(ImmutableArray<long> instructions, State state)
    {
        while (state.InstPtr < instructions.Length)
        {
            var opcode = instructions[state.InstPtr];
            var operand = instructions[state.InstPtr + 1];
            state = Operations[opcode](state, operand);
        }

        return state;
    }

    static long ComboOperand(long operand, State state) => operand switch
    {
        >= 0 and <= 3 => operand,
        4 => state.A,
        5 => state.B,
        6 => state.C,
        _ => throw new Exception("Invalid operand."),
    };

    static long Adv(long op, State state) => state.A / (long)Math.Pow(2, ComboOperand(op, state));

    static readonly Func<State, long, State>[] Operations =
    [
        (s, op) => s with { InstPtr = s.InstPtr + 2, A = Adv(op, s) },
        (s, op) => s with { InstPtr = s.InstPtr + 2, B = s.B ^ op },
        (s, op) => s with { InstPtr = s.InstPtr + 2, B = ComboOperand(op, s) % 8 },
        (s, op) => s with { InstPtr = (s.A == 0) ? (s.InstPtr + 2) : (op <= int.MaxValue) ? (int)op : throw new ArithmeticException("Integer overflow!") },
        (s, _) => s with { InstPtr = s.InstPtr + 2, B = s.B ^ s.C },
        (s, op) => s with { InstPtr = s.InstPtr + 2, Output = s.Output.Add(ComboOperand(op, s) % 8) },
        (s, op) => s with { InstPtr = s.InstPtr + 2, B = Adv(op, s) },
        (s, op) => s with { InstPtr = s.InstPtr + 2, C = Adv(op, s) },
    ];


    static (State, ImmutableArray<long> instructions) ReceiveInput(string file)
    {
        var input = File.ReadAllLines(file);

        return
        (
            new State(
                long.Parse(input[0].Substring("Register A: ".Length)),
                long.Parse(input[1].Substring("Register B: ".Length)),
                long.Parse(input[2].Substring("Register C: ".Length)),
                0,
                []),
            input[4].Substring("Program: ".Length)
                .Split(",")
                .Select(long.Parse)
                .ToImmutableArray()
        );
    }
}