diff --git a/2021/nim/common.nim b/2021/nim/common.nim index 7493467..09e990d 100644 --- a/2021/nim/common.nim +++ b/2021/nim/common.nim @@ -47,17 +47,17 @@ proc doDay*[T, X]( expectedPart1: X, expectedPart2: X): void = - # when not defined(release): - # var p1 = testInput.part1() - # echo "Day ", day, " Part 1: ", p1, " (Expected: ", expectedPart1, ")" - # doAssert p1 == expectedPart1 + when not defined(release): + var p1 = testInput.part1() + echo "Day ", day, " Part 1: ", p1, " (Expected: ", expectedPart1, ")" + doAssert p1 == expectedPart1 - # time(&"Day {day} Part 1"): echo day.inputLoader().part1() + time(&"Day {day} Part 1"): echo day.inputLoader().part1() - # when not defined(release): - var p2 = testInput.part2() - echo "Day ", day, " Part 2: ", p2, " (Expected: ", expectedPart2, ")" - doAssert p2 == expectedPart2 + when not defined(release): + var p2 = testInput.part2() + echo "Day ", day, " Part 2: ", p2, " (Expected: ", expectedPart2, ")" + doAssert p2 == expectedPart2 time(&"Day {day} Part 2"): echo day.inputLoader().part2() diff --git a/2021/nim/day24.nim b/2021/nim/day24.nim new file mode 100644 index 0000000..af21269 --- /dev/null +++ b/2021/nim/day24.nim @@ -0,0 +1,73 @@ +import ./common, std/[strutils, sugar, sequtils, options, tables, sets, strformat, algorithm, pegs] + +type + Register = int + ALUInstruction = (string, Register, string) + ALUState = array[4, int] + +proc parseInstruction(s: string): ALUInstruction = + # echo s + let ss = s.split(' ') + let i = if ss.len > 2: ss[2] else: "" + (ss[0], ss[1][0].ord - ord('w'), i) + +proc runALUInstructions(instructions: seq[ALUInstruction], input: string): ALUState = + var inputs = input.reversed + let registers = toHashSet(['w', 'x', 'y', 'z']) + var n = 0 + for i in instructions: + let (op, reg, arg) = i + var narg = arg + var num = 0 + if arg != "": + if registers.contains(arg[0]): + let index = arg[0].ord - 'w'.ord + num = result[index] + narg = &"r{index+1}" + else: num = arg.parseInt + if n mod 18 in [4, 5, 15, 0]: + echo &"{result} -> {op} {narg} to r{reg+1} (Input Left: {inputs.join})" + case op: + of "inp": result[reg] = inputs.pop.ord - '0'.ord + of "add": result[reg] += num + of "mul": result[reg] *= num + of "div": result[reg] = result[reg] div num + of "mod": result[reg] = result[reg] mod num + of "eql": result[reg] = (result[reg] == num).int + inc n + +proc p1(input: Lines): uint64 = + # repeating these 18 instructions: + # w is used to store the input digit + # x is zeroed + # z is added to x + # x is modulo'd over 26 + # z is divided by either 1 or 26 (mostly in the latter half of the inputs) + # x is added with SOME NUMBER (sometimes negative) + # x is ALWAYS eql'd with w and 0 + # this is meant to ensure that x is NOT equal to the input? + # y is ALWAYS set to 25 + # y is multiplied by x, which will be 25 if x was 1 or 0 otherwise + # so y will be 25 if x was equal to the input and 0 if not + # y is incremented + # 26 now, if x was equal, 1 if not + # z is multiplied by y + # so z + # y is zeroed out, set to w (the input), added with SOME NUMBER, then multiplied with x + # add y to z + + # if I need to get z to zero, I need to know where those 26-divisions are and leverage them + # if I can ever get y to be negative, that could help a lot as well + + # probably a relatively simple way to bruteforce over this? + let instructions = input.map(parseInstruction) + # let oalu = instructions.runALUInstructions("13579246899999") + # echo oalu + let alu = instructions.runALUInstructions("99879249111111") + echo alu + 0 + +proc p2(input: Lines): uint64 = + 0 + +time(&"Day 24 Part 1"): echo 24.loadInput.p1