aoc-all

My solutions to all Advent of Code
git clone https://git.instinctive.eu/aoc-all.git
Log | Files | Refs | README | LICENSE

commit b97116b99d30c161899d7e91b7ae03ec9983bded
parent b1fdfddbaa46b51e3e28ead17e0d8f482d98e3ed
Author: Natasha Kerensikova <natgh@instinctive.eu>
Date:   Wed, 18 Dec 2024 06:36:02 +0000

Day 17 references and solutions
Diffstat:
A2024/day17.nim | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2024/ref/day17a.txt | 5+++++
A2024/ref/day17b.txt | 5+++++
3 files changed, 153 insertions(+), 0 deletions(-)

diff --git a/2024/day17.nim b/2024/day17.nim @@ -0,0 +1,143 @@ +# Copyright (c) 2024, Natacha Porté +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from std/random import randomize, rand +from std/sequtils import map, toSeq +from std/strutils import join, parseInt, split + +# Read input file + +let data = stdin.lines().toSeq() + +assert len(data) == 5 +assert data[0][0 .. 11] == "Register A: " +assert data[1][0 .. 11] == "Register B: " +assert data[2][0 .. 11] == "Register C: " +assert data[3] == "" +assert data[4][0 .. 8] == "Program: " + +type + Machine = tuple + A, B, C, ip: int + res: seq[int] + +let + init: Machine = (A: parseInt(data[0][12 .. ^1]), B: parseInt(data[1][12 .. ^1]), C: parseInt(data[2][12 .. ^1]), ip: 0, res: @[]) + program = data[4][9 .. ^1].split(",").map(parseInt) + +# Puzzle 1 + +func combo(m: Machine, op: int): int = + case op + of 0 .. 3: + result = op + of 4: + result = m.A + of 5: + result = m.B + of 6: + result = m.C + else: + assert false + +func adv(m: Machine, op: int): Machine = + result = m + result.A = result.A shr combo(m, op) + result.ip += 2 + +func bxl(m: Machine, op: int): Machine = + result = m + result.B = result.B xor op + result.ip += 2 + +func bst(m: Machine, op: int): Machine = + result = m + result.B = combo(m, op) mod 8 + result.ip += 2 + +func jnz(m: Machine, op: int): Machine = + result = m + if result.A == 0: + result.ip += 2 + else: + result.ip = op + +func op_out(m: Machine, op: int): Machine = + result = m + result.res.add(combo(m, op) mod 8) + result.ip += 2 + +func bxc(m: Machine, op: int): Machine = + result = m + result.B = result.B xor result.C + result.ip += 2 + +func bdv(m: Machine, op: int): Machine = + result = m + result.B = result.A shr combo(m, op) + result.ip += 2 + +func cdv(m: Machine, op: int): Machine = + result = m + result.C = result.A shr combo(m, op) + result.ip += 2 + +let + opcodes = [adv, bxl, bst, jnz, bxc, op_out, bdv, cdv] + +proc step(m: Machine, prg: seq[int]): Machine = + result = opcodes[prg[m.ip]](m, prg[m.ip + 1]) + +proc run(m: Machine, prg: seq[int]): Machine = + result = m + while result.ip + 1 < len(prg): + result = step(result, prg) + +assert run((A: rand(9999), B: rand(9999), C: 9, ip: 0, res: @[]), @[2, 6]).B == 1 +assert run((A: 10, B: rand(9999), C: rand(9999), ip: 0, res: @[]), @[5,0,5,1,5,4]).res == @[0,1,2] +assert run((A: 2024, B: rand(9999), C: rand(9999), ip: 0, res: @[]), @[0,1,5,4,3,0]).res == @[4,2,5,6,7,7,7,7,3,1,0] +assert run((A: 2024, B: rand(9999), C: rand(9999), ip: 0, res: @[]), @[0,1,5,4,3,0]).A == 0 +assert run((A: rand(9999), B: 29, C: rand(9999), ip: 0, res: @[]), @[1,7]).B == 26 +assert run((A: rand(9999), B: 2024, C: 43690, ip: 0, res: @[]), @[4,0]).B == 44354 + +echo "Puzzle 1: ", run(init, program).res.join(",") + +# Puzzle 2 +# 164515378771682 is too low + +let op_names = ["adv", "bxl", "bst", "jnz", "bxc", "op_out", "bdv", "cdv"] + +for i in 0 .. (len(program)-2) div 2: + echo 2*i, ": ", op_names[program[2*i]], " ", program[2*i+1] + +proc answer2(im: Machine, prg: seq[int]): int = + var + m = im + q = @[0] + while len(q) > 0: + let h = q[0] + q = q[1 .. ^1] + for i in 0 .. 7: + m.A = h * 8 + i + let s = run(m, prg).res + + if s == prg: + return m.A + elif s == prg[^len(s) .. ^1]: + q.add(m.A) + else: + assert len(s) == 1 or s[1..^1] == prg[^(len(s)-1) .. ^1] + assert false + +echo "Puzzle 2: ", answer2(init, program) diff --git a/2024/ref/day17a.txt b/2024/ref/day17a.txt @@ -0,0 +1,5 @@ +Register A: 729 +Register B: 0 +Register C: 0 + +Program: 0,1,5,4,3,0 diff --git a/2024/ref/day17b.txt b/2024/ref/day17b.txt @@ -0,0 +1,5 @@ +Register A: 2024 +Register B: 0 +Register C: 0 + +Program: 0,3,5,4,3,0