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