aoc-2020-zig

git clone https://git.sinitax.com/sinitax/aoc-2020-zig
Log | Files | Refs | README | sfeed.txt

commit 6157648abc2cd42b0ed9455fdb6ec059c725dc73
parent e164c733157b73f4b758ea93df56b11338c34333
Author: Louis Burda <quent.burda@gmail.com>
Date:   Tue,  8 Dec 2020 19:30:03 +0100

added day 8, fixed deinit with aoc env and added check if command script exists

Diffstat:
Maoc | 9++++++---
Alib/console8.zig | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mscripts/build | 5++++-
Mscripts/run | 1-
Asrc/day8/input | 628+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/day8/main.zig | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/day8/part1 | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/day8/part2 | 33+++++++++++++++++++++++++++++++++
8 files changed, 871 insertions(+), 5 deletions(-)

diff --git a/aoc b/aoc @@ -1,7 +1,7 @@ #!/bin/bash function rmprefix() { - echo "${1:$(echo -n "$2" | wc -c)}" + echo "${1:${#2}}" } SCRIPTPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" @@ -34,6 +34,9 @@ if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then fi else [ $# -lt 1 ] && exit 0 - - "$REPOROOT/scripts/$1" ${@:2} + if [ -e "$REPOROOT/scripts/$1" ]; then + "$REPOROOT/scripts/$1" ${@:2} + else + echo "No such script" + fi fi diff --git a/lib/console8.zig b/lib/console8.zig @@ -0,0 +1,91 @@ +const std = @import("std"); + +pub const OpError = error{ InstructionPointerOOB, InvalidFormat, InstructionUnknown }; +pub const OpFuncSig = fn (ctx: *Console, arg: i64) OpError!void; +pub const Instruction = struct { + opcode: []const u8, opfunc: OpFuncSig, argval: i64 +}; + +pub const Console = struct { + accumulator: i64 = 0, + instructptr: u64 = 0, + + jumpAddr: i65 = 0, + + code: []const u8, + instlist: [][]const u8, + allocator: *std.mem.Allocator, + const Self = @This(); + + pub fn init(code: []const u8, allocator: *std.mem.Allocator) !Self { + var instvec = std.ArrayList([]const u8).init(allocator); + errdefer instvec.deinit(); + + var instit = std.mem.tokenize(code, "\n"); + while (instit.next()) |inst| { + try instvec.append(inst); + } + return Console{ + .code = code, + .instlist = instvec.toOwnedSlice(), + .allocator = allocator, + }; + } + + pub fn deinit(self: *Self) void { + self.allocator.free(self.instlist); + } + + pub fn reset(self: *Self) void { + self.accumulator = 0; + self.instructptr = 0; + } + + const instructionMap = std.ComptimeStringMap(OpFuncSig, .{ + .{ "jmp", jumpInstruction }, + .{ "acc", accInstruction }, + .{ "nop", nopInstruction }, + }); + + pub fn jumpInstruction(self: *Self, arg: i64) OpError!void { + self.jumpAddr = @intCast(i65, self.instructptr) + @intCast(i65, arg); + if (self.jumpAddr < 0 or self.jumpAddr >= self.instlist.len) + return error.InstructionPointerOOB; + self.instructptr = @intCast(u64, self.jumpAddr); + } + + pub fn accInstruction(self: *Self, arg: i64) OpError!void { + self.accumulator += arg; + self.instructptr += 1; + } + + pub fn nopInstruction(self: *Self, arg: i64) OpError!void { + self.instructptr += 1; + } + + pub fn parseNext(self: *Self) !?Instruction { + if (self.instructptr >= self.instlist.len) + return null; + + const inststr = self.instlist[self.instructptr]; + const sep = std.mem.indexOfScalar(u8, inststr, ' '); + if (sep == null) return OpError.InvalidFormat; + + const opcode = inststr[0..sep.?]; + if (instructionMap.get(opcode)) |opfunc| { + const arg = inststr[sep.? + 1 ..]; + const val = std.fmt.parseInt(i64, arg, 10) catch |err| { + std.debug.print("Failed to parse arg value: {}\n", .{arg}); + return OpError.InvalidFormat; + }; + return Instruction{ .opcode = opcode, .opfunc = opfunc, .argval = val }; + } else { + std.debug.print("Unknown instruction: {}\n", .{inststr}); + return OpError.InstructionUnknown; + } + } + + pub fn exec(self: *Self, inst: *Instruction) !void { + try inst.opfunc(self, inst.argval); + } +}; diff --git a/scripts/build b/scripts/build @@ -3,4 +3,7 @@ [ -z "$REPOROOT" ] && exit 1 [ ! -e "$REPOROOT/cache" ] && mkdir "$REPOROOT/cache" -zig build-exe --cache-dir "$REPOROOT/cache" --pkg-begin "aoc" "$REPOROOT/lib/aoc.zig" --pkg-end main.zig +zig build-exe --cache-dir "$REPOROOT/cache" \ + --pkg-begin "console8" "$REPOROOT/lib/console8.zig" --pkg-end \ + --pkg-begin "aoc" "$REPOROOT/lib/aoc.zig" --pkg-end \ + main.zig diff --git a/scripts/run b/scripts/run @@ -1,5 +1,4 @@ #!/bin/bash [ ! -e "main" ] && aoc build - $PWD/main $@ diff --git a/src/day8/input b/src/day8/input @@ -0,0 +1,628 @@ +jmp +336 +jmp +593 +jmp +121 +acc -8 +nop +459 +jmp +451 +acc -6 +acc +23 +acc +23 +acc -2 +jmp +113 +acc -11 +acc +25 +jmp +529 +acc +0 +jmp +1 +jmp +313 +acc +30 +nop +235 +jmp +45 +nop +195 +acc -11 +jmp +491 +acc +6 +nop +425 +nop +68 +acc +9 +jmp -25 +jmp +507 +jmp +456 +acc -1 +acc +49 +acc +5 +jmp +31 +acc +30 +nop +513 +jmp +499 +nop +533 +acc +18 +acc +28 +acc -2 +jmp +170 +acc -5 +jmp +180 +nop +179 +acc +15 +acc +33 +nop +27 +jmp +424 +acc +30 +acc +33 +acc +50 +jmp +348 +jmp +435 +acc +21 +acc +14 +acc +13 +jmp +1 +jmp +98 +jmp +39 +acc +11 +acc +23 +acc +44 +jmp +494 +acc +17 +acc -4 +acc +24 +acc +5 +jmp +204 +nop +454 +acc +45 +acc -10 +acc -3 +jmp +78 +acc +47 +acc +49 +nop +99 +acc +29 +jmp -76 +acc -9 +acc +43 +jmp +279 +jmp +460 +jmp +246 +jmp -78 +acc -8 +acc -3 +jmp +415 +acc -3 +acc -12 +jmp +117 +acc +32 +jmp +206 +acc +6 +acc +19 +jmp +291 +acc +8 +jmp +175 +acc +2 +jmp -6 +acc +11 +acc +28 +acc -19 +acc +1 +jmp +194 +acc +29 +nop +387 +acc +21 +jmp +507 +jmp +304 +acc +22 +acc -14 +acc -6 +acc +45 +jmp +101 +acc +12 +jmp +91 +acc +47 +jmp +171 +acc -4 +acc +24 +acc +3 +jmp +29 +nop +311 +acc -12 +jmp +179 +jmp +1 +acc -3 +acc +6 +acc +22 +jmp +214 +nop -101 +jmp -118 +acc +23 +acc +15 +jmp -42 +acc +22 +nop +391 +jmp +27 +acc -9 +jmp +449 +jmp +453 +jmp +208 +jmp +480 +jmp +335 +acc +23 +jmp +1 +acc +3 +acc +45 +jmp -18 +jmp +335 +jmp +165 +acc +26 +acc +8 +acc -3 +jmp -57 +jmp -112 +acc +14 +acc +20 +acc +21 +acc +13 +jmp -20 +acc +35 +jmp -81 +jmp +406 +acc -16 +acc +30 +acc -18 +jmp +79 +jmp +103 +jmp -96 +acc +43 +acc +36 +acc +31 +jmp +423 +nop +13 +acc -11 +acc +46 +nop +208 +jmp +398 +acc +50 +jmp +326 +acc +31 +jmp +45 +acc +50 +acc +13 +acc +38 +jmp +60 +nop -37 +nop -79 +jmp +213 +acc -19 +acc -16 +jmp +30 +jmp +1 +acc +27 +acc -4 +acc +46 +jmp -81 +jmp +29 +nop +23 +nop +388 +acc +40 +acc +46 +jmp +19 +acc +17 +jmp +287 +jmp +265 +acc +17 +acc +49 +jmp +353 +acc -4 +acc +39 +jmp +397 +jmp +84 +jmp -156 +jmp -41 +acc +2 +acc +7 +acc +45 +acc +26 +jmp +376 +jmp +143 +jmp -195 +acc +1 +acc -16 +acc +47 +jmp -225 +acc -11 +acc -7 +nop -166 +jmp +297 +acc +12 +acc +14 +acc -17 +jmp +9 +acc +49 +acc -9 +nop -31 +acc +17 +jmp -130 +acc +3 +acc +41 +jmp +112 +acc -11 +jmp +21 +jmp +125 +acc +2 +acc +37 +jmp -165 +acc +9 +acc +21 +jmp -35 +nop +9 +nop +303 +acc -6 +acc +12 +jmp +177 +acc +36 +acc +15 +nop -207 +jmp +224 +jmp -106 +acc +18 +nop -166 +jmp +39 +jmp +175 +acc -11 +acc -13 +acc +23 +acc -6 +jmp -269 +acc +8 +nop +212 +jmp -123 +jmp +188 +acc +35 +acc +43 +acc +33 +jmp -91 +acc +39 +acc +8 +acc -1 +acc +15 +jmp +29 +acc +44 +nop +18 +jmp -250 +jmp +83 +acc +10 +acc +12 +acc +18 +jmp +1 +jmp +170 +acc +47 +acc -13 +acc +4 +jmp +32 +acc +0 +jmp +203 +acc -16 +acc +11 +acc +38 +jmp -103 +jmp +2 +jmp -69 +nop -292 +jmp -90 +nop -97 +acc +29 +nop +124 +acc -12 +jmp -238 +acc +4 +jmp +36 +jmp -108 +acc +14 +acc +21 +jmp +82 +acc -6 +acc +28 +jmp -133 +acc -4 +acc +28 +jmp +155 +nop +168 +acc -2 +nop +86 +jmp +287 +acc +15 +acc +46 +acc +40 +acc -16 +jmp -139 +acc +39 +jmp +36 +acc -16 +acc +25 +nop -215 +jmp +146 +nop -296 +acc -12 +acc +40 +jmp -299 +acc +48 +acc +37 +nop -205 +acc -17 +jmp +215 +jmp +254 +jmp +53 +acc +15 +acc +34 +acc +8 +jmp +216 +nop +5 +acc +23 +jmp -195 +acc +0 +jmp +69 +acc +6 +jmp +187 +acc +14 +acc -2 +jmp -51 +acc -12 +acc +43 +nop -51 +jmp -193 +acc -1 +jmp -234 +acc +20 +jmp +1 +acc +33 +acc +23 +jmp -131 +acc +38 +acc +2 +jmp +179 +jmp +1 +jmp +209 +nop -187 +acc +41 +acc +32 +acc +6 +jmp +209 +nop -230 +acc +37 +acc +47 +acc +32 +jmp +82 +acc +45 +acc +21 +jmp -108 +acc +13 +acc +39 +jmp +127 +jmp +1 +nop +196 +jmp -146 +acc +19 +jmp -125 +jmp -149 +acc +28 +acc -1 +acc +35 +acc +7 +jmp -262 +acc -16 +acc -3 +acc +48 +acc +13 +jmp +177 +jmp -91 +acc +26 +nop +78 +acc +15 +jmp +1 +jmp +197 +acc +12 +acc -14 +acc +9 +jmp -317 +acc +41 +acc +2 +acc -11 +acc +6 +jmp -284 +acc +28 +acc -16 +jmp -65 +acc +31 +nop -276 +jmp -205 +acc +6 +acc +33 +acc +7 +acc -2 +jmp -125 +acc +34 +jmp -193 +acc -12 +acc +39 +jmp +1 +jmp -208 +acc +3 +acc +0 +nop +9 +jmp -112 +jmp +1 +jmp -314 +acc +34 +acc +9 +acc +5 +acc +20 +jmp +139 +acc -8 +acc +11 +acc +18 +jmp +1 +jmp -66 +acc -14 +jmp -173 +acc -3 +acc +31 +acc +0 +jmp +117 +acc +47 +acc +24 +acc +9 +acc +43 +jmp -427 +acc -11 +nop -226 +jmp -444 +acc +43 +acc -6 +acc -3 +jmp -202 +acc +34 +jmp -337 +acc +36 +acc +8 +acc +9 +jmp -162 +jmp +118 +acc +18 +jmp -481 +nop -144 +nop -236 +jmp -290 +acc -14 +jmp -448 +acc +29 +acc -19 +acc +21 +acc -11 +jmp -78 +acc +1 +acc +30 +acc -2 +jmp +114 +jmp +11 +jmp -117 +jmp -322 +acc +23 +jmp -361 +jmp -337 +acc +40 +nop +85 +nop -206 +acc +12 +jmp -199 +acc +38 +acc +20 +acc +19 +acc +33 +jmp -61 +acc +30 +nop -234 +acc +6 +acc +24 +jmp -463 +acc -10 +jmp +79 +acc +43 +acc +45 +jmp -261 +acc -13 +acc +1 +nop -217 +nop -82 +jmp -153 +acc +39 +jmp -340 +acc +37 +acc +17 +jmp -182 +acc +26 +acc +1 +acc +23 +jmp +16 +acc +39 +acc +13 +jmp -40 +acc +37 +acc -7 +jmp -119 +acc +20 +acc +44 +acc +44 +acc +14 +jmp -464 +acc +6 +acc +14 +acc +7 +jmp +54 +acc +10 +jmp -538 +acc +13 +acc -1 +acc +22 +jmp -397 +acc +17 +acc -8 +acc -5 +jmp -230 +acc +38 +nop -218 +jmp -81 +acc -19 +nop -14 +acc +32 +jmp -311 +nop -32 +acc +18 +jmp -232 +acc +40 +nop -242 +acc -11 +acc +34 +jmp -528 +jmp -484 +jmp -155 +acc -2 +acc +50 +acc -11 +acc +50 +jmp -116 +nop -361 +acc +12 +jmp -293 +acc +39 +jmp +17 +jmp -37 +acc -14 +jmp -440 +jmp -226 +acc +16 +acc +25 +acc +50 +acc +49 +jmp -242 +acc +47 +acc -19 +nop -435 +acc +41 +jmp -523 +acc +6 +jmp -458 +acc +0 +acc +37 +jmp -528 +acc +27 +jmp -57 +acc +47 +acc -9 +acc +23 +jmp -205 +acc +40 +nop -207 +acc -6 +jmp -129 +jmp +1 +acc +24 +acc -14 +jmp +1 +jmp +1 diff --git a/src/day8/main.zig b/src/day8/main.zig @@ -0,0 +1,60 @@ +const std = @import("std"); +const aoc = @import("aoc"); +const Console = @import("console8").Console; + +fn runTillRepeat(console: *Console, instlist: *std.ArrayList(u64), swapon: ?u64) !void { + while (try console.parseNext()) |*inst| { + // std.debug.print("{:<5}: {} {}\n", .{ console.instructptr, inst.opcode, inst.argval }); + if (std.mem.indexOfScalar(u64, instlist.items, console.instructptr) != null) { + return; + } + if (swapon != null and swapon.? == console.instructptr) { + inst.opfunc = switch (inst.opfunc) { + Console.jumpInstruction => Console.nopInstruction, + Console.nopInstruction => Console.jumpInstruction, + else => unreachable, + }; + } + try instlist.append(console.instructptr); + try console.exec(inst); + } +} + +fn part1(allocator: *std.mem.Allocator, input: []u8, args: [][]u8) !void { + var console = try Console.init(input, allocator); + defer console.deinit(); + + var instlist = std.ArrayList(u64).init(allocator); + defer instlist.deinit(); + + try runTillRepeat(&console, &instlist, null); + std.debug.print("{}\n", .{console.accumulator}); +} + +fn part2(allocator: *std.mem.Allocator, input: []u8, args: [][]u8) !void { + var console = try Console.init(input, allocator); + defer console.deinit(); + + var instlist = std.ArrayList(u64).init(allocator); + defer instlist.deinit(); + + try runTillRepeat(&console, &instlist, null); + + for (instlist.items) |inst| { + if (std.mem.eql(u8, "acc"[0..3], console.instlist[inst][0..3])) + continue; + + var sim_seen = std.ArrayList(u64).init(allocator); + defer sim_seen.deinit(); + + console.reset(); + //std.debug.print("Swapping instruction: {:<5}: {}\n", .{ inst, console.instlist[inst] }); + runTillRepeat(&console, &sim_seen, inst) catch {}; + if (console.jumpAddr == console.instlist.len or console.instructptr == console.instlist.len) { + std.debug.print("{}\n", .{console.accumulator}); + break; + } + } +} + +pub const main = aoc.gen_main(part1, part2); diff --git a/src/day8/part1 b/src/day8/part1 @@ -0,0 +1,49 @@ +--- Day 8: Handheld Halting --- + +Your flight to the major airline hub reaches cruising altitude without incident. While you consider +checking the in-flight menu for one of those drinks that come with a little umbrella, you are +interrupted by the kid sitting next to you. + +Their handheld game console won't turn on! They ask if you can take a look. + +You narrow the problem down to a strange infinite loop in the boot code (your puzzle +input) of the device. You should be able to fix it, but first you need to be able to run the code in +isolation. + +The boot code is represented as a text file with one instruction per line of text. Each +instruction consists of an operation (acc, jmp, or nop) and an argument (a +signed number like +4 or -20). + +- acc increases or decreases a single global value called the accumulator by the value +given in the argument. For example, acc +7 would increase the accumulator by 7. The accumulator +starts at 0. After an acc instruction, the instruction immediately below it is executed next. - jmp +jumps to a new instruction relative to itself. The next instruction to execute is found +using the argument as an offset from the jmp instruction; for example, jmp +2 would +skip the next instruction, jmp +1 would continue to the instruction immediately below it, and jmp +-20 would cause the instruction 20 lines above to be executed next. - nop stands for No +OPeration - it does nothing. The instruction immediately below it is executed next. + +For example, consider the following program: + +nop +0 acc +1 jmp +4 acc +3 jmp -3 acc -99 acc +1 jmp -4 acc +6 + +These instructions are visited in this order: + +nop +0 | 1 acc +1 | 2, 8(!) jmp +4 | 3 acc +3 | 6 jmp -3 | 7 acc -99 | acc +1 | 4 jmp -4 | 5 acc +6 +| + +First, the nop +0 does nothing. Then, the accumulator is increased from 0 to 1 (acc +1) and jmp +4 +sets the next instruction to the other acc +1 near the bottom. After it increases the accumulator +from 1 to 2, jmp -4 executes, setting the next instruction to the only acc +3. It sets the +accumulator to 5, and jmp -3 causes the program to continue back at the first acc +1. + +This is an infinite loop: with this sequence of jumps, the program will run forever. +The moment the program tries to run any instruction a second time, you know it will never terminate. + +Immediately before the program would run an instruction a second time, the value in the +accumulator is 5. + +Run your copy of the boot code. Immediately before any instruction is executed a second time, +what value is in the accumulator? + + diff --git a/src/day8/part2 b/src/day8/part2 @@ -0,0 +1,33 @@ +--- Part Two --- + +After some careful analysis, you believe that exactly one instruction is corrupted. + +Somewhere in the program, either a jmp is supposed to be a nop, or a nop +is supposed to be a jmp. (No acc instructions were harmed in the corruption of this boot code.) + +The program is supposed to terminate by attempting to execute an instruction immediately +after the last instruction in the file. By changing exactly one jmp or nop, you can repair the +boot code and make it terminate correctly. + +For example, consider the same program from above: + +nop +0 acc +1 jmp +4 acc +3 jmp -3 acc -99 acc +1 jmp -4 acc +6 + +If you change the first instruction from nop +0 to jmp +0, it would create a single-instruction +infinite loop, never leaving that instruction. If you change almost any of the jmp instructions, the +program will still eventually find another jmp instruction and loop forever. + +However, if you change the second-to-last instruction (from jmp -4 to nop -4), the program +terminates! The instructions are visited in this order: + +nop +0 | 1 acc +1 | 2 jmp +4 | 3 acc +3 | jmp -3 | acc -99 | acc +1 | 4 nop -4 | 5 acc ++6 | 6 + +After the last instruction (acc +6), the program terminates by attempting to run the instruction +below the last instruction in the file. With this change, after the program terminates, the +accumulator contains the value 8 (acc +1, acc +1, acc +6). + +Fix the program so that it terminates normally by changing exactly one jmp (to nop) or nop (to jmp). +What is the value of the accumulator after the program terminates? + +