From 08a13d416c92edb0248c3dc2789a38c9032a6fe9 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sun, 1 Dec 2019 17:40:23 +0000 Subject: [PATCH 01/32] Day 01 --- .gitignore | 1 + 01/build.zig | 14 +++++++ 01/input | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ 01/src/main.zig | 33 ++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 .gitignore create mode 100644 01/build.zig create mode 100644 01/input create mode 100644 01/src/main.zig diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2040c29 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +zig-cache diff --git a/01/build.zig b/01/build.zig new file mode 100644 index 0000000..2ab06e7 --- /dev/null +++ b/01/build.zig @@ -0,0 +1,14 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("01", "src/main.zig"); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/01/input b/01/input new file mode 100644 index 0000000..dde704b --- /dev/null +++ b/01/input @@ -0,0 +1,100 @@ +109067 +75007 +66030 +93682 +83818 +108891 +139958 +129246 +80272 +119897 +112804 +69495 +95884 +85402 +148361 +75986 +120063 +127683 +146962 +76907 +61414 +98452 +134330 +53858 +82662 +143258 +82801 +60279 +131782 +105989 +102464 +96563 +71172 +113731 +90645 +94830 +133247 +110149 +54792 +134863 +125919 +145490 +69836 +108808 +87954 +148957 +110182 +126668 +148024 +96915 +117727 +147378 +75967 +91915 +60130 +85331 +66800 +103419 +72627 +72687 +61606 +113160 +107082 +110793 +61589 +105005 +73952 +65705 +117243 +140944 +117091 +113482 +91379 +148185 +113853 +119822 +78179 +85407 +119886 +109230 +68783 +63914 +51101 +93549 +53361 +127984 +106315 +54997 +138941 +81075 +120272 +120307 +98414 +115245 +105649 +89793 +88421 +121104 +97084 +56928 diff --git a/01/src/main.zig b/01/src/main.zig new file mode 100644 index 0000000..b357db7 --- /dev/null +++ b/01/src/main.zig @@ -0,0 +1,33 @@ +const std = @import("std"); + +fn rocket(in: i64) i64 { + var x: i64 = @divFloor(in, 3) - 2; + if (x < 0) { + x = 0; + } + + return x; +} + +pub fn main() anyerror!void { + const file = std.io.getStdIn(); + const stream = &file.inStream().stream; + + var buf: [20]u8 = undefined; + var sum1: i64 = 0; // part 1 + var sum2: i64 = 0; // part 2 + + while (try stream.readUntilDelimiterOrEof(&buf, '\n')) |line| { + const mass = try std.fmt.parseInt(i64, line, 10); + var rock = rocket(mass); + sum1 += rock; + while (rock > 0) { + sum2 += rock; + rock = rocket(rock); + } + } + + std.debug.warn("Part 1: {}\n", sum1); + std.debug.warn("Part 2: {}\n", sum2); +} + From e943794b67298d8fe737aaea32fcbfe27e433f9b Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 2 Dec 2019 19:04:53 +0000 Subject: [PATCH 02/32] Add README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ac0bff --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# [Advent Of Code 2019](https://adventofcode.com/2019) + +[lupine](https://ur.gs/)'s repository + +This year, I'll be working in [Zig](https://ziglang.org) From de87b93be1bbb98f1c83d3da5e8ffc27a7f2457c Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 2 Dec 2019 20:13:09 +0000 Subject: [PATCH 03/32] Day 2.1 --- 02/build.zig | 14 ++++++++++ 02/input | 1 + 02/src/main.zig | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 02/build.zig create mode 100644 02/input create mode 100644 02/src/main.zig diff --git a/02/build.zig b/02/build.zig new file mode 100644 index 0000000..cf6ba36 --- /dev/null +++ b/02/build.zig @@ -0,0 +1,14 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("02", "src/main.zig"); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/02/input b/02/input new file mode 100644 index 0000000..d58f471 --- /dev/null +++ b/02/input @@ -0,0 +1 @@ +1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,13,19,2,9,19,23,1,23,6,27,1,13,27,31,1,31,10,35,1,9,35,39,1,39,9,43,2,6,43,47,1,47,5,51,2,10,51,55,1,6,55,59,2,13,59,63,2,13,63,67,1,6,67,71,1,71,5,75,2,75,6,79,1,5,79,83,1,83,6,87,2,10,87,91,1,9,91,95,1,6,95,99,1,99,6,103,2,103,9,107,2,107,10,111,1,5,111,115,1,115,6,119,2,6,119,123,1,10,123,127,1,127,5,131,1,131,2,135,1,135,5,0,99,2,0,14,0 diff --git a/02/src/main.zig b/02/src/main.zig new file mode 100644 index 0000000..c989e66 --- /dev/null +++ b/02/src/main.zig @@ -0,0 +1,71 @@ +const std = @import("std"); + +// Load the whole program into memory in one go +fn loadProgram() anyerror![]u32 { + const file = std.io.getStdIn(); + const stream = &file.inStream().stream; + var program = [_]u32{0} ** 1024; + var buf = [_]u8{0} ** 255; + var i: u32 = 0; + + while (try stream.readUntilDelimiterOrEof(&buf, ',')) |num| { + var trimmed = std.mem.trimRight(u8, num, "\r\n"); + program[i] = try std.fmt.parseInt(u32, trimmed, 10); + + std.debug.warn("{},", program[i]); + + i += 1; + } + + std.debug.warn("\n"); + + return program[0..program.len]; +} + +pub fn main() anyerror!void { + var program = try loadProgram(); + + // Initial program state. + var ip: u32 = 0; + var exit: bool = false; + + // Gravity assist modifications + program[1] = 12; + program[2] = 2; + + while (!exit) { + std.debug.warn(" IP {d:4}: ", ip); + const opcode = switch (program[ip]) { + 1 => { + var a = program[program[ip + 1]]; + var b = program[program[ip + 2]]; + var dest = program[ip + 3]; + var result = a + b; + + std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); + program[dest] = result; + ip += 4; + }, + 2 => { + var a = program[program[ip + 1]]; + var b = program[program[ip + 2]]; + var dest = program[ip + 3]; + var result = a * b; + + std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); + program[dest] = result; + ip += 4; + }, + 99 => { + std.debug.warn("EXIT\n"); + exit = true; + }, + else => { + std.debug.warn("Unknown opcode at IP {}: {}", ip, program[ip]); + exit = true; + }, + }; + } + + std.debug.warn("Part 1: {}\n", program[0]); +} From 637f909678c1bd70e9a5f980dbec6e00a61dff3e Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 2 Dec 2019 21:09:05 +0000 Subject: [PATCH 04/32] Extract intcode computer into a library --- 02/build.zig | 3 +- 02/src/main.zig | 71 ++++------------------------------ lib/intcode/intcode.zig | 84 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 65 deletions(-) create mode 100644 lib/intcode/intcode.zig diff --git a/02/build.zig b/02/build.zig index cf6ba36..1c55192 100644 --- a/02/build.zig +++ b/02/build.zig @@ -2,7 +2,8 @@ const Builder = @import("std").build.Builder; pub fn build(b: *Builder) void { const mode = b.standardReleaseOptions(); - const exe = b.addExecutable("02", "src/main.zig"); + const exe = b.addExecutable("part-02", "src/main.zig"); + exe.addPackagePath("intcode", "../lib/intcode/intcode.zig"); exe.setBuildMode(mode); exe.install(); diff --git a/02/src/main.zig b/02/src/main.zig index c989e66..c790985 100644 --- a/02/src/main.zig +++ b/02/src/main.zig @@ -1,71 +1,14 @@ const std = @import("std"); - -// Load the whole program into memory in one go -fn loadProgram() anyerror![]u32 { - const file = std.io.getStdIn(); - const stream = &file.inStream().stream; - var program = [_]u32{0} ** 1024; - var buf = [_]u8{0} ** 255; - var i: u32 = 0; - - while (try stream.readUntilDelimiterOrEof(&buf, ',')) |num| { - var trimmed = std.mem.trimRight(u8, num, "\r\n"); - program[i] = try std.fmt.parseInt(u32, trimmed, 10); - - std.debug.warn("{},", program[i]); - - i += 1; - } - - std.debug.warn("\n"); - - return program[0..program.len]; -} +const intcode = @import("intcode"); pub fn main() anyerror!void { - var program = try loadProgram(); + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); - // Initial program state. - var ip: u32 = 0; - var exit: bool = false; + const alloc = &arena.allocator; - // Gravity assist modifications - program[1] = 12; - program[2] = 2; + var program = try intcode.loadFromStdIn(alloc); - while (!exit) { - std.debug.warn(" IP {d:4}: ", ip); - const opcode = switch (program[ip]) { - 1 => { - var a = program[program[ip + 1]]; - var b = program[program[ip + 2]]; - var dest = program[ip + 3]; - var result = a + b; - - std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); - program[dest] = result; - ip += 4; - }, - 2 => { - var a = program[program[ip + 1]]; - var b = program[program[ip + 2]]; - var dest = program[ip + 3]; - var result = a * b; - - std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); - program[dest] = result; - ip += 4; - }, - 99 => { - std.debug.warn("EXIT\n"); - exit = true; - }, - else => { - std.debug.warn("Unknown opcode at IP {}: {}", ip, program[ip]); - exit = true; - }, - }; - } - - std.debug.warn("Part 1: {}\n", program[0]); + // Part 1 + std.debug.warn("Part 1: {}\n", try intcode.runCopy(alloc, program, 12, 2)); } diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig new file mode 100644 index 0000000..f6516ea --- /dev/null +++ b/lib/intcode/intcode.zig @@ -0,0 +1,84 @@ +const std = @import("std"); + +pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]u32 { + var program = try alloc.alloc(u32, 1024); + + var buf = [_]u8{0} ** 255; + var i: u32 = 0; + + while (try stream.readUntilDelimiterOrEof(&buf, ',')) |num| { + var trimmed = std.mem.trimRight(u8, num, "\r\n"); + program[i] = try std.fmt.parseInt(u32, trimmed, 10); + + std.debug.warn("{},", program[i]); + + i += 1; + } + + std.debug.warn("\n"); + + return program[0..program.len]; +} + +pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]u32 { + const file = std.io.getStdIn(); + const stream = &file.inStream().stream; + + return loadFromStream(alloc, stream); +} + +pub fn runCopy(alloc: *std.mem.Allocator, program: []u32, noun: u32, verb: u32) anyerror!u32 { + var memory = try alloc.alloc(u32, program.len); + defer alloc.free(memory); + + std.mem.copy(u32, memory, program); + + return run(memory, noun, verb); +} + +pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 { + program[1] = noun; + program[2] = verb; + + // Initial program state + var ip: u32 = 0; + var exit: bool = false; + + // TODO: create a nice struct + + while (!exit) { + std.debug.warn(" IP {d:4}: ", ip); + const opcode = switch (program[ip]) { + 1 => { + var a = program[program[ip + 1]]; + var b = program[program[ip + 2]]; + var dest = program[ip + 3]; + var result = a + b; + + std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); + program[dest] = result; + ip += 4; + }, + 2 => { + var a = program[program[ip + 1]]; + var b = program[program[ip + 2]]; + var dest = program[ip + 3]; + var result = a * b; + + std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); + program[dest] = result; + ip += 4; + }, + 99 => { + std.debug.warn("EXIT\n"); + exit = true; + }, + else => { + std.debug.warn("Unknown opcode at IP {}: {}", ip, program[ip]); + exit = true; + }, + }; + } + + return program[0]; +} From 14eff1a60c44d0d252cdccb7a4e14730269446dd Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 2 Dec 2019 21:37:21 +0000 Subject: [PATCH 05/32] Day 2.2 --- 02/src/main.zig | 30 ++++++++++++++++++++++++++++++ lib/intcode/intcode.zig | 8 ++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/02/src/main.zig b/02/src/main.zig index c790985..3918edf 100644 --- a/02/src/main.zig +++ b/02/src/main.zig @@ -11,4 +11,34 @@ pub fn main() anyerror!void { // Part 1 std.debug.warn("Part 1: {}\n", try intcode.runCopy(alloc, program, 12, 2)); + + // Part 2: 100*100 = 10,000 combinations to try. + var memory: []u32 = try alloc.alloc(u32, program.len); + var done: bool = false; + var noun: u32 = 0; + var verb: u32 = 0; + + std.debug.warn("Part 2: Searching..."); + while (!done) { + std.mem.copy(u32, memory, program); + const result = try intcode.run(memory, noun, verb); + + // Too high: 250800 (noun=33, verb=76) + if (result == 19690720) { + std.debug.warn("OK! noun={} verb={}\n", noun, verb); + done = true; + } + + noun += 1; + if (noun > 100) { + noun = 0; + verb += 1; + + if (verb > 100) { + std.debug.warn("failed!\n"); + } else { + std.debug.warn("."); + } + } + } } diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index f6516ea..95a8f78 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -47,7 +47,7 @@ pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 { // TODO: create a nice struct while (!exit) { - std.debug.warn(" IP {d:4}: ", ip); + // std.debug.warn(" IP {d:4}: ", ip); const opcode = switch (program[ip]) { 1 => { var a = program[program[ip + 1]]; @@ -55,7 +55,7 @@ pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 { var dest = program[ip + 3]; var result = a + b; - std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); + // std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); program[dest] = result; ip += 4; }, @@ -65,12 +65,12 @@ pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 { var dest = program[ip + 3]; var result = a * b; - std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); + // std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); program[dest] = result; ip += 4; }, 99 => { - std.debug.warn("EXIT\n"); + // std.debug.warn("EXIT\n"); exit = true; }, else => { From 7fb5201a11ad7e3c116fa9c721c63246a4702da0 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Tue, 3 Dec 2019 22:34:17 +0000 Subject: [PATCH 06/32] Day 3.1 - first, bad attempt --- 03/build.zig | 14 ++++ 03/input | 2 + 03/src/main.zig | 213 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 03/build.zig create mode 100644 03/input create mode 100644 03/src/main.zig diff --git a/03/build.zig b/03/build.zig new file mode 100644 index 0000000..890999c --- /dev/null +++ b/03/build.zig @@ -0,0 +1,14 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("03", "src/main.zig"); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/03/input b/03/input new file mode 100644 index 0000000..c0eaa6c --- /dev/null +++ b/03/input @@ -0,0 +1,2 @@ +R1004,U520,R137,D262,L403,U857,R50,U679,R788,D98,L717,D1,R367,U608,L125,U703,L562,D701,L718,U357,R742,D860,R557,D117,R950,U546,L506,U836,R951,D460,L38,U893,L1,D217,R262,D950,R239,U384,R971,D289,R323,U878,L525,U687,L831,U523,R94,D33,L879,D318,R633,D775,R879,D351,L120,D8,R31,U49,R328,D598,L380,D160,R261,D716,R459,U533,L444,U412,L326,U93,L193,D621,R236,U769,L319,D885,L559,U509,L62,U321,L667,D505,R556,U159,L5,U126,L262,D946,L168,U491,L56,D831,R926,U926,R562,D270,R785,U436,R852,D629,R872,U716,R549,U435,R462,U191,R318,U91,L637,D682,R647,D53,L789,D725,R312,D366,L287,U29,R85,D657,R88,U300,R795,U378,R800,D391,L594,U791,R205,U352,L510,D975,R47,D311,R319,U579,R214,D112,R996,U874,R328,D578,R37,U689,L543,U16,L580,D230,L714,D58,L580,D658,R218,U535,R149,U996,L173,D316,L90,D372,L364,U700,L60,D70,L250,U276,R580,U505,L682,U943,R336,U847,R810,U963,R874,D740,R732,D328,R926,D447,R638,D102,R696,U211,L594,D354,R384,U81,L884,U916,L168,U759,R631,D702,L598,D382,L647,U642,R537,U53,R897,U954,R263,U445,L41,D91,L51,D338,R219,U269,L689,D172,R627,D287,L440,D504,L253,D252,R815,D108,L282,U835,L243,U638,R910,D306,R755,D202,R69,D862,L537,D947,L180,D835,L111,U832,R939,D449,R180,U105,R892,D837,L153,U215,L695,U957,R923,U496,R608,U739,L711,U700,L838,D117,R479,U852,R795,D955,L386,D70,R728,D40,R580,U777,L877,U284,R414,D300,R105,D372,L317,D91,R653,U920,R956,D496,L543,D363,R374,D283,L696,U466,R467,D878,R660,U590,L962,U619,R991,U848,L648,D191,R459,U125,L998,U19,L214,U947,R188,U103,R916 +L1008,U717,R288,D770,R270,U514,R109,D538,L719,U179,R466,D792,R421,U723,L22,U705,L284,U14,L478,U367,R727,U880,R620,D46,R377,U897,L731,U840,L910,D385,L257,U311,L596,D991,L668,D730,L707,D816,R47,U948,R84,D700,R299,U707,R261,D928,R358,D504,R309,U369,R931,U20,L940,U326,L362,D52,R98,D475,L907,D918,R931,D468,R279,D586,R592,U973,R753,D365,R694,U278,R934,U712,R441,U996,L989,D693,L211,D561,R105,D425,R53,U168,L451,U865,L585,D412,L857,U988,R724,U774,R295,U588,R329,D810,L698,D118,R277,U193,R309,U933,R186,D535,R409,U322,L849,U606,R590,U892,L542,D237,R475,D920,R679,U602,L477,D634,L988,D540,L323,U791,L375,U625,L621,U567,L943,U512,L239,D90,L66,U151,R83,U435,R612,D865,L177,U368,R326,U574,L241,U197,R499,U419,R297,U207,L311,D243,L559,D281,R513,U748,L884,U207,R71,D441,R133,D993,L4,D977,L669,U523,L564,U186,R477,U737,L685,U338,L456,U939,R774,U674,L97,D827,R237,D451,R618,D143,R750,U196,L559,D178,L693,D916,R334,U231,L651,U249,R620,U283,L387,U352,L915,U959,L693,U909,R320,U119,L617,U177,L993,D265,R667,U204,R59,D601,L579,U483,R155,D484,L44,D751,R915,U510,L552,U308,R505,U394,R585,U872,L617,U202,R928,U941,R235,U768,R666,D547,L244,D270,R353,D612,R384,U430,L685,D536,R103,U147,R794,D621,L52,U96,L557,D455,L635,D58,R265,U545,R938,D266,L173,U746,L672,D237,R286,U131,R487,U837,R394,D702,R49,U579,L699,U819,L448,D223,L982,D906,L397,U807,L737,D223,L791,D965,R436,U29,R908,D273,R194,U91,R232,U591,L336,D70,R467,U505,L341,U989,R278,U387,L442,U950,R487,D384,L534,D514,L433,U627,R381,U54,L847,U231,L590 diff --git a/03/src/main.zig b/03/src/main.zig new file mode 100644 index 0000000..655a8d4 --- /dev/null +++ b/03/src/main.zig @@ -0,0 +1,213 @@ +const std = @import("std"); + +const max = 512; +const xOrigin = max / 2; +const yOrigin = max / 2; + +const Error = error{ParseError}; + +const State = enum(u8) { + Empty, + Origin, + Line, + Intersect, +}; + +const Direction = enum(u8) { + Up = 'U', + Right = 'R', + Down = 'D', + Left = 'L', + + pub fn parse(in: u8) anyerror!Direction { + return switch (in) { + 'U' => .Up, + 'R' => .Right, + 'D' => .Down, + 'L' => .Left, + else => Error.ParseError, + }; + } +}; + +const Grid = [max][max]State; + +const Step = struct { + d: Direction, + l: u32, + + pub fn parse(in: []const u8) anyerror!Step { + if (in.len < 2) { + return error.ParseError; + } + + return Step{ + .d = try Direction.parse(in[0]), + .l = try std.fmt.parseInt(u32, in[1..in.len], 10), + }; + } +}; + +const World = struct { + x: u32, + y: u32, + grid: *Grid, + + pub fn init(self: *World) void { + for (self.grid) |y, y_offset| { + for (y) |x, x_offset| { + self.grid[y_offset][x_offset] = State.Empty; + } + } + } + + pub fn display(self: *World) void { + for (self.grid) |y, y_offset| { + for (y) |x, x_offset| { + var chr = switch (x) { + State.Empty => " ", + State.Line => ".", + State.Origin => "o", + State.Intersect => "*", + }; + + std.debug.warn("{}", chr); + } + std.debug.warn("\n"); + } + } + + pub fn step(self: *World, in: Step, compare: *Grid) void { + std.debug.warn("Step: {}\n", in); + + switch (in.d) { + .Up => { + self.lineY(self.y - in.l, self.y - 1, compare); + self.y -= in.l; + }, + .Down => { + self.lineY(self.y + 1, self.y + in.l, compare); + self.y += in.l; + }, + .Left => { + self.lineX(self.x - in.l, self.x - 1, compare); + self.x -= in.l; + }, + .Right => { + self.lineX(self.x + 1, self.x + in.l, compare); + self.x += in.l; + }, + } + } + + fn lineX(self: *World, start: u32, end: u32, compare: *Grid) void { + var x: u32 = start; + while (x <= end) : (x += 1) { + self.fill(x, self.y, compare); + } + } + + fn lineY(self: *World, start: u32, end: u32, compare: *Grid) void { + var y: u32 = start; + while (y <= end) : (y += 1) { + self.fill(self.x, y, compare); + } + } + + fn fill(self: *World, x: u32, y: u32, compare: *Grid) void { + std.debug.warn("\tFilling {},{}\n", x, y); + + var newVal: State = switch (compare[y][x]) { + .Line => .Intersect, + else => .Line, + }; + + self.grid[y][x] = newVal; + } +}; + +fn getLine(stream: *std.fs.File.InStream.Stream) anyerror![]Step { + var buf: [10240]u8 = undefined; + var out: [1000]Step = undefined; + var i: u32 = 0; + + var line = (try stream.readUntilDelimiterOrEof(&buf, '\n')) orelse return Error.ParseError; + var iter = std.mem.separate(line, ","); + + while (iter.next()) |value| { + std.debug.assert(i < out.len); + + out[i] = try Step.parse(value); + i += 1; + } + + return out[0..i]; +} + +fn manhattan(x: i32, y: i32) u32 { + return std.math.absCast(x - xOrigin) + std.math.absCast(y - yOrigin); +} + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + + const alloc = &arena.allocator; + const file = std.io.getStdIn(); + const stream = &file.inStream().stream; + + var grid = try alloc.create(Grid); + + var world: World = World{ + .x = xOrigin, + .y = yOrigin, + .grid = grid, + }; + + world.init(); + var compare = std.mem.dupe(alloc, Grid, grid); + + // Line 1 + for (try getLine(stream)) |item| { + world.step(item, compare); + } + + // reset to origin + //std.mem.copy(compare, world.grid); + world.x = xOrigin; + world.y = yOrigin; + + // Line 2 + for (try getLine(stream)) |item| { + world.step(item, compare); + } + + // Ignore the origin + world.grid[yOrigin][xOrigin] = State.Origin; + + // detect collisions + var minMH: u32 = undefined; + var found: bool = false; + for (world.grid) |y, yOff| { + for (y) |x, xOff| { + if (x == State.Intersect) { + const mh = manhattan(@intCast(i32, xOff), @intCast(i32, yOff)); + std.debug.warn("Intersect! {},{} : {}\n", xOff, yOff, mh); + if (found) { + if (minMH > mh) { + minMH = mh; + } + } else { + found = true; + minMH = mh; + } + } + } + } + + if (found) { + std.debug.warn("Smallest manhattan: {}\n", minMH); + } + + // world.display(); +} From 67f3c61d578619b13c6592ad3cb72013a7228203 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Tue, 3 Dec 2019 23:11:58 +0000 Subject: [PATCH 07/32] Day 2.1, horrible but working --- 03/src/main.zig | 146 +++++++++++++++--------------------------------- 1 file changed, 44 insertions(+), 102 deletions(-) diff --git a/03/src/main.zig b/03/src/main.zig index 655a8d4..d016064 100644 --- a/03/src/main.zig +++ b/03/src/main.zig @@ -1,18 +1,14 @@ const std = @import("std"); -const max = 512; -const xOrigin = max / 2; -const yOrigin = max / 2; - const Error = error{ParseError}; -const State = enum(u8) { - Empty, - Origin, - Line, - Intersect, +const Point = struct { + X: i32, + Y: i32, }; +const Points = std.ArrayList(Point); + const Direction = enum(u8) { Up = 'U', Right = 'R', @@ -30,11 +26,9 @@ const Direction = enum(u8) { } }; -const Grid = [max][max]State; - const Step = struct { d: Direction, - l: u32, + l: i32, pub fn parse(in: []const u8) anyerror!Step { if (in.len < 2) { @@ -43,86 +37,55 @@ const Step = struct { return Step{ .d = try Direction.parse(in[0]), - .l = try std.fmt.parseInt(u32, in[1..in.len], 10), + .l = try std.fmt.parseInt(i32, in[1..in.len], 10), }; } }; const World = struct { - x: u32, - y: u32, - grid: *Grid, + entries: Points, + pos: Point, - pub fn init(self: *World) void { - for (self.grid) |y, y_offset| { - for (y) |x, x_offset| { - self.grid[y_offset][x_offset] = State.Empty; - } - } - } - - pub fn display(self: *World) void { - for (self.grid) |y, y_offset| { - for (y) |x, x_offset| { - var chr = switch (x) { - State.Empty => " ", - State.Line => ".", - State.Origin => "o", - State.Intersect => "*", - }; - - std.debug.warn("{}", chr); - } - std.debug.warn("\n"); - } - } - - pub fn step(self: *World, in: Step, compare: *Grid) void { + pub fn step(self: *World, in: Step) anyerror!void { std.debug.warn("Step: {}\n", in); switch (in.d) { .Up => { - self.lineY(self.y - in.l, self.y - 1, compare); - self.y -= in.l; + try self.lineY(self.pos.Y - in.l, self.pos.Y - 1); + self.pos.Y -= in.l; }, .Down => { - self.lineY(self.y + 1, self.y + in.l, compare); - self.y += in.l; + try self.lineY(self.pos.Y + 1, self.pos.Y + in.l); + self.pos.Y += in.l; }, .Left => { - self.lineX(self.x - in.l, self.x - 1, compare); - self.x -= in.l; + try self.lineX(self.pos.X - in.l, self.pos.X - 1); + self.pos.X -= in.l; }, .Right => { - self.lineX(self.x + 1, self.x + in.l, compare); - self.x += in.l; + try self.lineX(self.pos.X + 1, self.pos.X + in.l); + self.pos.X += in.l; }, } } - fn lineX(self: *World, start: u32, end: u32, compare: *Grid) void { - var x: u32 = start; + fn lineX(self: *World, start: i32, end: i32) anyerror!void { + var x: i32 = start; while (x <= end) : (x += 1) { - self.fill(x, self.y, compare); + try self.fill(x, self.pos.Y); } } - fn lineY(self: *World, start: u32, end: u32, compare: *Grid) void { - var y: u32 = start; + fn lineY(self: *World, start: i32, end: i32) anyerror!void { + var y: i32 = start; while (y <= end) : (y += 1) { - self.fill(self.x, y, compare); + try self.fill(self.pos.X, y); } } - fn fill(self: *World, x: u32, y: u32, compare: *Grid) void { - std.debug.warn("\tFilling {},{}\n", x, y); - - var newVal: State = switch (compare[y][x]) { - .Line => .Intersect, - else => .Line, - }; - - self.grid[y][x] = newVal; + fn fill(self: *World, x: i32, y: i32) anyerror!void { + //self.entries = try self.alloc.realloc(self.entries, self.entries.len+1); + self.entries.appendAssumeCapacity(Point{ .X = x, .Y = y }); } }; @@ -145,9 +108,11 @@ fn getLine(stream: *std.fs.File.InStream.Stream) anyerror![]Step { } fn manhattan(x: i32, y: i32) u32 { - return std.math.absCast(x - xOrigin) + std.math.absCast(y - yOrigin); + return std.math.absCast(x) + std.math.absCast(y); } +const maxEntries = 1024 * 1024; + pub fn main() anyerror!void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); @@ -156,58 +121,35 @@ pub fn main() anyerror!void { const file = std.io.getStdIn(); const stream = &file.inStream().stream; - var grid = try alloc.create(Grid); - var world: World = World{ - .x = xOrigin, - .y = yOrigin, - .grid = grid, + .entries = try Points.initCapacity(alloc, maxEntries), + .pos = Point{ .X = 0, .Y = 0 }, }; - world.init(); - var compare = std.mem.dupe(alloc, Grid, grid); - // Line 1 for (try getLine(stream)) |item| { - world.step(item, compare); + try world.step(item); } // reset to origin - //std.mem.copy(compare, world.grid); - world.x = xOrigin; - world.y = yOrigin; + const entriesA = world.entries; + world.entries = try Points.initCapacity(alloc, maxEntries); + world.pos = Point{ .X = 0, .Y = 0 }; // Line 2 for (try getLine(stream)) |item| { - world.step(item, compare); + try world.step(item); } - // Ignore the origin - world.grid[yOrigin][xOrigin] = State.Origin; + const entriesB = world.entries; - // detect collisions - var minMH: u32 = undefined; - var found: bool = false; - for (world.grid) |y, yOff| { - for (y) |x, xOff| { - if (x == State.Intersect) { - const mh = manhattan(@intCast(i32, xOff), @intCast(i32, yOff)); - std.debug.warn("Intersect! {},{} : {}\n", xOff, yOff, mh); - if (found) { - if (minMH > mh) { - minMH = mh; - } - } else { - found = true; - minMH = mh; - } + std.debug.warn("A: {} entries\nB: {} entries\n", entriesA.len, entriesB.len); + + for (entriesA.toSlice()) |a| { + for (entriesB.toSlice()) |b| { + if (a.X == b.X and a.Y == b.Y) { + std.debug.warn("Match! {} => {}\n", a, manhattan(a.X, a.Y)); } } } - - if (found) { - std.debug.warn("Smallest manhattan: {}\n", minMH); - } - - // world.display(); } From fd875fe36b9e115e707cc1bbd0634cb6c4a37199 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Tue, 3 Dec 2019 23:45:30 +0000 Subject: [PATCH 08/32] Day 3.2 --- 03/src/main.zig | 71 ++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/03/src/main.zig b/03/src/main.zig index d016064..e095020 100644 --- a/03/src/main.zig +++ b/03/src/main.zig @@ -5,6 +5,7 @@ const Error = error{ParseError}; const Point = struct { X: i32, Y: i32, + Steps: i32, // number of steps taken to reach this point }; const Points = std.ArrayList(Point); @@ -44,48 +45,52 @@ const Step = struct { const World = struct { entries: Points, - pos: Point, + ticks: i32, + x: i32, + y: i32, - pub fn step(self: *World, in: Step) anyerror!void { - std.debug.warn("Step: {}\n", in); + pub fn step(self: *World, in: Step) void { + std.debug.warn("Step {}: {}\n", self.ticks, in); + var i: i32 = 0; switch (in.d) { .Up => { - try self.lineY(self.pos.Y - in.l, self.pos.Y - 1); - self.pos.Y -= in.l; + while (i < in.l) : (i += 1) { + self.y -= 1; + self.fill(); + } }, .Down => { - try self.lineY(self.pos.Y + 1, self.pos.Y + in.l); - self.pos.Y += in.l; + while (i < in.l) : (i += 1) { + self.y += 1; + self.fill(); + } }, .Left => { - try self.lineX(self.pos.X - in.l, self.pos.X - 1); - self.pos.X -= in.l; + while (i < in.l) : (i += 1) { + self.x -= 1; + self.fill(); + } }, .Right => { - try self.lineX(self.pos.X + 1, self.pos.X + in.l); - self.pos.X += in.l; + while (i < in.l) : (i += 1) { + self.x += 1; + self.fill(); + } }, } } - fn lineX(self: *World, start: i32, end: i32) anyerror!void { - var x: i32 = start; - while (x <= end) : (x += 1) { - try self.fill(x, self.pos.Y); - } - } + fn fill(self: *World) void { + self.ticks += 1; - fn lineY(self: *World, start: i32, end: i32) anyerror!void { - var y: i32 = start; - while (y <= end) : (y += 1) { - try self.fill(self.pos.X, y); - } - } + const point = Point{ .X = self.x, .Y = self.y, .Steps = self.ticks }; - fn fill(self: *World, x: i32, y: i32) anyerror!void { - //self.entries = try self.alloc.realloc(self.entries, self.entries.len+1); - self.entries.appendAssumeCapacity(Point{ .X = x, .Y = y }); + // TODO: use the lower number of ticks for multiple crossings + // I'm lucky, I don't need this. + + std.debug.warn("\t{}\n", point); + self.entries.appendAssumeCapacity(point); } }; @@ -123,22 +128,26 @@ pub fn main() anyerror!void { var world: World = World{ .entries = try Points.initCapacity(alloc, maxEntries), - .pos = Point{ .X = 0, .Y = 0 }, + .ticks = 0, + .x = 0, + .y = 0, }; // Line 1 for (try getLine(stream)) |item| { - try world.step(item); + world.step(item); } // reset to origin const entriesA = world.entries; world.entries = try Points.initCapacity(alloc, maxEntries); - world.pos = Point{ .X = 0, .Y = 0 }; + world.ticks = 0; + world.x = 0; + world.y = 0; // Line 2 for (try getLine(stream)) |item| { - try world.step(item); + world.step(item); } const entriesB = world.entries; @@ -148,7 +157,7 @@ pub fn main() anyerror!void { for (entriesA.toSlice()) |a| { for (entriesB.toSlice()) |b| { if (a.X == b.X and a.Y == b.Y) { - std.debug.warn("Match! {} => {}\n", a, manhattan(a.X, a.Y)); + std.debug.warn("Match! {}, {} => {} : {}\n", a, b, manhattan(a.X, a.Y), a.Steps + b.Steps); } } } From e445b7582ae5a0df0c2c5903bce0b92b34a29fb1 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Tue, 3 Dec 2019 23:51:19 +0000 Subject: [PATCH 09/32] Remove a comment that is wrong in retrospect --- 03/src/main.zig | 4 ---- 1 file changed, 4 deletions(-) diff --git a/03/src/main.zig b/03/src/main.zig index e095020..33a6d3c 100644 --- a/03/src/main.zig +++ b/03/src/main.zig @@ -85,10 +85,6 @@ const World = struct { self.ticks += 1; const point = Point{ .X = self.x, .Y = self.y, .Steps = self.ticks }; - - // TODO: use the lower number of ticks for multiple crossings - // I'm lucky, I don't need this. - std.debug.warn("\t{}\n", point); self.entries.appendAssumeCapacity(point); } From a2607b8508fb153f2845462f94230232fb0c448e Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 4 Dec 2019 23:11:57 +0000 Subject: [PATCH 10/32] Day 4.1 --- 04/build.zig | 14 ++++++++++++++ 04/src/main.zig | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 04/build.zig create mode 100644 04/src/main.zig diff --git a/04/build.zig b/04/build.zig new file mode 100644 index 0000000..843c820 --- /dev/null +++ b/04/build.zig @@ -0,0 +1,14 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("04", "src/main.zig"); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/04/src/main.zig b/04/src/main.zig new file mode 100644 index 0000000..c5310cf --- /dev/null +++ b/04/src/main.zig @@ -0,0 +1,42 @@ +const std = @import("std"); + +const first = 171309; +const last = 643603; + +// - [x] It is a six-digit number (implied) +// - [x] The value is within the range given in your puzzle input (implied) +// - [x] Two adjacent digits are the same (like 22 in 122345). +// - [x] Going from left to right, the digits never decrease; they only ever increase or stay the same (like 111123 or 135679). + +fn tests1(num: i32) anyerror!bool { + var buf: [6]u8 = undefined; + var numStr = try std.fmt.bufPrint(&buf, "{}", num); + + if (numStr[0] > numStr[1] or + numStr[1] > numStr[2] or + numStr[2] > numStr[3] or + numStr[3] > numStr[4] or + numStr[4] > numStr[5] + ) return false; + + return + numStr[0] == numStr[1] or + numStr[1] == numStr[2] or + numStr[2] == numStr[3] or + numStr[3] == numStr[4] or + numStr[4] == numStr[5]; +} + +pub fn main() anyerror!void { + var count: i32 = 0; + var i: i32 = first; + + while (i <= last) : (i+=1) { + if (try tests1(i)) { + //std.debug.warn("Match: {}\n", i); + count+=1; + } + } + + std.debug.warn("Part 1: matches: {}\n", count); +} From be0c611f0d140fd35199534b39a822b72208a1ee Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 4 Dec 2019 23:27:58 +0000 Subject: [PATCH 11/32] Day 4.2 --- 04/src/main.zig | 56 ++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/04/src/main.zig b/04/src/main.zig index c5310cf..b813914 100644 --- a/04/src/main.zig +++ b/04/src/main.zig @@ -1,42 +1,54 @@ const std = @import("std"); const first = 171309; -const last = 643603; +const last = 643603; // - [x] It is a six-digit number (implied) // - [x] The value is within the range given in your puzzle input (implied) // - [x] Two adjacent digits are the same (like 22 in 122345). // - [x] Going from left to right, the digits never decrease; they only ever increase or stay the same (like 111123 or 135679). -fn tests1(num: i32) anyerror!bool { - var buf: [6]u8 = undefined; - var numStr = try std.fmt.bufPrint(&buf, "{}", num); +fn tests1(num: i32, str: []u8) bool { + if (str[0] > str[1] or str[1] > str[2] or + str[2] > str[3] or str[3] > str[4] or + str[4] > str[5]) return false; - if (numStr[0] > numStr[1] or - numStr[1] > numStr[2] or - numStr[2] > numStr[3] or - numStr[3] > numStr[4] or - numStr[4] > numStr[5] - ) return false; + return str[0] == str[1] or str[1] == str[2] or + str[2] == str[3] or str[3] == str[4] or + str[4] == str[5]; +} - return - numStr[0] == numStr[1] or - numStr[1] == numStr[2] or - numStr[2] == numStr[3] or - numStr[3] == numStr[4] or - numStr[4] == numStr[5]; +fn tests2(num: i32, str: []u8) bool { + if (str[0] == str[1] and str[1] != str[2]) return true; // [0 1]2 3 4 5 + if (str[1] == str[2] and str[0] != str[1] and str[2] != str[3]) return true; // 0[1 2]3 4 5 + if (str[2] == str[3] and str[1] != str[2] and str[3] != str[4]) return true; // 0 1[2 3]4 5 + if (str[3] == str[4] and str[2] != str[3] and str[4] != str[5]) return true; // 0 1 2[3 4]5 + if (str[4] == str[5] and str[3] != str[4]) return true; // 0 1 2 3[4 5] + + return false; } pub fn main() anyerror!void { - var count: i32 = 0; + var count1: i32 = 0; + var count2: i32 = 0; var i: i32 = first; - while (i <= last) : (i+=1) { - if (try tests1(i)) { - //std.debug.warn("Match: {}\n", i); - count+=1; + while (i <= last) : (i += 1) { + var buf: [6]u8 = undefined; + var numStr = try std.fmt.bufPrint(&buf, "{}", i); + + if (tests1(i, numStr)) { + count1 += 1; + + if (tests2(i, numStr)) { + std.debug.warn("Match: {}\n", i); + count2 += 1; + } } } - std.debug.warn("Part 1: matches: {}\n", count); + std.debug.warn(" 012345\n"); + + std.debug.warn("Part 1: matches: {}\n", count1); + std.debug.warn("Part 2: matches: {}\n", count2); } From 3ddda35eec9fcf4dc3ada2c142dbf6c47cfffeba Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 4 Dec 2019 23:30:26 +0000 Subject: [PATCH 12/32] Minor speed tweaks for day 4 --- 04/src/main.zig | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/04/src/main.zig b/04/src/main.zig index b813914..e524fad 100644 --- a/04/src/main.zig +++ b/04/src/main.zig @@ -8,7 +8,7 @@ const last = 643603; // - [x] Two adjacent digits are the same (like 22 in 122345). // - [x] Going from left to right, the digits never decrease; they only ever increase or stay the same (like 111123 or 135679). -fn tests1(num: i32, str: []u8) bool { +inline fn tests1(num: i32, str: []u8) bool { if (str[0] > str[1] or str[1] > str[2] or str[2] > str[3] or str[3] > str[4] or str[4] > str[5]) return false; @@ -18,7 +18,7 @@ fn tests1(num: i32, str: []u8) bool { str[4] == str[5]; } -fn tests2(num: i32, str: []u8) bool { +inline fn tests2(num: i32, str: []u8) bool { if (str[0] == str[1] and str[1] != str[2]) return true; // [0 1]2 3 4 5 if (str[1] == str[2] and str[0] != str[1] and str[2] != str[3]) return true; // 0[1 2]3 4 5 if (str[2] == str[3] and str[1] != str[2] and str[3] != str[4]) return true; // 0 1[2 3]4 5 @@ -41,13 +41,12 @@ pub fn main() anyerror!void { count1 += 1; if (tests2(i, numStr)) { - std.debug.warn("Match: {}\n", i); count2 += 1; } } } - std.debug.warn(" 012345\n"); + //std.debug.warn(" 012345\n"); std.debug.warn("Part 1: matches: {}\n", count1); std.debug.warn("Part 2: matches: {}\n", count2); From 2f4ca301ad203f527e654bcc8c8ee65dda7a57aa Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 5 Dec 2019 19:45:14 +0000 Subject: [PATCH 13/32] Refactor intcode in preparation for day 5 --- 02/src/main.zig | 30 ++++++++++++---- lib/intcode/intcode.zig | 78 ++++++++++++++++++++++++++++------------- 2 files changed, 77 insertions(+), 31 deletions(-) diff --git a/02/src/main.zig b/02/src/main.zig index 3918edf..270da8c 100644 --- a/02/src/main.zig +++ b/02/src/main.zig @@ -1,6 +1,24 @@ const std = @import("std"); const intcode = @import("intcode"); +fn run(program: []i32, noun: i32, verb: i32) i32 { + program[1] = noun; + program[2] = verb; + + intcode.run(program); + + return program[0]; +} + +fn runCopy(alloc: *std.mem.Allocator, program: []i32, noun: i32, verb: i32) anyerror!i32 { + var memory = try alloc.alloc(i32, program.len); + defer alloc.free(memory); + + std.mem.copy(i32, memory, program); + + return run(memory, noun, verb); +} + pub fn main() anyerror!void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); @@ -10,18 +28,18 @@ pub fn main() anyerror!void { var program = try intcode.loadFromStdIn(alloc); // Part 1 - std.debug.warn("Part 1: {}\n", try intcode.runCopy(alloc, program, 12, 2)); + std.debug.warn("Part 1: {}\n", try runCopy(alloc, program, 12, 2)); // Part 2: 100*100 = 10,000 combinations to try. - var memory: []u32 = try alloc.alloc(u32, program.len); + var memory: []i32 = try alloc.alloc(i32, program.len); var done: bool = false; - var noun: u32 = 0; - var verb: u32 = 0; + var noun: i32 = 0; + var verb: i32 = 0; std.debug.warn("Part 2: Searching..."); while (!done) { - std.mem.copy(u32, memory, program); - const result = try intcode.run(memory, noun, verb); + std.mem.copy(i32, memory, program); + const result = run(memory, noun, verb); // Too high: 250800 (noun=33, verb=76) if (result == 19690720) { diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 95a8f78..95a546d 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -1,14 +1,14 @@ const std = @import("std"); -pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]u32 { - var program = try alloc.alloc(u32, 1024); +pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 { + var program = try alloc.alloc(i32, 1024); var buf = [_]u8{0} ** 255; var i: u32 = 0; while (try stream.readUntilDelimiterOrEof(&buf, ',')) |num| { var trimmed = std.mem.trimRight(u8, num, "\r\n"); - program[i] = try std.fmt.parseInt(u32, trimmed, 10); + program[i] = try std.fmt.parseInt(i32, trimmed, 10); std.debug.warn("{},", program[i]); @@ -20,26 +20,14 @@ pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.S return program[0..program.len]; } -pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]u32 { +pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]i32 { const file = std.io.getStdIn(); const stream = &file.inStream().stream; return loadFromStream(alloc, stream); } -pub fn runCopy(alloc: *std.mem.Allocator, program: []u32, noun: u32, verb: u32) anyerror!u32 { - var memory = try alloc.alloc(u32, program.len); - defer alloc.free(memory); - - std.mem.copy(u32, memory, program); - - return run(memory, noun, verb); -} - -pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 { - program[1] = noun; - program[2] = verb; - +pub fn run(program: []i32) void { // Initial program state var ip: u32 = 0; var exit: bool = false; @@ -50,23 +38,23 @@ pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 { // std.debug.warn(" IP {d:4}: ", ip); const opcode = switch (program[ip]) { 1 => { - var a = program[program[ip + 1]]; - var b = program[program[ip + 2]]; + var a = program[@intCast(usize, program[ip + 1])]; + var b = program[@intCast(usize, program[ip + 2])]; var dest = program[ip + 3]; var result = a + b; // std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); - program[dest] = result; + program[@intCast(usize, dest)] = result; ip += 4; }, 2 => { - var a = program[program[ip + 1]]; - var b = program[program[ip + 2]]; + var a = program[@intCast(usize, program[ip + 1])]; + var b = program[@intCast(usize, program[ip + 2])]; var dest = program[ip + 3]; var result = a * b; // std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); - program[dest] = result; + program[@intCast(usize, dest)] = result; ip += 4; }, 99 => { @@ -79,6 +67,46 @@ pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 { }, }; } - - return program[0]; +} + +const assert = std.debug.assert; + +test "day 2 example 1" { + var before: [12]i32 = .{ 1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50 }; + var after: [12]i32 = .{ 3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50 }; + + run(before[0..before.len]); + assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); +} + +test "day 2 example 2" { + var before: [5]i32 = .{ 1, 0, 0, 0, 99 }; + var after: [5]i32 = .{ 2, 0, 0, 0, 99 }; + + run(before[0..before.len]); + assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); +} + +test "day 2 example 3" { + var before: [5]i32 = .{ 2, 3, 0, 3, 99 }; + var after: [5]i32 = .{ 2, 3, 0, 6, 99 }; + + run(before[0..before.len]); + assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); +} + +test "day 2 example 4" { + var before: [6]i32 = .{ 2, 4, 4, 5, 99, 0 }; + var after: [6]i32 = .{ 2, 4, 4, 5, 99, 9801 }; + + run(before[0..before.len]); + assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); +} + +test "day 2 example 5" { + var before: [9]i32 = .{ 1, 1, 1, 4, 99, 5, 6, 0, 99 }; + var after: [9]i32 = .{ 30, 1, 1, 4, 2, 5, 6, 0, 99 }; + + run(before[0..before.len]); + assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } From 032451ad74cea8db864bda3d7b3f3e6628bb20e2 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 5 Dec 2019 22:07:05 +0000 Subject: [PATCH 14/32] More intcode refactoring --- 02/src/main.zig | 4 ++- lib/intcode/intcode.zig | 71 +++++++++++++++++++++++++---------------- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/02/src/main.zig b/02/src/main.zig index 270da8c..45b6022 100644 --- a/02/src/main.zig +++ b/02/src/main.zig @@ -5,7 +5,9 @@ fn run(program: []i32, noun: i32, verb: i32) i32 { program[1] = noun; program[2] = verb; - intcode.run(program); + var machine = &intcode.Machine{ .memory = program, .ip = 0 }; + + machine.run(); return program[0]; } diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 95a546d..661f8ac 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -27,86 +27,101 @@ pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]i32 { return loadFromStream(alloc, stream); } -pub fn run(program: []i32) void { - // Initial program state - var ip: u32 = 0; - var exit: bool = false; +pub const Machine = struct { + memory: []i32, - // TODO: create a nice struct + ip: usize = 0, - while (!exit) { - // std.debug.warn(" IP {d:4}: ", ip); - const opcode = switch (program[ip]) { + pub fn Run(program: []i32) anyerror!Machine { + var machine = try init(program); + + machine.run(); + + return machine; + } + + pub fn init(program: []i32) anyerror!Machine { + return Machine{ .memory = program }; + } + + pub fn run(self: *Machine) void { + while (self.step()) {} + } + + pub fn step(self: *Machine) bool { + var program = self.memory; + + const opcode = switch (program[self.ip]) { 1 => { - var a = program[@intCast(usize, program[ip + 1])]; - var b = program[@intCast(usize, program[ip + 2])]; - var dest = program[ip + 3]; + var a = program[@intCast(usize, program[self.ip + 1])]; + var b = program[@intCast(usize, program[self.ip + 2])]; + var dest = program[self.ip + 3]; var result = a + b; - // std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); program[@intCast(usize, dest)] = result; - ip += 4; + self.ip += 4; }, 2 => { - var a = program[@intCast(usize, program[ip + 1])]; - var b = program[@intCast(usize, program[ip + 2])]; - var dest = program[ip + 3]; + var a = program[@intCast(usize, program[self.ip + 1])]; + var b = program[@intCast(usize, program[self.ip + 2])]; + var dest = program[self.ip + 3]; var result = a * b; - // std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); program[@intCast(usize, dest)] = result; - ip += 4; + self.ip += 4; }, 99 => { - // std.debug.warn("EXIT\n"); - exit = true; + self.ip += 1; + return false; }, else => { - std.debug.warn("Unknown opcode at IP {}: {}", ip, program[ip]); - exit = true; + std.debug.warn("Unknown opcode at IP {}: {}", self.ip, program[self.ip]); + return false; }, }; + + return true; } -} +}; const assert = std.debug.assert; test "day 2 example 1" { var before: [12]i32 = .{ 1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50 }; var after: [12]i32 = .{ 3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50 }; + var machine = Machine.Run(before[0..before.len]); - run(before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } test "day 2 example 2" { var before: [5]i32 = .{ 1, 0, 0, 0, 99 }; var after: [5]i32 = .{ 2, 0, 0, 0, 99 }; + var machine = Machine.Run(before[0..before.len]); - run(before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } test "day 2 example 3" { var before: [5]i32 = .{ 2, 3, 0, 3, 99 }; var after: [5]i32 = .{ 2, 3, 0, 6, 99 }; + var machine = Machine.Run(before[0..before.len]); - run(before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } test "day 2 example 4" { var before: [6]i32 = .{ 2, 4, 4, 5, 99, 0 }; var after: [6]i32 = .{ 2, 4, 4, 5, 99, 9801 }; + var machine = Machine.Run(before[0..before.len]); - run(before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } test "day 2 example 5" { var before: [9]i32 = .{ 1, 1, 1, 4, 99, 5, 6, 0, 99 }; var after: [9]i32 = .{ 30, 1, 1, 4, 2, 5, 6, 0, 99 }; + var machine = Machine.Run(before[0..before.len]); - run(before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } From 0ffe0410b4c3466106079d5da8ea64896f24149c Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 5 Dec 2019 22:31:18 +0000 Subject: [PATCH 15/32] Add character devices --- 02/src/main.zig | 12 ++++------ lib/intcode/intcode.zig | 52 ++++++++++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/02/src/main.zig b/02/src/main.zig index 45b6022..94ee58d 100644 --- a/02/src/main.zig +++ b/02/src/main.zig @@ -1,24 +1,22 @@ const std = @import("std"); const intcode = @import("intcode"); -fn run(program: []i32, noun: i32, verb: i32) i32 { +fn run(alloc: *std.mem.Allocator, program: []i32, noun: i32, verb: i32) !i32 { program[1] = noun; program[2] = verb; - var machine = &intcode.Machine{ .memory = program, .ip = 0 }; - - machine.run(); + var machine = try intcode.Machine.Run(alloc, program); return program[0]; } -fn runCopy(alloc: *std.mem.Allocator, program: []i32, noun: i32, verb: i32) anyerror!i32 { +fn runCopy(alloc: *std.mem.Allocator, program: []i32, noun: i32, verb: i32) !i32 { var memory = try alloc.alloc(i32, program.len); defer alloc.free(memory); std.mem.copy(i32, memory, program); - return run(memory, noun, verb); + return run(alloc, memory, noun, verb); } pub fn main() anyerror!void { @@ -41,7 +39,7 @@ pub fn main() anyerror!void { std.debug.warn("Part 2: Searching..."); while (!done) { std.mem.copy(i32, memory, program); - const result = run(memory, noun, verb); + const result = try run(alloc, memory, noun, verb); // Too high: 250800 (noun=33, verb=76) if (result == 19690720) { diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 661f8ac..062bdaa 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -1,5 +1,8 @@ const std = @import("std"); +const CharDev = std.ArrayList(i32); +const CharDevLimit = 32; + pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 { var program = try alloc.alloc(i32, 1024); @@ -32,23 +35,30 @@ pub const Machine = struct { ip: usize = 0, - pub fn Run(program: []i32) anyerror!Machine { - var machine = try init(program); + input: CharDev, + output: CharDev, - machine.run(); + pub fn Run(alloc: *std.mem.Allocator, program: []i32) anyerror!Machine { + var machine = try init(alloc, program); + + try machine.run(); return machine; } - pub fn init(program: []i32) anyerror!Machine { - return Machine{ .memory = program }; + pub fn init(alloc: *std.mem.Allocator, program: []i32) anyerror!Machine { + return Machine{ + .memory = program, + .input = try CharDev.initCapacity(alloc, CharDevLimit), + .output = try CharDev.initCapacity(alloc, CharDevLimit), + }; } - pub fn run(self: *Machine) void { - while (self.step()) {} + pub fn run(self: *Machine) anyerror!void { + while (try self.step()) {} } - pub fn step(self: *Machine) bool { + pub fn step(self: *Machine) anyerror!bool { var program = self.memory; const opcode = switch (program[self.ip]) { @@ -75,7 +85,7 @@ pub const Machine = struct { return false; }, else => { - std.debug.warn("Unknown opcode at IP {}: {}", self.ip, program[self.ip]); + std.debug.warn("Unknown opcode at IP {}: {}\n", self.ip, program[self.ip]); return false; }, }; @@ -85,11 +95,12 @@ pub const Machine = struct { }; const assert = std.debug.assert; +const test_allocator = std.heap.page_allocator; test "day 2 example 1" { var before: [12]i32 = .{ 1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50 }; var after: [12]i32 = .{ 3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50 }; - var machine = Machine.Run(before[0..before.len]); + var machine = try Machine.Run(test_allocator, before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } @@ -97,7 +108,7 @@ test "day 2 example 1" { test "day 2 example 2" { var before: [5]i32 = .{ 1, 0, 0, 0, 99 }; var after: [5]i32 = .{ 2, 0, 0, 0, 99 }; - var machine = Machine.Run(before[0..before.len]); + var machine = try Machine.Run(test_allocator, before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } @@ -105,7 +116,7 @@ test "day 2 example 2" { test "day 2 example 3" { var before: [5]i32 = .{ 2, 3, 0, 3, 99 }; var after: [5]i32 = .{ 2, 3, 0, 6, 99 }; - var machine = Machine.Run(before[0..before.len]); + var machine = try Machine.Run(test_allocator, before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } @@ -113,7 +124,7 @@ test "day 2 example 3" { test "day 2 example 4" { var before: [6]i32 = .{ 2, 4, 4, 5, 99, 0 }; var after: [6]i32 = .{ 2, 4, 4, 5, 99, 9801 }; - var machine = Machine.Run(before[0..before.len]); + var machine = try Machine.Run(test_allocator, before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } @@ -121,7 +132,20 @@ test "day 2 example 4" { test "day 2 example 5" { var before: [9]i32 = .{ 1, 1, 1, 4, 99, 5, 6, 0, 99 }; var after: [9]i32 = .{ 30, 1, 1, 4, 2, 5, 6, 0, 99 }; - var machine = Machine.Run(before[0..before.len]); + var machine = try Machine.Run(test_allocator, before[0..before.len]); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); } + +test "day 5 example 1" { + var before: [5]i32 = .{ 3, 0, 4, 0, 99 }; + var after = before; + var machine = try Machine.init(test_allocator, before[0..before.len]); + + try machine.input.append(666); + try machine.run(); + + assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); + assert(machine.output.len == 1); + assert(machine.output.at(0) == 666); +} From a46f56da7f66d9eb61c6bae523c6624ccbeaebea Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 5 Dec 2019 22:45:18 +0000 Subject: [PATCH 16/32] Implement opcodes 3 and 4, naively --- lib/intcode/intcode.zig | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 062bdaa..fe9b82b 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -80,6 +80,19 @@ pub const Machine = struct { program[@intCast(usize, dest)] = result; self.ip += 4; }, + 3 => { + const input = self.input.orderedRemove(0); + const dest = program[self.ip + 1]; + + program[@intCast(usize, dest)] = input; + self.ip += 2; + }, + 4 => { + const output = program[@intCast(usize, program[self.ip + 1])]; + + try self.output.append(output); + self.ip += 2; + }, 99 => { self.ip += 1; return false; @@ -139,7 +152,7 @@ test "day 2 example 5" { test "day 5 example 1" { var before: [5]i32 = .{ 3, 0, 4, 0, 99 }; - var after = before; + var after: [5]i32 = .{ 666, 0, 4, 0, 99 }; var machine = try Machine.init(test_allocator, before[0..before.len]); try machine.input.append(666); From 156e9250b3ab866bdec171bef9ce450d39e22e2e Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 6 Dec 2019 00:10:14 +0000 Subject: [PATCH 17/32] Day 5.1 --- 05/build.zig | 15 ++++ 05/input | 1 + 05/src/main.zig | 20 +++++ lib/intcode/intcode.zig | 181 ++++++++++++++++++++++++++++++++-------- 4 files changed, 184 insertions(+), 33 deletions(-) create mode 100644 05/build.zig create mode 100644 05/input create mode 100644 05/src/main.zig diff --git a/05/build.zig b/05/build.zig new file mode 100644 index 0000000..c228b31 --- /dev/null +++ b/05/build.zig @@ -0,0 +1,15 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("05", "src/main.zig"); + exe.addPackagePath("intcode", "../lib/intcode/intcode.zig"); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/05/input b/05/input new file mode 100644 index 0000000..2109937 --- /dev/null +++ b/05/input @@ -0,0 +1 @@ +3,225,1,225,6,6,1100,1,238,225,104,0,1102,40,93,224,1001,224,-3720,224,4,224,102,8,223,223,101,3,224,224,1,224,223,223,1101,56,23,225,1102,64,78,225,1102,14,11,225,1101,84,27,225,1101,7,82,224,1001,224,-89,224,4,224,1002,223,8,223,1001,224,1,224,1,224,223,223,1,35,47,224,1001,224,-140,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,1101,75,90,225,101,9,122,224,101,-72,224,224,4,224,1002,223,8,223,101,6,224,224,1,224,223,223,1102,36,63,225,1002,192,29,224,1001,224,-1218,224,4,224,1002,223,8,223,1001,224,7,224,1,223,224,223,102,31,218,224,101,-2046,224,224,4,224,102,8,223,223,101,4,224,224,1,224,223,223,1001,43,38,224,101,-52,224,224,4,224,1002,223,8,223,101,5,224,224,1,223,224,223,1102,33,42,225,2,95,40,224,101,-5850,224,224,4,224,1002,223,8,223,1001,224,7,224,1,224,223,223,1102,37,66,225,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1007,226,677,224,1002,223,2,223,1005,224,329,1001,223,1,223,1007,226,226,224,1002,223,2,223,1006,224,344,101,1,223,223,1107,677,226,224,102,2,223,223,1006,224,359,1001,223,1,223,108,677,677,224,1002,223,2,223,1006,224,374,1001,223,1,223,107,677,677,224,1002,223,2,223,1005,224,389,101,1,223,223,8,677,677,224,1002,223,2,223,1005,224,404,1001,223,1,223,108,226,226,224,1002,223,2,223,1005,224,419,101,1,223,223,1008,677,677,224,1002,223,2,223,1005,224,434,101,1,223,223,1008,226,226,224,1002,223,2,223,1005,224,449,101,1,223,223,7,677,226,224,1002,223,2,223,1006,224,464,1001,223,1,223,7,226,226,224,1002,223,2,223,1005,224,479,1001,223,1,223,1007,677,677,224,102,2,223,223,1005,224,494,101,1,223,223,1108,677,226,224,102,2,223,223,1006,224,509,1001,223,1,223,8,677,226,224,102,2,223,223,1005,224,524,1001,223,1,223,1107,226,226,224,102,2,223,223,1006,224,539,1001,223,1,223,1008,226,677,224,1002,223,2,223,1006,224,554,1001,223,1,223,1107,226,677,224,1002,223,2,223,1006,224,569,1001,223,1,223,1108,677,677,224,102,2,223,223,1005,224,584,101,1,223,223,7,226,677,224,102,2,223,223,1006,224,599,1001,223,1,223,1108,226,677,224,102,2,223,223,1006,224,614,101,1,223,223,107,226,677,224,1002,223,2,223,1005,224,629,101,1,223,223,108,226,677,224,1002,223,2,223,1005,224,644,101,1,223,223,8,226,677,224,1002,223,2,223,1005,224,659,1001,223,1,223,107,226,226,224,1002,223,2,223,1006,224,674,101,1,223,223,4,223,99,226 diff --git a/05/src/main.zig b/05/src/main.zig new file mode 100644 index 0000000..ae55384 --- /dev/null +++ b/05/src/main.zig @@ -0,0 +1,20 @@ +const std = @import("std"); +const intcode = @import("intcode"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + + const alloc = &arena.allocator; + + var program = try intcode.loadFromStdIn(alloc); + var machine = try intcode.Machine.init(alloc, program); + + try machine.input.append(1); // Air conditioner unit + try machine.run(); + + std.debug.warn("Part 1\n"); + for (machine.output.toSlice()) |value, idx| { + std.debug.warn("Test {}: {}\n", idx, value); + } +} diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index fe9b82b..50460ca 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -30,6 +30,58 @@ pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]i32 { return loadFromStream(alloc, stream); } +const Opcode = enum(u8) { + ADD = 1, + MULT = 2, + IN = 3, + OUT = 4, + END = 99, +}; + +const Mode = enum(u8) { + Position = 0, + Immediate = 1, +}; + +const Instruction = struct { + op: Opcode, + + // Modes for each parameter of the opcode. Parameter 0 is in position 0, etc + modes: [3]Mode, + + pub fn decode(value: i32) !Instruction { + assert(value > 0 and value < 99999); + + var buf: [6]u8 = undefined; + const str = try std.fmt.bufPrint(&buf, "{d:0<6}", value); + const op = ((str[4] - '0') * 10) + (str[5] - '0'); + + return Instruction{ + .op = @intToEnum(Opcode, op), + .modes = [3]Mode{ + @intToEnum(Mode, buf[3] - '0'), + @intToEnum(Mode, buf[2] - '0'), + @intToEnum(Mode, buf[1] - '0'), + }, + }; + } + + /// Number of bytes taken up by a particular instruction + pub fn size(self: Instruction) usize { + return switch (self.op) { + .ADD => 4, + .MULT => 4, + .IN => 2, + .OUT => 2, + .END => 1, + }; + } + + pub fn halt(self: Instruction) bool { + return self.op == .END; + } +}; + pub const Machine = struct { memory: []i32, @@ -58,52 +110,52 @@ pub const Machine = struct { while (try self.step()) {} } + /// Read an immediate or position value from memory. Parameter determines + /// which field following the current instruction to read from + inline fn __read(self: *Machine, parameter: usize, mode: Mode) i32 { + const immediate = self.memory[self.ip + parameter + 1]; + + return switch (mode) { + .Immediate => immediate, + .Position => self.memory[@intCast(usize, immediate)], + }; + } + + inline fn __write(self: *Machine, parameter: usize, value: i32) void { + const dest = self.__read(parameter, .Immediate); + self.memory[@intCast(usize, dest)] = value; + } + pub fn step(self: *Machine) anyerror!bool { var program = self.memory; + const insn = try Instruction.decode(program[self.ip]); - const opcode = switch (program[self.ip]) { - 1 => { - var a = program[@intCast(usize, program[self.ip + 1])]; - var b = program[@intCast(usize, program[self.ip + 2])]; - var dest = program[self.ip + 3]; - var result = a + b; + const opcode = switch (insn.op) { + .ADD => { + const a = self.__read(0, insn.modes[0]); + const b = self.__read(1, insn.modes[1]); - program[@intCast(usize, dest)] = result; - self.ip += 4; + self.__write(2, a + b); }, - 2 => { - var a = program[@intCast(usize, program[self.ip + 1])]; - var b = program[@intCast(usize, program[self.ip + 2])]; - var dest = program[self.ip + 3]; - var result = a * b; - program[@intCast(usize, dest)] = result; - self.ip += 4; - }, - 3 => { - const input = self.input.orderedRemove(0); - const dest = program[self.ip + 1]; + .MULT => { + const a = self.__read(0, insn.modes[0]); + const b = self.__read(1, insn.modes[1]); - program[@intCast(usize, dest)] = input; - self.ip += 2; + self.__write(2, a * b); }, - 4 => { - const output = program[@intCast(usize, program[self.ip + 1])]; - try self.output.append(output); - self.ip += 2; + .IN => { + self.__write(0, self.input.orderedRemove(0)); }, - 99 => { - self.ip += 1; - return false; - }, - else => { - std.debug.warn("Unknown opcode at IP {}: {}\n", self.ip, program[self.ip]); - return false; + .OUT => { + try self.output.append(self.__read(0, insn.modes[0])); }, + .END => {}, }; - return true; + self.ip += insn.size(); + return !insn.halt(); } }; @@ -162,3 +214,66 @@ test "day 5 example 1" { assert(machine.output.len == 1); assert(machine.output.at(0) == 666); } + +test "Instruction#decode ADD" { + const insn = try Instruction.decode(1); + + assert(insn.op == Opcode.ADD); + assert(insn.modes[0] == .Position); + assert(insn.modes[1] == .Position); + assert(insn.modes[2] == .Position); +} + +test "Instruction#decode MULT" { + const insn = try Instruction.decode(2); + + assert(insn.op == Opcode.MULT); + assert(insn.modes[0] == .Position); + assert(insn.modes[1] == .Position); + assert(insn.modes[2] == .Position); +} + +test "Instruction#decode IN" { + const insn = try Instruction.decode(3); + + assert(insn.op == Opcode.IN); + assert(insn.modes[0] == .Position); + assert(insn.modes[1] == .Position); + assert(insn.modes[2] == .Position); +} + +test "Instruction#decode OUT" { + const insn = try Instruction.decode(4); + + assert(insn.op == Opcode.OUT); + assert(insn.modes[0] == .Position); + assert(insn.modes[1] == .Position); + assert(insn.modes[2] == .Position); +} + +test "Instruction#decode END Position" { + const insn = try Instruction.decode(99); + + assert(insn.op == Opcode.END); + assert(insn.modes[0] == .Position); + assert(insn.modes[1] == .Position); + assert(insn.modes[2] == .Position); +} + +test "Instruction#decode END Immediate" { + const insn = try Instruction.decode(11199); + + assert(insn.op == Opcode.END); + assert(insn.modes[0] == .Immediate); + assert(insn.modes[1] == .Immediate); + assert(insn.modes[2] == .Immediate); +} + +test "Instruction#decode END mixed" { + const insn = try Instruction.decode(10099); + + assert(insn.op == Opcode.END); + assert(insn.modes[0] == .Position); + assert(insn.modes[1] == .Position); + assert(insn.modes[2] == .Immediate); +} From ec0fc3ef1b68c2dbf3e975487b1fab5b639e12e9 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 6 Dec 2019 00:14:20 +0000 Subject: [PATCH 18/32] Add a little helper to run all intcode challenges --- run-intcodes | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 run-intcodes diff --git a/run-intcodes b/run-intcodes new file mode 100755 index 0000000..dcf2052 --- /dev/null +++ b/run-intcodes @@ -0,0 +1,4 @@ +#!/bin/sh +zig test lib/intcode/intcode.zig +zig build --build-file 02/build.zig run < 02/input +zig build --build-file 05/build.zig run < 05/input From 881cdd6e3243221fbe3acb2e40517dc858fb8e1e Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 6 Dec 2019 00:44:48 +0000 Subject: [PATCH 19/32] Day 5.2 --- 05/src/main.zig | 22 +++++++++++++----- lib/intcode/intcode.zig | 50 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/05/src/main.zig b/05/src/main.zig index ae55384..dee0a3a 100644 --- a/05/src/main.zig +++ b/05/src/main.zig @@ -7,14 +7,26 @@ pub fn main() anyerror!void { const alloc = &arena.allocator; - var program = try intcode.loadFromStdIn(alloc); - var machine = try intcode.Machine.init(alloc, program); + var p1 = try intcode.loadFromStdIn(alloc); + var p2 = try alloc.alloc(i32, p1.len); + std.mem.copy(i32, p2, p1); - try machine.input.append(1); // Air conditioner unit - try machine.run(); + var m1 = try intcode.Machine.init(alloc, p1); + var m2 = try intcode.Machine.init(alloc, p2); std.debug.warn("Part 1\n"); - for (machine.output.toSlice()) |value, idx| { + try m1.input.append(1); // Air conditioner unit + try m1.run(); + + for (m1.output.toSlice()) |value, idx| { + std.debug.warn("Test {}: {}\n", idx, value); + } + + std.debug.warn("\nPart 2\n"); + try m2.input.append(5); // Thermal radiator controller + try m2.run(); + + for (m2.output.toSlice()) |value, idx| { std.debug.warn("Test {}: {}\n", idx, value); } } diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 50460ca..039fc20 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -35,6 +35,10 @@ const Opcode = enum(u8) { MULT = 2, IN = 3, OUT = 4, + JNZ = 5, + JZ = 6, + LT = 7, + EQ = 8, END = 99, }; @@ -73,6 +77,10 @@ const Instruction = struct { .MULT => 4, .IN => 2, .OUT => 2, + .JNZ => 3, + .JZ => 3, + .LT => 4, + .EQ => 4, .END => 1, }; } @@ -127,8 +135,8 @@ pub const Machine = struct { } pub fn step(self: *Machine) anyerror!bool { - var program = self.memory; - const insn = try Instruction.decode(program[self.ip]); + const insn = try Instruction.decode(self.memory[self.ip]); + const start_ip = self.ip; const opcode = switch (insn.op) { .ADD => { @@ -148,13 +156,49 @@ pub const Machine = struct { .IN => { self.__write(0, self.input.orderedRemove(0)); }, + .OUT => { try self.output.append(self.__read(0, insn.modes[0])); }, + + .JNZ => { + if (self.__read(0, insn.modes[0]) != 0) + self.ip = @intCast(usize, self.__read(1, insn.modes[1])); + }, + + .JZ => { + if (self.__read(0, insn.modes[0]) == 0) + self.ip = @intCast(usize, self.__read(1, insn.modes[1])); + }, + + .LT => { + const a = self.__read(0, insn.modes[0]); + const b = self.__read(1, insn.modes[1]); + + if (a < b) { + self.__write(2, 1); + } else { + self.__write(2, 0); + } + }, + + .EQ => { + const a = self.__read(0, insn.modes[0]); + const b = self.__read(1, insn.modes[1]); + + if (a == b) { + self.__write(2, 1); + } else { + self.__write(2, 0); + } + }, + .END => {}, }; - self.ip += insn.size(); + // Only modify IP if the instruction itself has not + if (self.ip == start_ip) self.ip += insn.size(); + return !insn.halt(); } }; From cc0f18f48f367f7a5b4b27ed0159a6e8b9e524ea Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 6 Dec 2019 20:11:27 +0000 Subject: [PATCH 20/32] Day 6.1 --- 06/build.zig | 14 + 06/input | 1062 +++++++++++++++++++++++++++++++++++++++++++++++ 06/src/main.zig | 102 +++++ 3 files changed, 1178 insertions(+) create mode 100644 06/build.zig create mode 100644 06/input create mode 100644 06/src/main.zig diff --git a/06/build.zig b/06/build.zig new file mode 100644 index 0000000..7300f55 --- /dev/null +++ b/06/build.zig @@ -0,0 +1,14 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("06", "src/main.zig"); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/06/input b/06/input new file mode 100644 index 0000000..2364732 --- /dev/null +++ b/06/input @@ -0,0 +1,1062 @@ +XNR)9W1 +VGS)XCW +WS5)5XM +T9F)RTN +RQ8)67Q +1WV)YS3 +V69)VCK +65J)756 +ZLV)DZ2 +1GM)JCS +SW3)DFT +LF8)P6Z +VDS)W5H +RMK)5BK +48J)VGR +LQF)LGD +KRW)FVR +BDP)TRT +D7B)SHH +LB4)1SJ +4ZH)127 +YFJ)RQP +KS1)93V +L2J)MRG +VXQ)NR2 +HNL)9HZ +RRK)B98 +KM5)86H +DSW)DRS +XXB)KQT +YDQ)VQ3 +RX9)V7D +CFJ)RHM +4MD)SW3 +7G4)LZ8 +Z34)NTS +RW1)89Y +X5Q)1GM +NVY)TC7 +4TR)PV8 +T28)1QV +PMM)62K +NG1)KKT +B7N)RH4 +T1F)3QJ +19P)V2V +2SB)SY2 +PV8)J3H +TRP)RMK +RWW)9TY +3N7)9F8 +92D)C1N +GLC)TNW +LF8)W7C +TT3)YHN +RKK)NK6 +SL6)ZCH +K4V)NXP +SXT)VQT +VQV)QDJ +PQ4)K84 +KXN)GMT +JN9)SBR +84X)QPY +HQM)SS4 +H1T)W18 +ZRQ)LVY +NY1)BLY +DRS)71Q +F26)RQ8 +TH2)THY +T35)ZC1 +TBH)LQF +2NK)2XM +PY5)N5Q +M69)345 +99P)92S +C22)3YW +Q9T)N5N +KQJ)1CV +FCK)VDS +43S)SQY +FTZ)T1G +57L)GVB +RG5)QSW +7LJ)HWL +VF4)HXG +XZ6)MDZ +5HS)M6Q +YSY)BCZ +GJZ)1DH +SSB)WXT +T1G)K39 +8QC)8RX +H7M)8G3 +PB9)BS3 +518)1X8 +4V7)2S6 +4V3)MH3 +BLY)XXB +XJL)DD4 +WMM)3VV +XTW)77B +ZKJ)VXJ +FVR)CFJ +G54)SGB +YHN)5LW +5CK)V4J +LVY)339 +V6S)QX3 +GQ5)4MB +GXH)ZGD +YPX)S1G +5PH)1BX +THJ)2NK +9ND)K9D +89Z)52F +79P)S6R +DH9)XHZ +8RX)4MD +T1L)GL4 +7TT)5K2 +V81)6CP +22F)ZD2 +ZXC)QWZ +QLT)VH6 +4SG)HDF +N82)S9Y +MQM)6KF +KDX)BKX +471)1KX +4JL)Y5R +XQX)RLC +Y9L)X4G +V9J)89P +H5V)MZ2 +TNX)1JM +694)KWK +C5W)D6Q +SZL)XB3 +CY8)4ZL +NCW)NVY +J75)L2J +KQT)35G +Z6V)DD2 +NZ7)DN6 +P56)PW3 +1VY)41W +MFN)SQQ +2H1)LPH +NTW)DSW +KRK)LTQ +71R)LF8 +9ZM)PW7 +11J)WW6 +1Y9)V6K +T71)XZK +5PH)PVL +4ZL)TYX +ZMY)FBQ +KTY)D7B +MR3)SG4 +3P6)1ZN +XV9)P46 +RHG)J6S +JWF)22F +H1T)J6R +1JT)NB7 +T4V)Z34 +8NV)P3V +RLR)KZ7 +24G)KQJ +H7S)WRN +QC2)D8G +T7N)3KM +QVG)RX9 +Y94)XXN +MZ2)G54 +P46)MHZ +VKC)WMM +M8M)F5C +Q43)DLM +8S2)2B6 +8NG)QT4 +YRY)NMB +HCB)S93 +K3N)Z9G +2MM)KYH +H64)DQR +9TY)RZ7 +8SY)4SV +QWZ)W6P +Q39)4XQ +NKW)VL3 +HDF)B1K +NC3)QGY +645)VHG +CK3)M3J +MZS)7W1 +P5B)C85 +3VV)9LD +62K)ZQS +T7R)V5L +5YC)JTD +VD6)TQ9 +NB7)7Z8 +1SL)CWF +ZM9)Z31 +LMH)RWP +SQD)H64 +JXG)TH2 +5VN)J51 +F9T)4WH +LGD)2J5 +37P)47V +K2H)FD2 +82L)7Z1 +TYF)C22 +NTG)V3H +NB4)4DW +83C)53T +CNS)KM5 +FZT)XXJ +SD2)WPL +PC4)4WZ +CK3)P5Z +M82)TNR +F1V)PB9 +T1X)LX5 +8P1)V9H +1SL)K3N +V69)ZG2 +52F)YPX +1X8)NY1 +1CV)L2S +SG4)DZ4 +Y1X)PRC +RRJ)NTG +BDD)8M6 +V4J)2FB +LTM)84B +NMX)RDY +3CD)YMW +47V)YGN +JBH)DXW +36G)XQX +XF1)D8R +8M6)L2Q +YKC)5CK +92S)LBP +B3R)W31 +CLR)MMQ +WRN)QLT +2KG)FZQ +TL4)71R +7DQ)KDX +M3J)W6Q +S23)PC4 +2XM)Z78 +S1G)8YY +H7M)8P1 +SC9)SXT +1JM)XV9 +XN5)M69 +58B)ZM9 +9N6)YKC +4DW)ZLV +1D7)4YN +ZQ5)6RM +PRT)371 +PVX)WNN +VCK)CP4 +VH2)CZN +T1W)J32 +3V2)HCP +G2Y)TML +BN2)ZY3 +J75)PBS +LX5)DHB +9P9)KM3 +1CG)KG7 +NMT)72B +KZ7)YZC +82G)1Y9 +ZTM)8P3 +1TD)645 +1D3)LMH +W45)YXR +XB1)TFX +RTC)5N3 +W7C)2KG +GJB)92D +SMG)63B +TJV)P4Y +CB1)HN8 +PV8)V5P +PBS)7YW +GWK)9P9 +V3N)DX6 +TQ9)K4V +QT6)KXN +H58)1TD +YGN)ZTM +DY1)3N7 +HLB)SZL +LK7)TJV +NNW)LG3 +284)11J +RZD)84X +K1M)HG8 +RH4)MS8 +29Q)HNL +ML6)JQY +8NG)38H +Z31)HQM +M6P)B4S +FR2)B6Q +BCZ)MVV +9TY)BKD +Q3P)315 +76Q)XJL +V9N)ZNH +992)78T +P16)329 +CQB)H4N +984)SVB +V6K)SQD +LTQ)V8Q +7Z1)NSJ +C4R)ZZF +QSM)RC3 +LGC)GTH +SHH)4BH +PW3)HVJ +BG7)DCT +MB8)S23 +XJ9)C78 +P3V)GJB +CQ4)64Y +84B)8J3 +F97)DPQ +KYH)TYF +5KL)LVD +F5C)TRP +YK8)211 +Q8Z)NPK +TC7)65K +BR5)XFS +CP9)3B5 +RRK)Q8Z +W6Q)WW2 +5RH)Q43 +82P)ZKJ +211)96N +NXP)JY5 +CY3)C5W +WLB)1JD +X19)LDD +6PN)T7R +HXG)GP4 +PCW)82G +B5B)K4S +3QJ)694 +57J)7TT +KXS)GTP +GWM)NDV +BVX)3S8 +ZQS)RZD +77B)T9F +6GT)FFP +N37)TW1 +GNC)KRW +WC5)213 +GYV)FG9 +KKT)G9L +SSB)X2Y +SBR)2FC +LPQ)BB7 +84R)9MV +CVD)R26 +7YJ)SS3 +T1M)9TG +WBF)2T4 +Z8H)L93 +339)TNX +V5P)XTW +YYP)YTS +5N3)9MM +WR3)RFV +BR5)18Q +NC3)35Y +MS8)PHX +65K)9FR +HL5)MR3 +Z95)9X1 +QDH)SF4 +5WG)WLJ +TRT)1V3 +P29)Q3P +K64)CVX +5XB)KMV +V4J)YV5 +RR1)6FT +NDV)D1L +DD2)QT8 +CQB)XNH +DP1)YY8 +5CK)SC9 +LL4)RW9 +V5L)SMG +XJL)5XB +156)R6L +6QH)V69 +SS4)VR1 +VXJ)5KL +RXH)471 +T12)HZZ +YVF)6WP +JVF)S1B +FBQ)2RT +B1Z)GXH +C38)L96 +QX4)WG2 +TML)GDW +9FJ)RR1 +FD2)PVQ +KHL)28C +BM4)4J5 +QHT)SD2 +1PF)BDF +VJW)8GJ +ZY3)7RJ +7BN)13W +RW9)QV5 +QVG)1VY +BQZ)V9N +BB7)VWM +J51)NCL +KGL)W1F +RWP)VD6 +XXJ)6V2 +P6Q)WQT +P6N)Y8N +BKX)WJH +DRW)B7N +LX9)G7D +J3H)DRW +WXT)3V2 +JRV)K2H +PC3)DSV +PDR)KS1 +F7M)9N9 +LVD)6ZT +QX4)4YT +RJB)DSK +94Y)G3K +VW2)H5V +QT8)P5B +18Q)LGC +V9H)QT6 +GQL)CLR +NSN)CBT +LX9)S71 +KMV)NB4 +ZGD)51C +1SJ)6SN +KYH)WL3 +2N9)36G +KXV)WC5 +THQ)LX9 +77K)CQ4 +WW2)THJ +YZC)R9C +1V3)FZT +12H)NC3 +SK7)ZH7 +LJ7)JBH +BS8)ZQG +YHX)649 +Y5R)JH9 +RWY)2M8 +3YW)7W6 +X6L)6QH +K9D)V6S +K4S)33C +GMT)5CY +XWD)PQS +24H)WLB +CCL)Z12 +87W)5HS +2WV)YYP +1DH)8S2 +JCS)1NL +X4G)9T2 +JC7)XK9 +RFR)PCW +J6S)WR3 +RB2)GQL +SF4)TH3 +CVX)284 +JQY)R2P +ZCH)HF1 +6S4)NTW +WQT)RVP +FZQ)F1V +K92)DJC +H5V)8GF +DVP)CM5 +KM3)2KZ +YS3)LH7 +RVP)2WV +WLW)DVP +93V)M2R +QL1)CQB +N41)VRS +Z78)WLW +ZZG)JWF +NSJ)PDR +PVQ)C4R +CWF)MWD +DC5)4F8 +4WZ)56P +KMC)KZ6 +7QB)87W +HNR)TL4 +WLZ)CB1 +WJH)J2B +K6P)ZKM +L2L)H3G +2KZ)4M2 +B1K)KMC +984)XZ6 +D8G)5VN +4ZL)8Q8 +18J)V9J +7QT)6M5 +1JM)G2Y +P6Z)PDZ +WPL)24H +WY3)BGP +18Y)4V1 +C85)GYH +N5Q)HM2 +2LL)VGS +J3N)6RW +NTS)LL4 +4V1)L2L +FVY)KXS +1QQ)PC3 +2KZ)8NG +3KM)2DR +83B)T7N +SD2)V81 +SGB)93K +DZK)CVD +9WS)6S4 +7Z8)LBV +41Q)NSN +SCJ)ZRQ +Z29)QC2 +DX6)QLL +KST)CMK +MXR)5Z9 +Y9Z)8RY +45F)Y9Z +YY8)V3N +NCL)63Z +527)CP9 +WNN)RRK +DP1)MB8 +6V2)FC9 +9N9)7WG +6WP)V58 +WW2)C38 +DSK)3CD +N7R)KHX +2B6)QVG +BN1)8LC +4XQ)N5S +MMQ)H58 +41W)6PW +TX5)NMT +C4R)T1W +VHG)VJT +8ZM)WH1 +71Q)KTY +38H)NNW +J86)PBZ +8H2)4L4 +9MM)FKP +PVL)82L +LBP)3X1 +MTN)QL1 +67Q)FCK +P56)DZK +HG8)BG7 +GPN)YK4 +6N5)776 +Z25)NZY +GKK)37P +GVB)9YM +Y8N)Y94 +7MP)3T6 +3VV)PMM +5Z9)JN9 +RLK)7RB +G4T)HXR +BDM)B6P +NNT)NCW +9F8)6HN +33C)5YV +DG4)BN1 +3T6)VGM +RC3)KJ9 +7RB)1PF +3D7)PS1 +8RY)T35 +R2P)K92 +6HN)6PN +84M)MXR +MH3)YFJ +ZQ5)P56 +YXR)J3N +2QN)YDQ +QGY)NKW +DFT)C6Z +DD4)H8T +756)984 +15H)9WS +FVJ)P16 +127)48J +SQY)HLB +4J5)Y1X +V1X)Q9N +MMT)MZS +K84)RWY +THY)FH5 +776)VXM +276)YRY +DCT)2MM +2FB)PD8 +RFV)8X1 +2J5)T1M +76S)GQW +5K2)RNM +44V)GWM +XP8)ZXC +WC5)6GT +72B)7RL +5JV)FG8 +VQ3)GFT +QDJ)X19 +HC9)126 +D7B)PQ4 +Y4Z)ZMY +SVB)LKF +YQL)436 +VR1)18Y +35Y)VH2 +7W6)CNS +8GF)T92 +4MB)FR1 +JPK)9DF +6RW)H1T +LKF)G2K +4F8)8HT +DXW)BM4 +BS3)N82 +CP4)89K +339)Y9L +FG9)5WZ +JK9)3ZV +ZC1)8LW +8YY)CY3 +W18)WLZ +NZY)HD8 +35G)5RH +213)9C5 +DN6)G4T +FH5)WFN +H1B)Q4H +8J3)BDM +9FR)TDJ +GQW)M8M +SLN)VJX +1ZN)7XL +6ZT)HF9 +KJ9)2JV +7XL)X6L +LB4)Q39 +1RW)57L +DJS)YVF +4YN)SCJ +C1N)GKK +YK4)LK8 +7BK)83C +371)JK9 +6X3)PB5 +TVK)G5P +H51)FTZ +1GP)SNH +5LT)RBX +5XM)1TW +6SN)QHT +78X)5LT +4WH)N41 +DZ2)MJV +5YV)KXV +6YP)RZ4 +H4N)QX4 +S1B)V1X +HXR)97J +DLM)B3R +VRS)3P6 +Z19)FR2 +B6Q)2QN +5XM)XY5 +TJV)CCL +BXC)J1L +89P)Q6W +J3N)RLK +X4Z)F9T +ZNM)18J +15S)M41 +ZZF)XP8 +2N1)M6P +ZNH)W2N +3HQ)F26 +R9C)SSB +M6Q)WBF +P5Z)6N5 +WW6)YHX +KQJ)G15 +DJC)4NG +ZY8)9N6 +HVJ)Q9G +DVN)B1Z +PS1)JZV +6PW)CVW +LPH)Z19 +6KF)K1M +QT4)94Y +1GM)3CS +GFT)PCP +6PW)X9L +4NG)8H2 +KN5)VXY +WP9)84R +VJT)Y4Z +7RJ)99P +KZ7)BD5 +K39)ZNX +RZ4)VF4 +6CP)K64 +RQP)Z3F +JTD)T1X +XNH)Z6V +TH3)RKK +DXC)RW1 +1JD)T4V +1FX)15S +63Z)JPK +QKV)6JH +Z3P)SAN +G15)4V7 +6XM)P62 +TNW)N37 +QM4)G1T +YV5)3HQ +VQT)4SG +SS3)R12 +K1M)WP9 +S71)7LJ +7JY)2SB +JZV)7QV +BVX)D56 +RXH)LK7 +SF1)8JV +ZNX)YSY +SWP)QQ7 +89Y)78X +6FT)YBY +VJX)YK8 +M2R)TWF +V3H)2LL +4J5)DP1 +XFS)Z25 +Z3F)DVN +KTY)2XG +1VK)ZQ5 +4L4)KR3 +XY5)BDP +TNR)43S +1BX)DXZ +HF1)8SY +8P3)HL5 +LL4)KST +DSV)6XM +2FC)3RK +Y27)RLR +HF9)JRV +6RM)HZ9 +G2K)SWP +ZQG)XWD +1TW)46P +YTS)YOU +636)KP2 +MXR)MTN +T92)F9H +XB3)1GQ +8HT)T28 +9YM)Y27 +8Q8)JRY +R6L)TT3 +QPY)JVF +D6Q)X5Q +LDD)45F +636)RTC +X9L)B5B +B7B)7QB +CMK)276 +7YW)P6Q +WG2)8ZM +WFN)LYB +Z12)FWP +276)992 +5DK)15H +WL3)4FV +G3K)9WW +X2Y)LB4 +J4H)L8G +WH1)M82 +JH9)JXG +7QB)2H1 +3RK)1GP +L2S)7MP +JVC)ZNM +LZ8)DH9 +B6Z)SF1 +RHM)T1L +LYB)2N1 +D8R)7YJ +K8Q)24G +DXZ)156 +BDM)4TR +L96)PVX +RLC)BXC +BDF)58B +GTH)DXC +W6P)ZY8 +XCW)K6P +Q4H)VJW +56P)WY3 +2RT)VQV +1KX)Q9T +78T)FVY +X6C)G5Q +HWL)4M5 +W31)4V3 +BD5)GNC +LZ8)KCC +M41)3D7 +P6G)BN2 +DHB)DJS +G9L)964 +T1G)TBH +471)RS6 +VL3)LTM +V7D)1D7 +N5N)XN5 +MDZ)GJZ +86H)FWL +315)NG1 +6FT)Q8S +5PD)F97 +HD8)T1F +NPK)1JT +KZ6)CY8 +YMW)TVK +PBZ)DC5 +RS6)GLC +PCP)6YP +KM5)B7B +8LW)BR5 +9T2)Z3P +Q8S)5YC +VGR)W45 +YZC)9FJ +L93)83B +TYX)5PH +J32)K8Q +QC2)QM4 +RZD)BDD +G5Q)SK7 +THB)5WG +FR1)QSM +NDV)57J +DQR)1D3 +YBY)9YW +XMQ)BQZ +B4S)82P +3S8)LJ7 +XHZ)H51 +JRY)TX5 +7WG)77K +4DR)B6T +3ZV)J86 +9YW)VKC +1GQ)NZ7 +RS4)5DK +CM5)1CG +VXM)J12 +VZS)GPN +G7D)GYV +S9Y)RXH +R2Q)QKV +ZM9)9RZ +GJB)Z95 +G5P)X6C +D4W)47X +4YT)1FX +CVW)1WV +ZJZ)T71 +R26)12H +4M2)L21 +MRG)7G4 +HNJ)VW2 +3B5)RJB +H3G)XMQ +G1T)7BK +PW7)65J +ZD2)3RP +XXN)84W +FWP)KN5 +5BK)GCC +V2V)7FC +VGM)SL6 +NK6)7BN +SQQ)YQL +FKP)1VK +47V)6ZH +J1L)RB2 +J4F)5JV +LG3)527 +MS8)TN8 +JTH)THQ +DXW)QDH +TRP)461 +5LW)N7R +RTN)HNJ +97J)SLN +L8G)FVJ +F9H)5PD +HN8)518 +51C)1QQ +PHX)P6G +63B)2N9 +Q6W)THB +J6R)H7M +K6X)JTH +46P)83D +13W)VZS +RWP)W4D +Y9L)BNG +9WW)KYT +HZ9)89Z +J2B)636 +RNM)7QT +PCP)T6S +NXP)9ZM +V9S)RG5 +7W6)41Q +7MP)WS5 +CBT)GLM +6JH)VK2 +2S6)XF1 +SY2)V2S +7W1)19P +V8Q)BVX +TW1)KHL +28J)NJ2 +PB5)Q4T +3CS)KGL +VK2)79P +W4D)4PK +GCC)XJ9 +NCG)MQM +V58)H7S +1NL)BS8 +GTP)ZJZ +Q9G)ZZG +3YX)Z29 +PQS)6XK +8LC)84M +ZH7)PRT +KWK)HCB +18Q)Z8H +4BH)76Q +QV5)T12 +G4T)P6N +TWF)RFR +8JV)GTZ +LBV)RWW +C6Z)1SL +9C5)MFN +QSW)7DQ +PD8)D4W +RLR)KRK +PDZ)76S +Z9G)8NV +WLJ)VXQ +96N)GWK +345)4ZH +NR2)HNR +P4Y)CK3 +D1L)J4F +JY5)NNT +9TG)28J +HCP)44V +BNG)X4Z +8GJ)4JL +329)J75 +5WZ)L62 +Q8S)MMT +PRC)3YX +KCC)29Q +GLM)26P +KR3)R2Q +1QV)J4H +8G3)XB1 +S6R)DG4 +CZN)8G6 +5CY)GQ5 +V2S)1PV +4V1)LPQ +N5S)H1B +3RP)1RW +4PK)NCG +COM)V9S +3HQ)8QC +9RZ)NMX +BKD)RRJ +GP4)XTN +28C)JC7 +4M5)DY1 +L21)9ND +QM4)7JY +RKK)HC9 +9HZ)PY5 +2JV)ZYP +84W)6X3 +S93)RS4 +P62)K6X +53T)5VM +KP2)B6Z +R12)JVC +2XG)ML6 +26P)XNR +GWM)4DR +GDW)F7M +DQR)P29 +89K)RHG diff --git a/06/src/main.zig b/06/src/main.zig new file mode 100644 index 0000000..029737e --- /dev/null +++ b/06/src/main.zig @@ -0,0 +1,102 @@ +const std = @import("std"); + +const Link = struct { + a: [3]u8 = [3]u8{ 0, 0, 0 }, + b: [3]u8 = [3]u8{ 0, 0, 0 }, +}; + +const Node = struct { + name: [3]u8 = [3]u8{ 0, 0, 0 }, + depth: u32 = 0, + parent: ?*Node, +}; + +const Links = std.ArrayList(Link); +const Nodes = std.StringHashMap(*Node); + +fn parse(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) !Links { + var list: Links = Links.init(alloc); + var buf: [8]u8 = undefined; + var i: u32 = 0; + + while (try stream.readUntilDelimiterOrEof(&buf, '\n')) |line| { + std.debug.assert(line.len == 7 and line[3] == ')'); + std.debug.warn("{}\n", line); + + var out: Link = Link{}; + std.mem.copy(u8, &out.a, line[0..3]); + std.mem.copy(u8, &out.b, line[4..7]); + + try list.append(out); + } + + return list; +} + +fn getOrCreateNode(alloc: *std.mem.Allocator, nodes: var, name: [3]u8) !*Node { + if (nodes.get(name)) |kv| { + return kv.value; + } else { + var node: *Node = try alloc.create(Node); + node.parent = null; + node.depth = 0; + + std.mem.copy(u8, &node.name, name); + + var kv = try nodes.put(name, node); + return node; + } +} + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + + const alloc = &arena.allocator; + const file = std.io.getStdIn(); + const stream = &file.inStream().stream; + + var links = try parse(alloc, stream); + + std.debug.warn("Part 1: {} links\n", links.len); + + // name -> node + var nodes = Nodes.init(alloc); + + // The input isn't ordered, so we need to pass over it several times + + // Pass 1: create all nodes + for (links.toSlice()) |link| { + var a = try getOrCreateNode(alloc, &nodes, link.a); + var b = try getOrCreateNode(alloc, &nodes, link.b); + } + + // Pass 2: link all nodes to their parents + for (links.toSlice()) |link| { + var a = try getOrCreateNode(alloc, &nodes, link.a); + var b = try getOrCreateNode(alloc, &nodes, link.b); + + std.debug.warn("\t{} ) {}\n", a.name, b.name); + + std.debug.assert(b.parent == null); + b.parent = a; + } + + // Pass 3: The tree is fully constructed, so we can count parents + var count: u32 = 0; + var iter = nodes.iterator(); + while (iter.next()) |kv| { + var node = kv.value; + + // Count number of orbits + var n: *Node = node; + while (n.parent) |p| { + node.depth += 1; + n = p; + } + + count += node.depth; + } + + std.debug.warn("Part 1: {}\n", count); +} From ea8f7914f9d5ca010e8130288dc627c02848078f Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 6 Dec 2019 20:46:40 +0000 Subject: [PATCH 21/32] Day 6.2 --- 06/src/main.zig | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/06/src/main.zig b/06/src/main.zig index 029737e..6e7b753 100644 --- a/06/src/main.zig +++ b/06/src/main.zig @@ -12,6 +12,7 @@ const Node = struct { }; const Links = std.ArrayList(Link); +const NodeList = std.ArrayList(*Node); const Nodes = std.StringHashMap(*Node); fn parse(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) !Links { @@ -21,7 +22,6 @@ fn parse(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) !Links while (try stream.readUntilDelimiterOrEof(&buf, '\n')) |line| { std.debug.assert(line.len == 7 and line[3] == ')'); - std.debug.warn("{}\n", line); var out: Link = Link{}; std.mem.copy(u8, &out.a, line[0..3]); @@ -48,6 +48,22 @@ fn getOrCreateNode(alloc: *std.mem.Allocator, nodes: var, name: [3]u8) !*Node { } } +fn getParents(alloc: *std.mem.Allocator, node: *Node) !NodeList { + var out = NodeList.init(alloc); + var n: *Node = node; + while (n.parent) |p| { + try out.append(p); + n = p; + } + + return out; +} + +// Assumes n1 is a parent of n2 +fn distance(n1: *Node, n2: *Node) u32 { + return n2.depth - n1.depth - 1; +} + pub fn main() anyerror!void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); @@ -58,8 +74,6 @@ pub fn main() anyerror!void { var links = try parse(alloc, stream); - std.debug.warn("Part 1: {} links\n", links.len); - // name -> node var nodes = Nodes.init(alloc); @@ -76,8 +90,6 @@ pub fn main() anyerror!void { var a = try getOrCreateNode(alloc, &nodes, link.a); var b = try getOrCreateNode(alloc, &nodes, link.b); - std.debug.warn("\t{} ) {}\n", a.name, b.name); - std.debug.assert(b.parent == null); b.parent = a; } @@ -99,4 +111,28 @@ pub fn main() anyerror!void { } std.debug.warn("Part 1: {}\n", count); + + // We need to find the node that both you and santa have in common + + var you = (nodes.get("YOU") orelse unreachable).value; + var san = (nodes.get("SAN") orelse unreachable).value; + + var yP = try getParents(alloc, you); + var sP = try getParents(alloc, san); + + var inCommon = NodeList.init(alloc); + + for (yP.toSlice()) |p1| { + for (sP.toSlice()) |p2| { + if (p1 == p2) try inCommon.append(p1); + } + } + + std.debug.warn("Part 2: you have {} parents, santa has {}, {} in common\n", yP.count(), sP.count(), inCommon.count()); + + for (inCommon.toSlice()) |p| { + const d1 = distance(p, you); + const d2 = distance(p, san); + std.debug.warn("\t{} - ({}) {} ({}) - {}: {}\n", you.name, d1, p.name, d2, san.name, d1 + d2); + } } From 4f614c7727016a9328b0558ed9f0387ca96daf35 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sat, 7 Dec 2019 17:31:23 +0000 Subject: [PATCH 22/32] Day 7.1 --- 07/build.zig | 15 ++++ 07/input | 1 + 07/src/main.zig | 178 ++++++++++++++++++++++++++++++++++++++++ lib/intcode/intcode.zig | 7 +- run-intcodes | 1 + 5 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 07/build.zig create mode 100644 07/input create mode 100644 07/src/main.zig diff --git a/07/build.zig b/07/build.zig new file mode 100644 index 0000000..16cb95e --- /dev/null +++ b/07/build.zig @@ -0,0 +1,15 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("07", "src/main.zig"); + exe.addPackagePath("intcode", "../lib/intcode/intcode.zig"); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/07/input b/07/input new file mode 100644 index 0000000..5828532 --- /dev/null +++ b/07/input @@ -0,0 +1 @@ +3,8,1001,8,10,8,105,1,0,0,21,34,55,68,85,106,187,268,349,430,99999,3,9,1001,9,5,9,1002,9,5,9,4,9,99,3,9,1002,9,2,9,1001,9,2,9,1002,9,5,9,1001,9,2,9,4,9,99,3,9,101,3,9,9,102,3,9,9,4,9,99,3,9,1002,9,5,9,101,3,9,9,102,5,9,9,4,9,99,3,9,1002,9,4,9,1001,9,2,9,102,3,9,9,101,3,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,99 diff --git a/07/src/main.zig b/07/src/main.zig new file mode 100644 index 0000000..630266d --- /dev/null +++ b/07/src/main.zig @@ -0,0 +1,178 @@ +const std = @import("std"); + +const intcode = @import("intcode"); + +// TODO: it would be awesome if we could make this a comptime function +const permutations = [120][5]i32{ + .{ 0, 1, 2, 3, 4 }, + .{ 0, 1, 2, 4, 3 }, + .{ 0, 1, 3, 2, 4 }, + .{ 0, 1, 3, 4, 2 }, + .{ 0, 1, 4, 2, 3 }, + .{ 0, 1, 4, 3, 2 }, + .{ 0, 2, 1, 3, 4 }, + .{ 0, 2, 1, 4, 3 }, + .{ 0, 2, 3, 1, 4 }, + .{ 0, 2, 3, 4, 1 }, + .{ 0, 2, 4, 1, 3 }, + .{ 0, 2, 4, 3, 1 }, + .{ 0, 3, 1, 2, 4 }, + .{ 0, 3, 1, 4, 2 }, + .{ 0, 3, 2, 1, 4 }, + .{ 0, 3, 2, 4, 1 }, + .{ 0, 3, 4, 1, 2 }, + .{ 0, 3, 4, 2, 1 }, + .{ 0, 4, 1, 2, 3 }, + .{ 0, 4, 1, 3, 2 }, + .{ 0, 4, 2, 1, 3 }, + .{ 0, 4, 2, 3, 1 }, + .{ 0, 4, 3, 1, 2 }, + .{ 0, 4, 3, 2, 1 }, + .{ 1, 0, 2, 3, 4 }, + .{ 1, 0, 2, 4, 3 }, + .{ 1, 0, 3, 2, 4 }, + .{ 1, 0, 3, 4, 2 }, + .{ 1, 0, 4, 2, 3 }, + .{ 1, 0, 4, 3, 2 }, + .{ 1, 2, 0, 3, 4 }, + .{ 1, 2, 0, 4, 3 }, + .{ 1, 2, 3, 0, 4 }, + .{ 1, 2, 3, 4, 0 }, + .{ 1, 2, 4, 0, 3 }, + .{ 1, 2, 4, 3, 0 }, + .{ 1, 3, 0, 2, 4 }, + .{ 1, 3, 0, 4, 2 }, + .{ 1, 3, 2, 0, 4 }, + .{ 1, 3, 2, 4, 0 }, + .{ 1, 3, 4, 0, 2 }, + .{ 1, 3, 4, 2, 0 }, + .{ 1, 4, 0, 2, 3 }, + .{ 1, 4, 0, 3, 2 }, + .{ 1, 4, 2, 0, 3 }, + .{ 1, 4, 2, 3, 0 }, + .{ 1, 4, 3, 0, 2 }, + .{ 1, 4, 3, 2, 0 }, + .{ 2, 0, 1, 3, 4 }, + .{ 2, 0, 1, 4, 3 }, + .{ 2, 0, 3, 1, 4 }, + .{ 2, 0, 3, 4, 1 }, + .{ 2, 0, 4, 1, 3 }, + .{ 2, 0, 4, 3, 1 }, + .{ 2, 1, 0, 3, 4 }, + .{ 2, 1, 0, 4, 3 }, + .{ 2, 1, 3, 0, 4 }, + .{ 2, 1, 3, 4, 0 }, + .{ 2, 1, 4, 0, 3 }, + .{ 2, 1, 4, 3, 0 }, + .{ 2, 3, 0, 1, 4 }, + .{ 2, 3, 0, 4, 1 }, + .{ 2, 3, 1, 0, 4 }, + .{ 2, 3, 1, 4, 0 }, + .{ 2, 3, 4, 0, 1 }, + .{ 2, 3, 4, 1, 0 }, + .{ 2, 4, 0, 1, 3 }, + .{ 2, 4, 0, 3, 1 }, + .{ 2, 4, 1, 0, 3 }, + .{ 2, 4, 1, 3, 0 }, + .{ 2, 4, 3, 0, 1 }, + .{ 2, 4, 3, 1, 0 }, + .{ 3, 0, 1, 2, 4 }, + .{ 3, 0, 1, 4, 2 }, + .{ 3, 0, 2, 1, 4 }, + .{ 3, 0, 2, 4, 1 }, + .{ 3, 0, 4, 1, 2 }, + .{ 3, 0, 4, 2, 1 }, + .{ 3, 1, 0, 2, 4 }, + .{ 3, 1, 0, 4, 2 }, + .{ 3, 1, 2, 0, 4 }, + .{ 3, 1, 2, 4, 0 }, + .{ 3, 1, 4, 0, 2 }, + .{ 3, 1, 4, 2, 0 }, + .{ 3, 2, 0, 1, 4 }, + .{ 3, 2, 0, 4, 1 }, + .{ 3, 2, 1, 0, 4 }, + .{ 3, 2, 1, 4, 0 }, + .{ 3, 2, 4, 0, 1 }, + .{ 3, 2, 4, 1, 0 }, + .{ 3, 4, 0, 1, 2 }, + .{ 3, 4, 0, 2, 1 }, + .{ 3, 4, 1, 0, 2 }, + .{ 3, 4, 1, 2, 0 }, + .{ 3, 4, 2, 0, 1 }, + .{ 3, 4, 2, 1, 0 }, + .{ 4, 0, 1, 2, 3 }, + .{ 4, 0, 1, 3, 2 }, + .{ 4, 0, 2, 1, 3 }, + .{ 4, 0, 2, 3, 1 }, + .{ 4, 0, 3, 1, 2 }, + .{ 4, 0, 3, 2, 1 }, + .{ 4, 1, 0, 2, 3 }, + .{ 4, 1, 0, 3, 2 }, + .{ 4, 1, 2, 0, 3 }, + .{ 4, 1, 2, 3, 0 }, + .{ 4, 1, 3, 0, 2 }, + .{ 4, 1, 3, 2, 0 }, + .{ 4, 2, 0, 1, 3 }, + .{ 4, 2, 0, 3, 1 }, + .{ 4, 2, 1, 0, 3 }, + .{ 4, 2, 1, 3, 0 }, + .{ 4, 2, 3, 0, 1 }, + .{ 4, 2, 3, 1, 0 }, + .{ 4, 3, 0, 1, 2 }, + .{ 4, 3, 0, 2, 1 }, + .{ 4, 3, 1, 0, 2 }, + .{ 4, 3, 1, 2, 0 }, + .{ 4, 3, 2, 0, 1 }, + .{ 4, 3, 2, 1, 0 }, +}; + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + + const alloc = &arena.allocator; + var program = try intcode.loadFromStdIn(alloc); + + // 5 intcode computers act as the amps + var machines: [5]intcode.Machine = undefined; + + // 120 phase permutations. Find the highest. + var max: i32 = 0; + for (permutations) |inputs| { + for (machines) |*machine| { + var copy = try alloc.alloc(i32, program.len); + std.mem.copy(i32, copy, program); + + machine.* = try intcode.Machine.init(alloc, copy); + } + + // Phase input + for (inputs) |input, i| { + try machines[i].input.append(input); + } + + // amplifier input + for (machines) |*machine, i| { + var ampInput: i32 = 0; + if (i > 0) { + try machine.input.append(machines[i - 1].output.at(0)); + } else { + try machine.input.append(0); + } + + try machine.run(); + } + + const final = machines[4].output.at(0); + if (final > max) + max = final; + + // Don't forget to free everything! + for (machines) |*machine, i| { + alloc.free(machine.memory); + machine.deinit(); + } + } + + std.debug.warn("Part 1: {}\n", max); +} diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 039fc20..9897b71 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -13,7 +13,7 @@ pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.S var trimmed = std.mem.trimRight(u8, num, "\r\n"); program[i] = try std.fmt.parseInt(i32, trimmed, 10); - std.debug.warn("{},", program[i]); + // std.debug.warn("{},", program[i]); i += 1; } @@ -118,6 +118,11 @@ pub const Machine = struct { while (try self.step()) {} } + pub fn deinit(self: *Machine) void { + self.input.deinit(); + self.output.deinit(); + } + /// Read an immediate or position value from memory. Parameter determines /// which field following the current instruction to read from inline fn __read(self: *Machine, parameter: usize, mode: Mode) i32 { diff --git a/run-intcodes b/run-intcodes index dcf2052..0b27af2 100755 --- a/run-intcodes +++ b/run-intcodes @@ -2,3 +2,4 @@ zig test lib/intcode/intcode.zig zig build --build-file 02/build.zig run < 02/input zig build --build-file 05/build.zig run < 05/input +zig build --build-file 07/build.zig run < 07/input From 325ec9d5911c8180a7f074bb415b3055da092d94 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sat, 7 Dec 2019 18:35:03 +0000 Subject: [PATCH 23/32] Switch to using a queue for character devices --- 02/src/main.zig | 8 ++---- 05/src/main.zig | 19 +++++++------ 07/src/main.zig | 19 ++++++------- lib/intcode/intcode.zig | 62 +++++++++++++++++++++++++++++++++-------- run-intcodes | 8 +++--- 5 files changed, 77 insertions(+), 39 deletions(-) diff --git a/02/src/main.zig b/02/src/main.zig index 94ee58d..412f1b4 100644 --- a/02/src/main.zig +++ b/02/src/main.zig @@ -28,7 +28,7 @@ pub fn main() anyerror!void { var program = try intcode.loadFromStdIn(alloc); // Part 1 - std.debug.warn("Part 1: {}\n", try runCopy(alloc, program, 12, 2)); + std.debug.warn("Day 2, Part 1: {}\n", try runCopy(alloc, program, 12, 2)); // Part 2: 100*100 = 10,000 combinations to try. var memory: []i32 = try alloc.alloc(i32, program.len); @@ -36,14 +36,14 @@ pub fn main() anyerror!void { var noun: i32 = 0; var verb: i32 = 0; - std.debug.warn("Part 2: Searching..."); + std.debug.warn("Day 2, Part 2: "); while (!done) { std.mem.copy(i32, memory, program); const result = try run(alloc, memory, noun, verb); // Too high: 250800 (noun=33, verb=76) if (result == 19690720) { - std.debug.warn("OK! noun={} verb={}\n", noun, verb); + std.debug.warn("noun={} verb={}\n", noun, verb); done = true; } @@ -54,8 +54,6 @@ pub fn main() anyerror!void { if (verb > 100) { std.debug.warn("failed!\n"); - } else { - std.debug.warn("."); } } } diff --git a/05/src/main.zig b/05/src/main.zig index dee0a3a..18353e7 100644 --- a/05/src/main.zig +++ b/05/src/main.zig @@ -14,19 +14,20 @@ pub fn main() anyerror!void { var m1 = try intcode.Machine.init(alloc, p1); var m2 = try intcode.Machine.init(alloc, p2); - std.debug.warn("Part 1\n"); - try m1.input.append(1); // Air conditioner unit + try m1.writeToInput(1); // Air conditioner unit try m1.run(); - for (m1.output.toSlice()) |value, idx| { - std.debug.warn("Test {}: {}\n", idx, value); + var out: i32 = 0; + while (m1.readFromOutput(false)) |item| { + out = item; + } else |err| { + std.debug.assert(err == std.os.ReadError.WouldBlock); } - std.debug.warn("\nPart 2\n"); - try m2.input.append(5); // Thermal radiator controller + std.debug.warn("Day 5, Part 1: {}\n", out); + + try m2.writeToInput(5); // Thermal radiator controller try m2.run(); - for (m2.output.toSlice()) |value, idx| { - std.debug.warn("Test {}: {}\n", idx, value); - } + std.debug.warn("Day 5, Part 2: {}\n", try m2.readFromOutput(false)); } diff --git a/07/src/main.zig b/07/src/main.zig index 630266d..a3ef2cb 100644 --- a/07/src/main.zig +++ b/07/src/main.zig @@ -3,7 +3,7 @@ const std = @import("std"); const intcode = @import("intcode"); // TODO: it would be awesome if we could make this a comptime function -const permutations = [120][5]i32{ +const perm1 = [120][5]i32{ .{ 0, 1, 2, 3, 4 }, .{ 0, 1, 2, 4, 3 }, .{ 0, 1, 3, 2, 4 }, @@ -138,7 +138,7 @@ pub fn main() anyerror!void { // 120 phase permutations. Find the highest. var max: i32 = 0; - for (permutations) |inputs| { + for (perm1) |inputs| { for (machines) |*machine| { var copy = try alloc.alloc(i32, program.len); std.mem.copy(i32, copy, program); @@ -148,22 +148,19 @@ pub fn main() anyerror!void { // Phase input for (inputs) |input, i| { - try machines[i].input.append(input); + try machines[i].writeToInput(input); } // amplifier input for (machines) |*machine, i| { var ampInput: i32 = 0; - if (i > 0) { - try machine.input.append(machines[i - 1].output.at(0)); - } else { - try machine.input.append(0); - } + if (i > 0) ampInput = try machines[i - 1].readFromOutput(false); + try machine.writeToInput(ampInput); try machine.run(); } - const final = machines[4].output.at(0); + const final = try machines[4].readFromOutput(false); if (final > max) max = final; @@ -174,5 +171,7 @@ pub fn main() anyerror!void { } } - std.debug.warn("Part 1: {}\n", max); + std.debug.warn("Day 7, Part 1: {}\n", max); + + // In part 2, the machines need to be wired into a feedback loop } diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 9897b71..2a795eb 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const CharDev = std.ArrayList(i32); -const CharDevLimit = 32; +const CharDev = std.atomic.Queue(i32); pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 { var program = try alloc.alloc(i32, 1024); @@ -91,6 +90,8 @@ const Instruction = struct { }; pub const Machine = struct { + alloc: *std.mem.Allocator, + memory: []i32, ip: usize = 0, @@ -108,9 +109,10 @@ pub const Machine = struct { pub fn init(alloc: *std.mem.Allocator, program: []i32) anyerror!Machine { return Machine{ + .alloc = alloc, .memory = program, - .input = try CharDev.initCapacity(alloc, CharDevLimit), - .output = try CharDev.initCapacity(alloc, CharDevLimit), + .input = CharDev.init(), + .output = CharDev.init(), }; } @@ -119,8 +121,47 @@ pub const Machine = struct { } pub fn deinit(self: *Machine) void { - self.input.deinit(); - self.output.deinit(); + // TODO + } + + pub fn readFromInput(self: *Machine, blocking: bool) !i32 { + return self.__in(&self.input, blocking); + } + + pub fn writeToInput(self: *Machine, val: i32) !void { + return self.__out(&self.input, val); + } + + pub fn readFromOutput(self: *Machine, blocking: bool) !i32 { + return self.__in(&self.output, blocking); + } + + pub fn writeToOutput(self: *Machine, val: i32) !void { + return self.__out(&self.output, val); + } + + inline fn __in(self: *Machine, dev: *CharDev, blocking: bool) !i32 { + var node = dev.get(); + + if (node == null) { + if (!blocking) return std.os.ReadError.WouldBlock; + // Just busy-wait for now + while (node == null) node = dev.get(); + } + + if (node) |n| { + defer self.alloc.destroy(n); + return n.data; + } + + unreachable; + } + + inline fn __out(self: *Machine, dev: *CharDev, val: i32) !void { + var node = try self.alloc.create(CharDev.Node); + node.data = val; + + dev.put(node); } /// Read an immediate or position value from memory. Parameter determines @@ -159,11 +200,11 @@ pub const Machine = struct { }, .IN => { - self.__write(0, self.input.orderedRemove(0)); + self.__write(0, try self.readFromInput(true)); // blocking read }, .OUT => { - try self.output.append(self.__read(0, insn.modes[0])); + try self.writeToOutput(self.__read(0, insn.modes[0])); }, .JNZ => { @@ -256,12 +297,11 @@ test "day 5 example 1" { var after: [5]i32 = .{ 666, 0, 4, 0, 99 }; var machine = try Machine.init(test_allocator, before[0..before.len]); - try machine.input.append(666); + try machine.writeToInput(666); try machine.run(); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); - assert(machine.output.len == 1); - assert(machine.output.at(0) == 666); + assert(666 == try machine.readFromOutput(false)); } test "Instruction#decode ADD" { diff --git a/run-intcodes b/run-intcodes index 0b27af2..ac04d79 100755 --- a/run-intcodes +++ b/run-intcodes @@ -1,5 +1,5 @@ #!/bin/sh -zig test lib/intcode/intcode.zig -zig build --build-file 02/build.zig run < 02/input -zig build --build-file 05/build.zig run < 05/input -zig build --build-file 07/build.zig run < 07/input +zig test lib/intcode/intcode.zig && + zig build --build-file 02/build.zig run < 02/input && + zig build --build-file 05/build.zig run < 05/input && + zig build --build-file 07/build.zig run < 07/input From ea094368e7d775d136109a2b2aec71c32f57c229 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sat, 7 Dec 2019 21:26:59 +0000 Subject: [PATCH 24/32] Switch to using OS pipes --- 05/src/main.zig | 8 ++---- 07/src/main.zig | 58 ++++++++++++++++++++++++++++++++--------- lib/intcode/intcode.zig | 55 ++++++++++++++++++-------------------- 3 files changed, 73 insertions(+), 48 deletions(-) diff --git a/05/src/main.zig b/05/src/main.zig index 18353e7..33b581c 100644 --- a/05/src/main.zig +++ b/05/src/main.zig @@ -18,16 +18,12 @@ pub fn main() anyerror!void { try m1.run(); var out: i32 = 0; - while (m1.readFromOutput(false)) |item| { - out = item; - } else |err| { - std.debug.assert(err == std.os.ReadError.WouldBlock); - } + while (out == 0) : (out = try m1.readFromOutput()) {} std.debug.warn("Day 5, Part 1: {}\n", out); try m2.writeToInput(5); // Thermal radiator controller try m2.run(); - std.debug.warn("Day 5, Part 2: {}\n", try m2.readFromOutput(false)); + std.debug.warn("Day 5, Part 2: {}\n", try m2.readFromOutput()); } diff --git a/07/src/main.zig b/07/src/main.zig index a3ef2cb..b71a8d5 100644 --- a/07/src/main.zig +++ b/07/src/main.zig @@ -136,42 +136,74 @@ pub fn main() anyerror!void { // 5 intcode computers act as the amps var machines: [5]intcode.Machine = undefined; + // Allocate memory once only. + for (machines) |*machine| { + machine.alloc = alloc; + machine.memory = try alloc.alloc(i32, program.len); + } + + // Now wire up the machines correctly. The output of each machine should be + // the input to the next. + const pipes: [6]intcode.CharDev = .{ + try std.os.pipe(), + try std.os.pipe(), + try std.os.pipe(), + try std.os.pipe(), + try std.os.pipe(), + try std.os.pipe(), + }; + + machines[0].input = pipes[0]; + machines[0].output = pipes[1]; + + machines[1].input = machines[0].output; + machines[1].output = pipes[2]; + + machines[2].input = machines[1].output; + machines[2].output = pipes[3]; + + machines[3].input = machines[2].output; + machines[3].output = pipes[4]; + + machines[4].input = machines[3].output; + machines[4].output = pipes[5]; + // 120 phase permutations. Find the highest. var max: i32 = 0; for (perm1) |inputs| { for (machines) |*machine| { - var copy = try alloc.alloc(i32, program.len); - std.mem.copy(i32, copy, program); - - machine.* = try intcode.Machine.init(alloc, copy); + std.mem.copy(i32, machine.memory, program); + machine.ip = 0; } - // Phase input + // Phase inputs for (inputs) |input, i| { try machines[i].writeToInput(input); } - // amplifier input - for (machines) |*machine, i| { - var ampInput: i32 = 0; - if (i > 0) ampInput = try machines[i - 1].readFromOutput(false); + // Provide starting value of 0 + try machines[0].writeToInput(0); - try machine.writeToInput(ampInput); + // run the program + for (machines) |*machine, i| { try machine.run(); } - const final = try machines[4].readFromOutput(false); + const final = try machines[4].readFromOutput(); if (final > max) max = final; // Don't forget to free everything! for (machines) |*machine, i| { alloc.free(machine.memory); - machine.deinit(); } } std.debug.warn("Day 7, Part 1: {}\n", max); - // In part 2, the machines need to be wired into a feedback loop + // In part 2, the machines need to be wired into a feedback loop. + // To do this, drop pipe 6 and replace it with pipe 0 + std.os.close(pipes[5][0]); + std.os.close(pipes[5][1]); + machines[4].output = machines[0].input; } diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 2a795eb..471ec41 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -1,6 +1,7 @@ const std = @import("std"); -const CharDev = std.atomic.Queue(i32); +// We're using pipes as character devices +pub const CharDev = [2]i32; pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 { var program = try alloc.alloc(i32, 1024); @@ -111,8 +112,8 @@ pub const Machine = struct { return Machine{ .alloc = alloc, .memory = program, - .input = CharDev.init(), - .output = CharDev.init(), + .input = try std.os.pipe(), + .output = try std.os.pipe(), }; } @@ -121,47 +122,43 @@ pub const Machine = struct { } pub fn deinit(self: *Machine) void { - // TODO + std.os.close(self.input[0]); + std.os.close(self.input[1]); + std.os.close(self.output[0]); + std.os.close(self.output[1]); } - pub fn readFromInput(self: *Machine, blocking: bool) !i32 { - return self.__in(&self.input, blocking); + pub fn readFromInput(self: *Machine) !i32 { + return self.__in(self.input); } pub fn writeToInput(self: *Machine, val: i32) !void { - return self.__out(&self.input, val); + return self.__out(self.input, val); } - pub fn readFromOutput(self: *Machine, blocking: bool) !i32 { - return self.__in(&self.output, blocking); + pub fn readFromOutput(self: *Machine) !i32 { + return self.__in(self.output); } pub fn writeToOutput(self: *Machine, val: i32) !void { - return self.__out(&self.output, val); + return self.__out(self.output, val); } - inline fn __in(self: *Machine, dev: *CharDev, blocking: bool) !i32 { - var node = dev.get(); + inline fn __in(self: *Machine, dev: CharDev) !i32 { + const fd = dev[0]; // Read from the pipe + var store: [4]u8 = undefined; - if (node == null) { - if (!blocking) return std.os.ReadError.WouldBlock; - // Just busy-wait for now - while (node == null) node = dev.get(); - } + var n = try std.os.read(fd, &store); + std.debug.assert(n == 4); // TODO: handle partial reads - if (node) |n| { - defer self.alloc.destroy(n); - return n.data; - } - - unreachable; + return std.mem.readIntNative(i32, &store); } - inline fn __out(self: *Machine, dev: *CharDev, val: i32) !void { - var node = try self.alloc.create(CharDev.Node); - node.data = val; + inline fn __out(self: *Machine, dev: CharDev, val: i32) !void { + const fd = dev[1]; // Write to the pipe + const bytes = std.mem.asBytes(&val); - dev.put(node); + try std.os.write(fd, bytes); } /// Read an immediate or position value from memory. Parameter determines @@ -200,7 +197,7 @@ pub const Machine = struct { }, .IN => { - self.__write(0, try self.readFromInput(true)); // blocking read + self.__write(0, try self.readFromInput()); // blocking read }, .OUT => { @@ -301,7 +298,7 @@ test "day 5 example 1" { try machine.run(); assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); - assert(666 == try machine.readFromOutput(false)); + assert(666 == try machine.readFromOutput()); } test "Instruction#decode ADD" { From 9864e914ba0b1a3524f6d33680f78b410f9a9ee1 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sat, 7 Dec 2019 22:41:14 +0000 Subject: [PATCH 25/32] Day 7.2 using threads --- 07/src/main.zig | 217 ++++++++++++++++++++++++++++++++-------- lib/intcode/intcode.zig | 14 +-- 2 files changed, 184 insertions(+), 47 deletions(-) diff --git a/07/src/main.zig b/07/src/main.zig index b71a8d5..06b7b80 100644 --- a/07/src/main.zig +++ b/07/src/main.zig @@ -126,6 +126,175 @@ const perm1 = [120][5]i32{ .{ 4, 3, 2, 1, 0 }, }; +const perm2 = [120][5]i32{ + .{ 5, 6, 7, 8, 9 }, + .{ 5, 6, 7, 9, 8 }, + .{ 5, 6, 8, 7, 9 }, + .{ 5, 6, 8, 9, 7 }, + .{ 5, 6, 9, 7, 8 }, + .{ 5, 6, 9, 8, 7 }, + .{ 5, 7, 6, 8, 9 }, + .{ 5, 7, 6, 9, 8 }, + .{ 5, 7, 8, 6, 9 }, + .{ 5, 7, 8, 9, 6 }, + .{ 5, 7, 9, 6, 8 }, + .{ 5, 7, 9, 8, 6 }, + .{ 5, 8, 6, 7, 9 }, + .{ 5, 8, 6, 9, 7 }, + .{ 5, 8, 7, 6, 9 }, + .{ 5, 8, 7, 9, 6 }, + .{ 5, 8, 9, 6, 7 }, + .{ 5, 8, 9, 7, 6 }, + .{ 5, 9, 6, 7, 8 }, + .{ 5, 9, 6, 8, 7 }, + .{ 5, 9, 7, 6, 8 }, + .{ 5, 9, 7, 8, 6 }, + .{ 5, 9, 8, 6, 7 }, + .{ 5, 9, 8, 7, 6 }, + .{ 6, 5, 7, 8, 9 }, + .{ 6, 5, 7, 9, 8 }, + .{ 6, 5, 8, 7, 9 }, + .{ 6, 5, 8, 9, 7 }, + .{ 6, 5, 9, 7, 8 }, + .{ 6, 5, 9, 8, 7 }, + .{ 6, 7, 5, 8, 9 }, + .{ 6, 7, 5, 9, 8 }, + .{ 6, 7, 8, 5, 9 }, + .{ 6, 7, 8, 9, 5 }, + .{ 6, 7, 9, 5, 8 }, + .{ 6, 7, 9, 8, 5 }, + .{ 6, 8, 5, 7, 9 }, + .{ 6, 8, 5, 9, 7 }, + .{ 6, 8, 7, 5, 9 }, + .{ 6, 8, 7, 9, 5 }, + .{ 6, 8, 9, 5, 7 }, + .{ 6, 8, 9, 7, 5 }, + .{ 6, 9, 5, 7, 8 }, + .{ 6, 9, 5, 8, 7 }, + .{ 6, 9, 7, 5, 8 }, + .{ 6, 9, 7, 8, 5 }, + .{ 6, 9, 8, 5, 7 }, + .{ 6, 9, 8, 7, 5 }, + .{ 7, 5, 6, 8, 9 }, + .{ 7, 5, 6, 9, 8 }, + .{ 7, 5, 8, 6, 9 }, + .{ 7, 5, 8, 9, 6 }, + .{ 7, 5, 9, 6, 8 }, + .{ 7, 5, 9, 8, 6 }, + .{ 7, 6, 5, 8, 9 }, + .{ 7, 6, 5, 9, 8 }, + .{ 7, 6, 8, 5, 9 }, + .{ 7, 6, 8, 9, 5 }, + .{ 7, 6, 9, 5, 8 }, + .{ 7, 6, 9, 8, 5 }, + .{ 7, 8, 5, 6, 9 }, + .{ 7, 8, 5, 9, 6 }, + .{ 7, 8, 6, 5, 9 }, + .{ 7, 8, 6, 9, 5 }, + .{ 7, 8, 9, 5, 6 }, + .{ 7, 8, 9, 6, 5 }, + .{ 7, 9, 5, 6, 8 }, + .{ 7, 9, 5, 8, 6 }, + .{ 7, 9, 6, 5, 8 }, + .{ 7, 9, 6, 8, 5 }, + .{ 7, 9, 8, 5, 6 }, + .{ 7, 9, 8, 6, 5 }, + .{ 8, 5, 6, 7, 9 }, + .{ 8, 5, 6, 9, 7 }, + .{ 8, 5, 7, 6, 9 }, + .{ 8, 5, 7, 9, 6 }, + .{ 8, 5, 9, 6, 7 }, + .{ 8, 5, 9, 7, 6 }, + .{ 8, 6, 5, 7, 9 }, + .{ 8, 6, 5, 9, 7 }, + .{ 8, 6, 7, 5, 9 }, + .{ 8, 6, 7, 9, 5 }, + .{ 8, 6, 9, 5, 7 }, + .{ 8, 6, 9, 7, 5 }, + .{ 8, 7, 5, 6, 9 }, + .{ 8, 7, 5, 9, 6 }, + .{ 8, 7, 6, 5, 9 }, + .{ 8, 7, 6, 9, 5 }, + .{ 8, 7, 9, 5, 6 }, + .{ 8, 7, 9, 6, 5 }, + .{ 8, 9, 5, 6, 7 }, + .{ 8, 9, 5, 7, 6 }, + .{ 8, 9, 6, 5, 7 }, + .{ 8, 9, 6, 7, 5 }, + .{ 8, 9, 7, 5, 6 }, + .{ 8, 9, 7, 6, 5 }, + .{ 9, 5, 6, 7, 8 }, + .{ 9, 5, 6, 8, 7 }, + .{ 9, 5, 7, 6, 8 }, + .{ 9, 5, 7, 8, 6 }, + .{ 9, 5, 8, 6, 7 }, + .{ 9, 5, 8, 7, 6 }, + .{ 9, 6, 5, 7, 8 }, + .{ 9, 6, 5, 8, 7 }, + .{ 9, 6, 7, 5, 8 }, + .{ 9, 6, 7, 8, 5 }, + .{ 9, 6, 8, 5, 7 }, + .{ 9, 6, 8, 7, 5 }, + .{ 9, 7, 5, 6, 8 }, + .{ 9, 7, 5, 8, 6 }, + .{ 9, 7, 6, 5, 8 }, + .{ 9, 7, 6, 8, 5 }, + .{ 9, 7, 8, 5, 6 }, + .{ 9, 7, 8, 6, 5 }, + .{ 9, 8, 5, 6, 7 }, + .{ 9, 8, 5, 7, 6 }, + .{ 9, 8, 6, 5, 7 }, + .{ 9, 8, 6, 7, 5 }, + .{ 9, 8, 7, 5, 6 }, + .{ 9, 8, 7, 6, 5 }, +}; + +fn doIt(m: *intcode.Machine) void { + if (m.run()) {} else |err| { + std.debug.warn("Machine {} failed to run successfully: {}\n", m.idx, err); + } +} + +fn run(program: []i32, machines: *[5]intcode.Machine, permutations: [120][5]i32) !i32 { + var max: i32 = 0; + + for (permutations) |inputs| { + // Reset program state each time + for (machines) |*machine, i| { + std.mem.copy(i32, machine.memory, program); + machine.ip = 0; + machine.idx = i; + } + + // Phase inputs + for (inputs) |input, i| { + try machines[i].writeToInput(input); + } + + // Provide starting value of 0 + try machines[0].writeToInput(0); + + // run the machines asychronously + var f0 = try std.Thread.spawn(&machines[0], doIt); + var f1 = try std.Thread.spawn(&machines[1], doIt); + var f2 = try std.Thread.spawn(&machines[2], doIt); + var f3 = try std.Thread.spawn(&machines[3], doIt); + var f4 = try std.Thread.spawn(&machines[4], doIt); + + f0.wait(); + f1.wait(); + f2.wait(); + f3.wait(); + f4.wait(); + + const final = try machines[4].readFromOutput(); + if (final > max) + max = final; + } + + return max; +} + pub fn main() anyerror!void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); @@ -145,12 +314,9 @@ pub fn main() anyerror!void { // Now wire up the machines correctly. The output of each machine should be // the input to the next. const pipes: [6]intcode.CharDev = .{ - try std.os.pipe(), - try std.os.pipe(), - try std.os.pipe(), - try std.os.pipe(), - try std.os.pipe(), - try std.os.pipe(), + try std.os.pipe(), try std.os.pipe(), + try std.os.pipe(), try std.os.pipe(), + try std.os.pipe(), try std.os.pipe(), }; machines[0].input = pipes[0]; @@ -168,42 +334,11 @@ pub fn main() anyerror!void { machines[4].input = machines[3].output; machines[4].output = pipes[5]; - // 120 phase permutations. Find the highest. - var max: i32 = 0; - for (perm1) |inputs| { - for (machines) |*machine| { - std.mem.copy(i32, machine.memory, program); - machine.ip = 0; - } - - // Phase inputs - for (inputs) |input, i| { - try machines[i].writeToInput(input); - } - - // Provide starting value of 0 - try machines[0].writeToInput(0); - - // run the program - for (machines) |*machine, i| { - try machine.run(); - } - - const final = try machines[4].readFromOutput(); - if (final > max) - max = final; - - // Don't forget to free everything! - for (machines) |*machine, i| { - alloc.free(machine.memory); - } - } - - std.debug.warn("Day 7, Part 1: {}\n", max); + std.debug.warn("Day 7, Part 1: {}\n", try run(program, &machines, perm1)); // In part 2, the machines need to be wired into a feedback loop. // To do this, drop pipe 6 and replace it with pipe 0 - std.os.close(pipes[5][0]); - std.os.close(pipes[5][1]); - machines[4].output = machines[0].input; + machines[0].input = machines[4].output; + + std.debug.warn("Day 7, Part 2: {}\n", try run(program, &machines, perm2)); } diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 471ec41..aba7eae 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -12,9 +12,6 @@ pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.S while (try stream.readUntilDelimiterOrEof(&buf, ',')) |num| { var trimmed = std.mem.trimRight(u8, num, "\r\n"); program[i] = try std.fmt.parseInt(i32, trimmed, 10); - - // std.debug.warn("{},", program[i]); - i += 1; } @@ -92,6 +89,7 @@ const Instruction = struct { pub const Machine = struct { alloc: *std.mem.Allocator, + idx: usize = 0, // handy for debugging memory: []i32, @@ -144,20 +142,22 @@ pub const Machine = struct { return self.__out(self.output, val); } - inline fn __in(self: *Machine, dev: CharDev) !i32 { + fn __in(self: *Machine, dev: CharDev) !i32 { const fd = dev[0]; // Read from the pipe var store: [4]u8 = undefined; + // std.debug.warn("{}: __in({} <- {})\n", self.idx, dev[0], dev[1]); var n = try std.os.read(fd, &store); std.debug.assert(n == 4); // TODO: handle partial reads return std.mem.readIntNative(i32, &store); } - inline fn __out(self: *Machine, dev: CharDev, val: i32) !void { + fn __out(self: *Machine, dev: CharDev, val: i32) !void { const fd = dev[1]; // Write to the pipe const bytes = std.mem.asBytes(&val); + // std.debug.warn("{}: __out({} -> {}, {})\n", self.idx, dev[1], dev[0], val); try std.os.write(fd, bytes); } @@ -236,7 +236,9 @@ pub const Machine = struct { } }, - .END => {}, + .END => { + // std.debug.warn("{}: ended\n", self.idx); + }, }; // Only modify IP if the instruction itself has not From 96e35f265efc054718e380e5102f33dbb026d70f Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sun, 8 Dec 2019 13:12:09 +0000 Subject: [PATCH 26/32] Day 8, all in --- 08/build.zig | 14 +++++++ 08/input | 1 + 08/src/main.zig | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 08/build.zig create mode 100644 08/input create mode 100644 08/src/main.zig diff --git a/08/build.zig b/08/build.zig new file mode 100644 index 0000000..773a3c1 --- /dev/null +++ b/08/build.zig @@ -0,0 +1,14 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("08", "src/main.zig"); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/08/input b/08/input new file mode 100644 index 0000000..cf062aa --- /dev/null +++ b/08/input @@ -0,0 +1 @@ +222222222222220222122222220022222222222202222222222222220202222222222201212222120222222220222102222212222222222012222222002222221222222202222220022220222222222222222222122222220222222222022202222222222222220222222222222222202222221222222221222202222212222222222102222222202222220222222222222221222220222222222222221222122222221022222222222212222222222222221212222222222212222202220222220220222112222202222222222122222222122222220222222202222222222222222222222222221222122222221022222222122222222222222222221102222222222201202212021222220220222212222202222222222002222222202222220222222202222221222222222222222222221222222222222122222222022202222222222222220202222222222200202202121222222221222202222222222222222022222222012202220222222202222222122222222222222222222222222222222022222222122212222222222222220112222222222221222202221222221221222122222222222222222112222222212212222222222102222222222221222222222222220222022222220022222222022222222222222222221102222222222201222212020222222222222002222202222222222022222022002012222222222012222220222222222222222222221222222222221122222222220212022222222222220012222222222200202212220222222220222212212202222222222002222122002212222222222222222220222221222222222222220222222222220222222222020212022222222222220002222222222211222222022222221221222202222222222222222002222022212102221222222012222220122222222222222222220222122222221122222222120212022222222222022012222222222200202222221222220222202102202202222222222202222022222022220222222212222220222222222222222222220222022222222122222222220212222222222222222002222222222221202212220222221221202012222222222222222022222122202002221222220002222221222220222222222222221222222222221222222222020212222222222222222102222222222200202212220222222220202112202212222220222012222222212112221222222212222220022220222222222222220222022222221122222222120212122222222222020212222222222200002202221222220222212222202222222220222212222222001012221222220202222120122221222222222222221222202222222122222222220222022222222222022102222222222221222222020222221222212012202212222221222112222122011012221222221222222211022220222222222222220222122222122122222222221222122222222222021112222222222220002212221222221220222122202202222221222002222122020012221222220112222111222222212222222222220222002222220122222222221222222222222222021222222222222201012212020222220220222002222202222222222202222122121212220222220102222002122222202222222222222222022222222122222222020212222222222222222202222222222211002202121222221221222102212202222221222012222022202122220222221222220001022221202222222222221222222222220122222222121222222222222222021122222222222202012211120222221220202102222212222221222002222122110012222222222212222120222221222222222222220222112222222022222222222212122222222222120202222222222210012222220222221222202112212202222221222222222022022122220222220222222000022221212222222222221222012222020222222222120212022222222222120202222222222202222202220222221221202012002212222222222122222222012102220222220012222121122222202222222222222222002222022222222222120202022222222222121212222222222202122222220222222221202002102222222220222212222122212022221222220012221220022222212222221222221222012222122222220222121212022222222020120222222222222222202200120220220222212112102212222222222212222122120002221222222022221101122221222222220222222222122222222122220222221212022222222020220102222222222222112221122220222221202212002202222222222222222022022212222222221012222001122220212222220222220222002222121222222222120222022222222020120222222222222222002221120221221221222202222202222222222012222022201122221222220112221002222221222222220222221222222222122122221222120222022222222022020102222222222222222211122222222221212012202212222222222002222222002222220222221112222011122220222222222222220222202222122022220222022222220222222021222202222222222210222210021220221222222022212222222221222212222122012012222222220122221220222121202222220212221222122222120022221222122222122222222121022212222222222220012222020221220220202212122222222222222222222022210202221222220212220220222220222222220202221222222222021222221222120212220222222121120202222222222220122212121221221221212102122202222221222212222122101102221222222212222200222021212222221222222222022222022022221222022222220222222121220122222222222202222221122220222220222112102212212222222022222222200112222222222102221202222220222222221202222222212222210122222222220222220222222121221212222222222220110222022201222222222202012212222220222112222222111222220222220112221101222021212222221202221222112222022122222222121222121222222021120122222222222200110102121210221222222112222202212220222202222022101102221222220102221110122101212222121212221222112222011020220222022202022222222120020222222222222212212011020210221221222202102222222220222222222222111122220222221202221121122022202222020222221222202222211222220222021202222222222220220122222202222210222122120221222221202012012222222222222012222122100212221222221002221212022000212222221202221222222222100020222222020222120222222122121212222212222212122220120212220222212012012222022221222012222022001122220222221102221012222220202222220202222222122222012220220222022222121222222020022102222222222210220120020220221222212212002212102220222202222122000012222222221122222200022221202222122212222222212222201022221222021212121222212120222112222222222210001002122220220222212222012222112121222222222122020012220222222002222101022210212222022212220222122222000021222222122212220222222122222202222202222202112221020210222202202012212212122121222012222222020022221222222212220010222122212222221222221222102222220222222221012202221122212121021202222222222222210221122211220200212212102202122221222022222022211202221222222002220011022001222202120212220222212222110112202220111222222022222120022102222202222212102012221220221210222012122212012221222112222222120202222222222022221101022011202202220222221222202222210200201221012202120122212022220112222212222201120121121220222222212212022222002220222012222022200122220222221122221112022120222222221222222222212222212001201222112222121222202120122012222222222221011200120210221210212012022222002220222012222122220122221222221122221002022202212202122222220222202222121221210121010222222122212220020222222202222222000121021210220222212112022222202020222012222122000002220222222122220020122101212201221212222222212222010220220022202202120122222122221122222212222210022211222210222202222212002222002220222222222022121022221222220012222102222211212202221222220222222222011220221221012212222222212020021212222202222221201020121212221210212202112222102020222002222122202122221222221112221200122121202210122202222222202222211110221021022212122222212020122022222212222211022212220212220211202222222222212022222002222222001022220222222212222020222220212221021212222222122222101001212122102202121222222020222222222212222220101000222222222212212002022222002022222002222022220002120222221122221112022002222211122202222222012222122220211222222212122122222022222112222202222212122011021212222211212022202202202122222022222122120012220222221102220102022001202202222202220222222222210112002022120222221022202221120202222212222220212221222211220202212012222202002020222102222022211012020222221012220201022010202222022222220222112222022120100020120212020022212022221022222212222221110112020210221212222112102202022222222222222022210012021222220202222022122220202220221222222222202222120020002222212212022222202121022222222202222221022120021200220220212012122212122020222002222022200212120222222012222012022021222200022202221222012222101001020020221202122122222122220012222002221211221111021222221211202112122222122220222202222222011212120222222222221100222210202200020222222222012222100112002021121222122022222022122022222102220220221102121202221202202112112202112221222122222022022122221222220222220110222021222201221212221222022222102110000020201222020022202020022222222112222222221221122221221200212112122222002120221012222022212102222222220212222021022022212202022202222222102222020120011120022222122222202121221012222202220201122102120201220221212202002202122220221202222022110022121222220112221021022121212211222202222222102222200220200221012210221222222120102002222102222211221201020211221210212022222202202221220102222222020212022222220102221121222020212201220202220222112222211102010021112202222122222122201222222122220212122001221201221212212012222202112221222122222122201022222222222202220110122112222212121212221222222222220121120120010200120022202122122212222112220222120002222222220220222112212212102220222112222022201122022222221022222212122022202212221222221222112222110111112220220210120222202020100022222022022221202011020220220220222212102222112022220122222222220202220222222112221022122221202210122212220222102220021000202022120221120022222221221022222122120201120111022210222220222202212212112020221022222022001122022222220022220210122111202212220202220222202222110222201120111222121122222020210102222022120210100101020212221221222112102212112220222012222122202122220222222022220122220220222212122202222222112221111102210021002202020122222221100112222212122210200022120202222220222002022222222222222112222122000112020222222112221102021002202200020222220222022220012001111120001220020222202121011212222122202212120020222221220202212202002202102220222122222222001002222222220212221120220111012220221222222222222222200010011222211211121222202022010002222222022220012100120211222211212222012202022220220012222222202102120222221110202212120112202202222222222022212222212001020121020211221222222020222212222012110200100102122200222201212122202022012022221122222122112102011222220202220221022122222210120202222222112222000202021220100220221222202122110202222102212200210221021201222202222212202022022220220122212022100202111222222022200101020110201220020222221122002221212212112021220220221222212222220002222102200211000120121220222212202212022212022221221202202022111002012222221122201022222022002002020222221122022221220102222222201201122122222122020012222212100212200202221212221210212122112022122220221122212022100112020222221000210211121212210020220202221222012220012200211120102212122222202022122202222122120202010211020200220222222102222112222022220222202022201200110222221200212222221110200012221222221222222221111102021120000200221222202020001222222022010222212121122212220202202112222022122120220222202022021220021222220210202001220012012220222212221022112221200122222022011210222122212020000012222002200220202210121202221202202102202102112220222102212022122000222222220112202200121222112111022202220122002221020000200121011220220222212222010002222202120222212112022202221222222212122122112220220122202022102200121222220001210122220010202200221002221122112221021112212020111201122122212120102022222212010212102201222220222112222022202112002120221112202022222112210222222102211220222111101121222012220222002221211111022220010212020222222220220102222012222200010200121200222110212022202002202121222010202122202112120222220001211002120222100010221102021122222222211101021221001200121022212020101002222012122201212011222111221002202112012002112022221221222222000212102222220100201120122210021012021122022022012220102221221121211200120122212020001202222122000211021201121120220112222122112202212222220122222222121201110222222122210102121102111200220102221022012221002221110022022201011122222022102012222002211221221202220221221210212102102222202222222011222222001201012222220222212010122112202010221212221122212221122200002120000020200022212021012002220002110200112102121121221201222002212102202120222121202122012211212222220210200022021201102000022102121022002220022122122121222221100122212022002022122002102200222222220212221001222222102102212120202012212122022221112222221210211200121211211222122112221022102221012122122220010102011222222121120112220122102222121121020221221010222122202122112121211202222122100221010222220102222220122010200011120122220222102221221221121022102000001122222221100222121102122211012212221120220212202212112202002020211022202022221211000222221111220222122212102110121122022122202222120010121020121210101222212120101012120212211200120120122102221111222122112112122021221120212222201101011222221112222020120011022011221212120022102222110022220021012212210022212022202002222112202202100200120200222201212002022022112122221102202122221121111222220111210101121122021021120112122022112220111202102222021020020122222120110122222222111200022002120020221212212012022022022121210212212122201112202222222202111011021202222101121112222122202220020221212221201020211022202222211202120212121201120111120102222200202222012012022121202101212222000200111222220211111102122100212222022122120222012222200100220020220022212222222022121202021202122211022101022200220020222022112012022120202101212022012100211222221111021211120111021011120102021022102222112111100022012112111122222020121012022012200201002000022101221201212012012112102120200022202022021010212222221211202121121021012212120112220021102220111102011022221220110222222222102212221112021222120011222211222020222222002122122021200102202222102011112222220202110202121021201000222102120020112220120110202222210020101022202221012012021102112211100100020101221210202222112102112120220002212122211022120222220122200210222210111212222122222120212021102112122220212011220222212121112212220102111201201002122222220220202222212102202120211201202222202010211222222011011120100212110211220112020020102021120202222222100201120022202222020112021002012221120201221212221110222002022202222020202122212122210110011222222101201210111211101022222002120221122020210112112022220101102222212120212012020102201212010210221111222110222212012002012220221011212022112110012222222212021212100002102202122012020121112021002201222021221220112122212021120102120002212210121200222221222212202222022022100022201010202222112001210222212220201201001021110112122102120001122222221010102121221002120222212022212112221202200211120202022202221011212022012122101021220100202122212111011222200122211101012121111111122112221200122022211101021221020201222022202220221112122022121212200001221222221000222212002212212122010212222122122101212222220121020020111100000110122102120122202220201221011222212020221220212022221102221202212202121101122010220001212012212112201021211000022222220202100222211112020021221121122202121022222022222220102022002122120211011220212020021022222102022222210012222101021222212012012122111121110120122122202001101222220020112021102002110210221212220002022221122001011220212000021222212221102222122012110201020121020100122222202022222202211121110212102022012122112222100101202010201121110010220102222202022220111201122021000221102222212220111202220122122202021202120021221021212212102102102122222212222222212201122222202021210110222112011121221012020001222020022201201101210010202020202000102222120022010220201121220122221122212112012112211120211200202022202120021222021222012112012110120010012210212121121201011020012122110012202102011101220220212200121020000101100100111012010120120000122100110011200110100002001011101102110002120111 diff --git a/08/src/main.zig b/08/src/main.zig new file mode 100644 index 0000000..2ca178b --- /dev/null +++ b/08/src/main.zig @@ -0,0 +1,104 @@ +const std = @import("std"); + +const depth = 100; +const width = 25; +const height = 6; + +const Layer = [height][width]Colour; +const Image = [depth]Layer; +const Colour = enum(u8) { + Black = 0, + White = 1, + Trans = 2, +}; + +fn printLayer(l: Layer) void { + for (l) |row| { + for (row) |byte| { + switch (byte) { + .Black => { + std.debug.warn(" "); + }, + .White => { + std.debug.warn("*"); + }, + else => { + std.debug.warn(" "); + }, + } + } + std.debug.warn("\n"); + } + std.debug.warn("\n"); +} + +fn printImage(image: Image) void { + var meta: Layer = undefined; + for (meta) |row, y| { + for (row) |_, x| { + meta[y][x] = .Trans; + } + } + + for (meta) |*row, y| { + for (row) |*b, x| { + var z: usize = 0; + while (b.* == .Trans) : (z += 1) { + if (image[z][y][x] != .Trans) { + b.* = image[z][y][x]; + } + } + } + } + + printLayer(meta); +} + +pub fn main() anyerror!void { + var img: Image = undefined; + var zeroCounts = [_]usize{0} ** depth; + + const file = std.io.getStdIn(); + const stream = &file.inStream().stream; + + for (img) |*layer, z| { + for (layer) |*row| { + for (row) |*pixel| { + var b = try stream.readByte(); + if (b == '0') zeroCounts[z] += 1; + pixel.* = @intToEnum(Colour, b - '0'); + } + } + } + + // Now count how many zeroes are in each layer, picking out the smallest + var minCount: usize = width * height; + var minZ: usize = 0; + + for (zeroCounts) |count, i| { + if (count < minCount) { + minCount = count; + minZ = i; + } + } + + var num1s: usize = 0; + var num2s: usize = 0; + for (img[minZ]) |row| { + for (row) |b| { + switch (b) { + .White => { + num1s += 1; + }, + .Trans => { + num2s += 1; + }, + else => {}, + } + } + } + + std.debug.warn("Day 8, Part 1: {} with {} zeroes, {} 1s, {} 2s. Result: {}\n\n", minZ, minCount, num1s, num2s, num1s * num2s); + + printImage(img); +} From 289aa920d0106699d4d1b6e6076d3e17c5eb9828 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 9 Dec 2019 10:48:40 +0000 Subject: [PATCH 27/32] Switch to i64 for words --- 02/src/main.zig | 16 ++++----- 05/src/main.zig | 6 ++-- 07/src/main.zig | 12 +++---- lib/intcode/intcode.zig | 75 +++++++++++++++++++++-------------------- 4 files changed, 55 insertions(+), 54 deletions(-) diff --git a/02/src/main.zig b/02/src/main.zig index 412f1b4..0d0d8f9 100644 --- a/02/src/main.zig +++ b/02/src/main.zig @@ -1,7 +1,7 @@ const std = @import("std"); const intcode = @import("intcode"); -fn run(alloc: *std.mem.Allocator, program: []i32, noun: i32, verb: i32) !i32 { +fn run(alloc: *std.mem.Allocator, program: []intcode.Word, noun: intcode.Word, verb: intcode.Word) !intcode.Word { program[1] = noun; program[2] = verb; @@ -10,11 +10,11 @@ fn run(alloc: *std.mem.Allocator, program: []i32, noun: i32, verb: i32) !i32 { return program[0]; } -fn runCopy(alloc: *std.mem.Allocator, program: []i32, noun: i32, verb: i32) !i32 { - var memory = try alloc.alloc(i32, program.len); +fn runCopy(alloc: *std.mem.Allocator, program: []intcode.Word, noun: intcode.Word, verb: intcode.Word) !intcode.Word { + var memory = try alloc.alloc(intcode.Word, program.len); defer alloc.free(memory); - std.mem.copy(i32, memory, program); + std.mem.copy(intcode.Word, memory, program); return run(alloc, memory, noun, verb); } @@ -31,14 +31,14 @@ pub fn main() anyerror!void { std.debug.warn("Day 2, Part 1: {}\n", try runCopy(alloc, program, 12, 2)); // Part 2: 100*100 = 10,000 combinations to try. - var memory: []i32 = try alloc.alloc(i32, program.len); + var memory: []intcode.Word = try alloc.alloc(intcode.Word, program.len); var done: bool = false; - var noun: i32 = 0; - var verb: i32 = 0; + var noun: intcode.Word = 0; + var verb: intcode.Word = 0; std.debug.warn("Day 2, Part 2: "); while (!done) { - std.mem.copy(i32, memory, program); + std.mem.copy(intcode.Word, memory, program); const result = try run(alloc, memory, noun, verb); // Too high: 250800 (noun=33, verb=76) diff --git a/05/src/main.zig b/05/src/main.zig index 33b581c..9d301ed 100644 --- a/05/src/main.zig +++ b/05/src/main.zig @@ -8,8 +8,8 @@ pub fn main() anyerror!void { const alloc = &arena.allocator; var p1 = try intcode.loadFromStdIn(alloc); - var p2 = try alloc.alloc(i32, p1.len); - std.mem.copy(i32, p2, p1); + var p2 = try alloc.alloc(intcode.Word, p1.len); + std.mem.copy(intcode.Word, p2, p1); var m1 = try intcode.Machine.init(alloc, p1); var m2 = try intcode.Machine.init(alloc, p2); @@ -17,7 +17,7 @@ pub fn main() anyerror!void { try m1.writeToInput(1); // Air conditioner unit try m1.run(); - var out: i32 = 0; + var out: intcode.Word = 0; while (out == 0) : (out = try m1.readFromOutput()) {} std.debug.warn("Day 5, Part 1: {}\n", out); diff --git a/07/src/main.zig b/07/src/main.zig index 06b7b80..9fc7d70 100644 --- a/07/src/main.zig +++ b/07/src/main.zig @@ -3,7 +3,7 @@ const std = @import("std"); const intcode = @import("intcode"); // TODO: it would be awesome if we could make this a comptime function -const perm1 = [120][5]i32{ +const perm1 = [120][5]intcode.Word{ .{ 0, 1, 2, 3, 4 }, .{ 0, 1, 2, 4, 3 }, .{ 0, 1, 3, 2, 4 }, @@ -126,7 +126,7 @@ const perm1 = [120][5]i32{ .{ 4, 3, 2, 1, 0 }, }; -const perm2 = [120][5]i32{ +const perm2 = [120][5]intcode.Word{ .{ 5, 6, 7, 8, 9 }, .{ 5, 6, 7, 9, 8 }, .{ 5, 6, 8, 7, 9 }, @@ -255,13 +255,13 @@ fn doIt(m: *intcode.Machine) void { } } -fn run(program: []i32, machines: *[5]intcode.Machine, permutations: [120][5]i32) !i32 { - var max: i32 = 0; +fn run(program: []intcode.Word, machines: *[5]intcode.Machine, permutations: [120][5]intcode.Word) !intcode.Word { + var max: intcode.Word = 0; for (permutations) |inputs| { // Reset program state each time for (machines) |*machine, i| { - std.mem.copy(i32, machine.memory, program); + std.mem.copy(intcode.Word, machine.memory, program); machine.ip = 0; machine.idx = i; } @@ -308,7 +308,7 @@ pub fn main() anyerror!void { // Allocate memory once only. for (machines) |*machine| { machine.alloc = alloc; - machine.memory = try alloc.alloc(i32, program.len); + machine.memory = try alloc.alloc(intcode.Word, program.len); } // Now wire up the machines correctly. The output of each machine should be diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index aba7eae..ce3279f 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -2,16 +2,17 @@ const std = @import("std"); // We're using pipes as character devices pub const CharDev = [2]i32; +pub const Word = i64; -pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 { - var program = try alloc.alloc(i32, 1024); +pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]Word { + var program = try alloc.alloc(Word, 1024); var buf = [_]u8{0} ** 255; var i: u32 = 0; while (try stream.readUntilDelimiterOrEof(&buf, ',')) |num| { var trimmed = std.mem.trimRight(u8, num, "\r\n"); - program[i] = try std.fmt.parseInt(i32, trimmed, 10); + program[i] = try std.fmt.parseInt(Word, trimmed, 10); i += 1; } @@ -20,7 +21,7 @@ pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.S return program[0..program.len]; } -pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]i32 { +pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]Word { const file = std.io.getStdIn(); const stream = &file.inStream().stream; @@ -50,7 +51,7 @@ const Instruction = struct { // Modes for each parameter of the opcode. Parameter 0 is in position 0, etc modes: [3]Mode, - pub fn decode(value: i32) !Instruction { + pub fn decode(value: Word) !Instruction { assert(value > 0 and value < 99999); var buf: [6]u8 = undefined; @@ -91,14 +92,14 @@ pub const Machine = struct { alloc: *std.mem.Allocator, idx: usize = 0, // handy for debugging - memory: []i32, + memory: []Word, ip: usize = 0, input: CharDev, output: CharDev, - pub fn Run(alloc: *std.mem.Allocator, program: []i32) anyerror!Machine { + pub fn Run(alloc: *std.mem.Allocator, program: []Word) anyerror!Machine { var machine = try init(alloc, program); try machine.run(); @@ -106,7 +107,7 @@ pub const Machine = struct { return machine; } - pub fn init(alloc: *std.mem.Allocator, program: []i32) anyerror!Machine { + pub fn init(alloc: *std.mem.Allocator, program: []Word) anyerror!Machine { return Machine{ .alloc = alloc, .memory = program, @@ -126,34 +127,34 @@ pub const Machine = struct { std.os.close(self.output[1]); } - pub fn readFromInput(self: *Machine) !i32 { + pub fn readFromInput(self: *Machine) !Word { return self.__in(self.input); } - pub fn writeToInput(self: *Machine, val: i32) !void { + pub fn writeToInput(self: *Machine, val: Word) !void { return self.__out(self.input, val); } - pub fn readFromOutput(self: *Machine) !i32 { + pub fn readFromOutput(self: *Machine) !Word { return self.__in(self.output); } - pub fn writeToOutput(self: *Machine, val: i32) !void { + pub fn writeToOutput(self: *Machine, val: Word) !void { return self.__out(self.output, val); } - fn __in(self: *Machine, dev: CharDev) !i32 { + fn __in(self: *Machine, dev: CharDev) !Word { const fd = dev[0]; // Read from the pipe - var store: [4]u8 = undefined; + var store: [8]u8 = undefined; // std.debug.warn("{}: __in({} <- {})\n", self.idx, dev[0], dev[1]); var n = try std.os.read(fd, &store); - std.debug.assert(n == 4); // TODO: handle partial reads + std.debug.assert(n == 8); // TODO: handle partial reads - return std.mem.readIntNative(i32, &store); + return std.mem.readIntNative(Word, &store); } - fn __out(self: *Machine, dev: CharDev, val: i32) !void { + fn __out(self: *Machine, dev: CharDev, val: Word) !void { const fd = dev[1]; // Write to the pipe const bytes = std.mem.asBytes(&val); @@ -163,7 +164,7 @@ pub const Machine = struct { /// Read an immediate or position value from memory. Parameter determines /// which field following the current instruction to read from - inline fn __read(self: *Machine, parameter: usize, mode: Mode) i32 { + inline fn __read(self: *Machine, parameter: usize, mode: Mode) Word { const immediate = self.memory[self.ip + parameter + 1]; return switch (mode) { @@ -172,7 +173,7 @@ pub const Machine = struct { }; } - inline fn __write(self: *Machine, parameter: usize, value: i32) void { + inline fn __write(self: *Machine, parameter: usize, value: Word) void { const dest = self.__read(parameter, .Immediate); self.memory[@intCast(usize, dest)] = value; } @@ -252,54 +253,54 @@ const assert = std.debug.assert; const test_allocator = std.heap.page_allocator; test "day 2 example 1" { - var before: [12]i32 = .{ 1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50 }; - var after: [12]i32 = .{ 3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50 }; + var before: [12]Word = .{ 1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50 }; + var after: [12]Word = .{ 3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); - assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); } test "day 2 example 2" { - var before: [5]i32 = .{ 1, 0, 0, 0, 99 }; - var after: [5]i32 = .{ 2, 0, 0, 0, 99 }; + var before: [5]Word = .{ 1, 0, 0, 0, 99 }; + var after: [5]Word = .{ 2, 0, 0, 0, 99 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); - assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); } test "day 2 example 3" { - var before: [5]i32 = .{ 2, 3, 0, 3, 99 }; - var after: [5]i32 = .{ 2, 3, 0, 6, 99 }; + var before: [5]Word = .{ 2, 3, 0, 3, 99 }; + var after: [5]Word = .{ 2, 3, 0, 6, 99 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); - assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); } test "day 2 example 4" { - var before: [6]i32 = .{ 2, 4, 4, 5, 99, 0 }; - var after: [6]i32 = .{ 2, 4, 4, 5, 99, 9801 }; + var before: [6]Word = .{ 2, 4, 4, 5, 99, 0 }; + var after: [6]Word = .{ 2, 4, 4, 5, 99, 9801 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); - assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); } test "day 2 example 5" { - var before: [9]i32 = .{ 1, 1, 1, 4, 99, 5, 6, 0, 99 }; - var after: [9]i32 = .{ 30, 1, 1, 4, 2, 5, 6, 0, 99 }; + var before: [9]Word = .{ 1, 1, 1, 4, 99, 5, 6, 0, 99 }; + var after: [9]Word = .{ 30, 1, 1, 4, 2, 5, 6, 0, 99 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); - assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); } test "day 5 example 1" { - var before: [5]i32 = .{ 3, 0, 4, 0, 99 }; - var after: [5]i32 = .{ 666, 0, 4, 0, 99 }; + var before: [5]Word = .{ 3, 0, 4, 0, 99 }; + var after: [5]Word = .{ 666, 0, 4, 0, 99 }; var machine = try Machine.init(test_allocator, before[0..before.len]); try machine.writeToInput(666); try machine.run(); - assert(std.mem.eql(i32, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); assert(666 == try machine.readFromOutput()); } From 421455f8ba9484d1ec248a2485506fe3fc7c3042 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 9 Dec 2019 11:37:00 +0000 Subject: [PATCH 28/32] Day 9.1 --- 02/src/main.zig | 10 ++-- 09/build.zig | 15 ++++++ 09/input | 1 + 09/src/main.zig | 17 +++++++ lib/intcode/intcode.zig | 101 +++++++++++++++++++++++++++++++++------- run-intcodes | 3 +- 6 files changed, 123 insertions(+), 24 deletions(-) create mode 100644 09/build.zig create mode 100644 09/input create mode 100644 09/src/main.zig diff --git a/02/src/main.zig b/02/src/main.zig index 0d0d8f9..8bf61be 100644 --- a/02/src/main.zig +++ b/02/src/main.zig @@ -6,17 +6,13 @@ fn run(alloc: *std.mem.Allocator, program: []intcode.Word, noun: intcode.Word, v program[2] = verb; var machine = try intcode.Machine.Run(alloc, program); + defer machine.deinit(); - return program[0]; + return machine.memory[0]; } fn runCopy(alloc: *std.mem.Allocator, program: []intcode.Word, noun: intcode.Word, verb: intcode.Word) !intcode.Word { - var memory = try alloc.alloc(intcode.Word, program.len); - defer alloc.free(memory); - - std.mem.copy(intcode.Word, memory, program); - - return run(alloc, memory, noun, verb); + return run(alloc, program, noun, verb); } pub fn main() anyerror!void { diff --git a/09/build.zig b/09/build.zig new file mode 100644 index 0000000..5cfd066 --- /dev/null +++ b/09/build.zig @@ -0,0 +1,15 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("09", "src/main.zig"); + exe.setBuildMode(mode); + exe.addPackagePath("intcode", "../lib/intcode/intcode.zig"); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/09/input b/09/input new file mode 100644 index 0000000..10cef79 --- /dev/null +++ b/09/input @@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,3,0,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,34,0,1013,1101,20,0,1012,1101,536,0,1023,1101,0,23,1006,1102,1,543,1022,1102,1,27,1003,1102,25,1,1014,1102,1,29,1009,1101,0,686,1025,1101,0,30,1004,1102,1,28,1017,1102,1,35,1016,1101,765,0,1028,1102,1,33,1002,1102,1,26,1000,1102,1,822,1027,1102,1,21,1001,1102,1,1,1021,1101,31,0,1007,1101,0,39,1010,1102,36,1,1019,1101,0,32,1015,1101,0,38,1018,1101,0,24,1005,1101,22,0,1011,1101,756,0,1029,1102,1,0,1020,1102,829,1,1026,1102,1,37,1008,1101,0,695,1024,109,19,1205,2,195,4,187,1105,1,199,1001,64,1,64,1002,64,2,64,109,7,1205,-6,215,1001,64,1,64,1105,1,217,4,205,1002,64,2,64,109,-16,21108,40,42,5,1005,1015,233,1106,0,239,4,223,1001,64,1,64,1002,64,2,64,109,-13,2102,1,5,63,1008,63,33,63,1005,63,261,4,245,1105,1,265,1001,64,1,64,1002,64,2,64,109,29,21101,41,0,-9,1008,1017,41,63,1005,63,291,4,271,1001,64,1,64,1105,1,291,1002,64,2,64,109,-22,2107,27,-4,63,1005,63,307,1105,1,313,4,297,1001,64,1,64,1002,64,2,64,109,7,1207,-4,30,63,1005,63,333,1001,64,1,64,1106,0,335,4,319,1002,64,2,64,109,1,21108,42,42,6,1005,1018,353,4,341,1105,1,357,1001,64,1,64,1002,64,2,64,109,14,21101,43,0,-7,1008,1019,41,63,1005,63,377,1106,0,383,4,363,1001,64,1,64,1002,64,2,64,109,-8,21102,44,1,-1,1008,1017,47,63,1005,63,407,1001,64,1,64,1105,1,409,4,389,1002,64,2,64,109,-15,2101,0,2,63,1008,63,25,63,1005,63,433,1001,64,1,64,1105,1,435,4,415,1002,64,2,64,109,7,1201,-8,0,63,1008,63,30,63,1005,63,455,1105,1,461,4,441,1001,64,1,64,1002,64,2,64,109,-12,2108,37,10,63,1005,63,483,4,467,1001,64,1,64,1106,0,483,1002,64,2,64,109,13,21107,45,44,0,1005,1011,499,1105,1,505,4,489,1001,64,1,64,1002,64,2,64,109,-2,2107,20,-8,63,1005,63,523,4,511,1106,0,527,1001,64,1,64,1002,64,2,64,109,20,2105,1,-6,1001,64,1,64,1105,1,545,4,533,1002,64,2,64,109,-28,2102,1,1,63,1008,63,30,63,1005,63,565,1105,1,571,4,551,1001,64,1,64,1002,64,2,64,109,20,1206,0,583,1105,1,589,4,577,1001,64,1,64,1002,64,2,64,109,-7,1206,6,603,4,595,1106,0,607,1001,64,1,64,1002,64,2,64,109,-14,2101,0,2,63,1008,63,33,63,1005,63,629,4,613,1105,1,633,1001,64,1,64,1002,64,2,64,109,-4,1208,8,30,63,1005,63,655,4,639,1001,64,1,64,1105,1,655,1002,64,2,64,109,23,21107,46,47,0,1005,1019,673,4,661,1105,1,677,1001,64,1,64,1002,64,2,64,109,-2,2105,1,7,4,683,1001,64,1,64,1106,0,695,1002,64,2,64,109,3,21102,47,1,-7,1008,1013,47,63,1005,63,717,4,701,1105,1,721,1001,64,1,64,1002,64,2,64,109,-11,1202,-7,1,63,1008,63,32,63,1005,63,745,1001,64,1,64,1105,1,747,4,727,1002,64,2,64,109,10,2106,0,9,4,753,1001,64,1,64,1105,1,765,1002,64,2,64,109,-24,1207,8,28,63,1005,63,783,4,771,1106,0,787,1001,64,1,64,1002,64,2,64,109,5,1201,0,0,63,1008,63,26,63,1005,63,813,4,793,1001,64,1,64,1105,1,813,1002,64,2,64,109,28,2106,0,-1,1001,64,1,64,1105,1,831,4,819,1002,64,2,64,109,-22,1202,-1,1,63,1008,63,24,63,1005,63,857,4,837,1001,64,1,64,1106,0,857,1002,64,2,64,109,-9,2108,30,6,63,1005,63,873,1106,0,879,4,863,1001,64,1,64,1002,64,2,64,109,-2,1208,10,26,63,1005,63,899,1001,64,1,64,1106,0,901,4,885,4,64,99,21102,1,27,1,21101,0,915,0,1105,1,922,21201,1,25948,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1106,0,922,22101,0,1,-1,21201,-2,-3,1,21102,957,1,0,1105,1,922,22201,1,-1,-2,1106,0,968,21201,-2,0,-2,109,-3,2106,0,0 diff --git a/09/src/main.zig b/09/src/main.zig new file mode 100644 index 0000000..9b4a670 --- /dev/null +++ b/09/src/main.zig @@ -0,0 +1,17 @@ +const std = @import("std"); +const intcode = @import("intcode"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + + const alloc = &arena.allocator; + + var program = try intcode.loadFromStdIn(alloc); + + var machine = try intcode.Machine.init(alloc, program); + try machine.writeToInput(1); // BOOST program in test mode + try machine.run(); + + std.debug.warn("Day 9, Part 1: {}\n", try machine.readFromOutput()); +} diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index ce3279f..c1a2fc6 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -3,6 +3,7 @@ const std = @import("std"); // We're using pipes as character devices pub const CharDev = [2]i32; pub const Word = i64; +pub const MemSize = 1024 * 2; pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]Word { var program = try alloc.alloc(Word, 1024); @@ -37,12 +38,14 @@ const Opcode = enum(u8) { JZ = 6, LT = 7, EQ = 8, + RBO = 9, END = 99, }; const Mode = enum(u8) { Position = 0, Immediate = 1, + Relative = 2, }; const Instruction = struct { @@ -79,6 +82,7 @@ const Instruction = struct { .JZ => 3, .LT => 4, .EQ => 4, + .RBO => 2, .END => 1, }; } @@ -93,6 +97,7 @@ pub const Machine = struct { idx: usize = 0, // handy for debugging memory: []Word, + rb: Word = 0, ip: usize = 0, @@ -108,9 +113,13 @@ pub const Machine = struct { } pub fn init(alloc: *std.mem.Allocator, program: []Word) anyerror!Machine { + var memory = try alloc.alloc(Word, MemSize); + std.mem.set(Word, memory, 0); + std.mem.copy(Word, memory, program); + return Machine{ .alloc = alloc, - .memory = program, + .memory = memory, .input = try std.os.pipe(), .output = try std.os.pipe(), }; @@ -121,6 +130,7 @@ pub const Machine = struct { } pub fn deinit(self: *Machine) void { + self.alloc.free(self.memory); std.os.close(self.input[0]); std.os.close(self.input[1]); std.os.close(self.output[0]); @@ -170,12 +180,18 @@ pub const Machine = struct { return switch (mode) { .Immediate => immediate, .Position => self.memory[@intCast(usize, immediate)], + .Relative => self.memory[@intCast(usize, immediate + self.rb)], }; } - inline fn __write(self: *Machine, parameter: usize, value: Word) void { + inline fn __write(self: *Machine, parameter: usize, mode: Mode, value: Word) void { const dest = self.__read(parameter, .Immediate); - self.memory[@intCast(usize, dest)] = value; + + switch (mode) { + .Immediate => unreachable, + .Position => self.memory[@intCast(usize, dest)] = value, + .Relative => self.memory[@intCast(usize, dest + self.rb)] = value, + } } pub fn step(self: *Machine) anyerror!bool { @@ -187,18 +203,18 @@ pub const Machine = struct { const a = self.__read(0, insn.modes[0]); const b = self.__read(1, insn.modes[1]); - self.__write(2, a + b); + self.__write(2, insn.modes[2], a + b); }, .MULT => { const a = self.__read(0, insn.modes[0]); const b = self.__read(1, insn.modes[1]); - self.__write(2, a * b); + self.__write(2, insn.modes[2], a * b); }, .IN => { - self.__write(0, try self.readFromInput()); // blocking read + self.__write(0, insn.modes[0], try self.readFromInput()); // blocking read }, .OUT => { @@ -220,9 +236,9 @@ pub const Machine = struct { const b = self.__read(1, insn.modes[1]); if (a < b) { - self.__write(2, 1); + self.__write(2, insn.modes[2], 1); } else { - self.__write(2, 0); + self.__write(2, insn.modes[2], 0); } }, @@ -231,12 +247,16 @@ pub const Machine = struct { const b = self.__read(1, insn.modes[1]); if (a == b) { - self.__write(2, 1); + self.__write(2, insn.modes[2], 1); } else { - self.__write(2, 0); + self.__write(2, insn.modes[2], 0); } }, + .RBO => { + self.rb += self.__read(0, insn.modes[0]); + }, + .END => { // std.debug.warn("{}: ended\n", self.idx); }, @@ -256,54 +276,103 @@ test "day 2 example 1" { var before: [12]Word = .{ 1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50 }; var after: [12]Word = .{ 3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); + defer machine.deinit(); - assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len])); } test "day 2 example 2" { var before: [5]Word = .{ 1, 0, 0, 0, 99 }; var after: [5]Word = .{ 2, 0, 0, 0, 99 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); + defer machine.deinit(); - assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len])); } test "day 2 example 3" { var before: [5]Word = .{ 2, 3, 0, 3, 99 }; var after: [5]Word = .{ 2, 3, 0, 6, 99 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); + defer machine.deinit(); - assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len])); } test "day 2 example 4" { var before: [6]Word = .{ 2, 4, 4, 5, 99, 0 }; var after: [6]Word = .{ 2, 4, 4, 5, 99, 9801 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); + defer machine.deinit(); - assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len])); } test "day 2 example 5" { var before: [9]Word = .{ 1, 1, 1, 4, 99, 5, 6, 0, 99 }; var after: [9]Word = .{ 30, 1, 1, 4, 2, 5, 6, 0, 99 }; var machine = try Machine.Run(test_allocator, before[0..before.len]); + defer machine.deinit(); - assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len])); } test "day 5 example 1" { var before: [5]Word = .{ 3, 0, 4, 0, 99 }; var after: [5]Word = .{ 666, 0, 4, 0, 99 }; var machine = try Machine.init(test_allocator, before[0..before.len]); + defer machine.deinit(); try machine.writeToInput(666); try machine.run(); - assert(std.mem.eql(Word, before[0..before.len], after[0..after.len])); + assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len])); assert(666 == try machine.readFromOutput()); } +test "day 9 example 1" { + var before: [16]Word = .{ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 }; + var after: [16]Word = before; + var output: [16]Word = undefined; + + var machine = try Machine.init(test_allocator, before[0..before.len]); + defer machine.deinit(); + try machine.run(); + + assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len])); + + for (output) |*b| { + b.* = try machine.readFromOutput(); + } + + // This program produces a copy of itself as output + assert(std.mem.eql(Word, machine.memory[0..before.len], output[0..after.len])); +} + +test "day 9 example 2" { + var before: [8]Word = .{ 1102, 34915192, 34915192, 7, 4, 7, 99, 0 }; + var after: [8]Word = .{ 1102, 34915192, 34915192, 7, 4, 7, 99, 1219070632396864 }; + + var machine = try Machine.init(test_allocator, before[0..before.len]); + defer machine.deinit(); + try machine.run(); + + assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len])); + std.debug.assert(1219070632396864 == try machine.readFromOutput()); +} + +test "day 9 example 3" { + var before: [3]Word = .{ 104, 1125899906842624, 99 }; + var after: [3]Word = before; + + var machine = try Machine.init(test_allocator, before[0..before.len]); + defer machine.deinit(); + try machine.run(); + + assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len])); + std.debug.assert(1125899906842624 == try machine.readFromOutput()); +} + test "Instruction#decode ADD" { const insn = try Instruction.decode(1); diff --git a/run-intcodes b/run-intcodes index ac04d79..c874ac0 100755 --- a/run-intcodes +++ b/run-intcodes @@ -2,4 +2,5 @@ zig test lib/intcode/intcode.zig && zig build --build-file 02/build.zig run < 02/input && zig build --build-file 05/build.zig run < 05/input && - zig build --build-file 07/build.zig run < 07/input + zig build --build-file 07/build.zig run < 07/input && + zig build --build-file 09/build.zig run < 09/input From 9d973154f37025cd54e8aedced399c3ad26f7f8f Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 9 Dec 2019 11:39:33 +0000 Subject: [PATCH 29/32] Day 9.2 --- 09/src/main.zig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/09/src/main.zig b/09/src/main.zig index 9b4a670..f8bf3c3 100644 --- a/09/src/main.zig +++ b/09/src/main.zig @@ -14,4 +14,9 @@ pub fn main() anyerror!void { try machine.run(); std.debug.warn("Day 9, Part 1: {}\n", try machine.readFromOutput()); + + try machine.writeToInput(2); // BOOST program in sensor boost mode + try machine.run(); + + std.debug.warn("Day 9, Part 2: {}\n", try machine.readFromOutput()); } From e81f3f6ab7234cc59bc3e5084d8d9779fb3ebb16 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Tue, 10 Dec 2019 21:14:32 +0000 Subject: [PATCH 30/32] Day 10.1 --- 10/build.zig | 14 ++++++++ 10/input | 25 ++++++++++++++ 10/src/main.zig | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 10/build.zig create mode 100644 10/input create mode 100644 10/src/main.zig diff --git a/10/build.zig b/10/build.zig new file mode 100644 index 0000000..6edf1ed --- /dev/null +++ b/10/build.zig @@ -0,0 +1,14 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("10", "src/main.zig"); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/10/input b/10/input new file mode 100644 index 0000000..c3f66aa --- /dev/null +++ b/10/input @@ -0,0 +1,25 @@ +#..#.#.#.######..#.#...## +##.#..#.#..##.#..######.# +.#.##.#..##..#.#.####.#.. +.#..##.#.#..#.#...#...#.# +#...###.##.##..##...#..#. +##..#.#.#.###...#.##..#.# +###.###.#.##.##....#####. +.#####.#.#...#..#####..#. +.#.##...#.#...#####.##... +######.#..##.#..#.#.#.... +###.##.#######....##.#..# +.####.##..#.##.#.#.##...# +##...##.######..##..#.### +...###...#..#...#.###..#. +.#####...##..#..#####.### +.#####..#.#######.###.##. +#...###.####.##.##.#.##.# +.#.#.#.#.#.##.#..#.#..### +##.#.####.###....###..##. +#..##.#....#..#..#.#..#.# +##..#..#...#..##..####..# +....#.....##..#.##.#...## +.##..#.#..##..##.#..##..# +.##..#####....#####.#.#.# +#..#..#..##...#..#.#.#.## diff --git a/10/src/main.zig b/10/src/main.zig new file mode 100644 index 0000000..f5e6584 --- /dev/null +++ b/10/src/main.zig @@ -0,0 +1,89 @@ +const std = @import("std"); + +// https://stackoverflow.com/a/328122 +fn isBetween(a: Point, b: Point, c: Point) bool { + const crossproduct = (c.y - a.y) * (b.x - a.x) - (c.x - a.x) * (b.y - a.y); + + // compare versus epsilon + if (std.math.absFloat(crossproduct) > std.math.f64_epsilon) return false; + + const dotproduct = (c.x - a.x) * (b.x - a.x) + (c.y - a.y) * (b.y - a.y); + if (dotproduct < 0.0) return false; + + const squaredlengthba = (b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y); + if (dotproduct > squaredlengthba) return false; + + return true; +} + +const Point = struct { + x: f64, + y: f64, + + fn eql(self: Point, other: Point) bool { + return self.x == other.x and self.y == other.y; + } +}; + +const Asteroid = struct { + p: Point, + visible: usize = 0, +}; + +const Asteroids = std.ArrayList(Asteroid); +const input = @embedFile("../input"); + +fn part1(asteroids: Asteroids) void { + for (asteroids.toSlice()) |*a| { + for (asteroids.toSlice()) |b| { + if (a.p.eql(b.p)) continue; + + // Check every asteroid to see if they fall between A and B + var blocked: bool = false; + for (asteroids.toSlice()) |c| { + if (a.p.eql(c.p) or b.p.eql(c.p)) continue; + + //var dist = distToSegment(a.p, b.p, c.p); + if (isBetween(a.p, b.p, c.p)) { + blocked = true; + break; + } + } + + // A can see B, so add it to A's score + if (!blocked) a.visible += 1; + } + } + + var best: usize = 0; + for (asteroids.toSlice()) |asteroid| { + if (asteroid.visible > best) best = asteroid.visible; + } + + std.debug.warn("Day 10, Part 1: {}\n", best); +} + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + + const alloc = &arena.allocator; + + var asteroids = Asteroids.init(alloc); + var lines = std.mem.separate(input, "\n"); + var y: usize = 0; + + while (lines.next()) |line| { + for (line) |byte, x| { + if (byte == '#') { + const px = @intToFloat(f64, x) + 0.5; + const py = @intToFloat(f64, y) + 0.5; + try asteroids.append(Asteroid{ .p = Point{ .x = px, .y = py } }); + } + } + + y += 1; + } + + part1(asteroids); +} From 48ca004a5390c0a04e4e69c9f3f2fd94e8383a6e Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 11 Dec 2019 20:40:09 +0000 Subject: [PATCH 31/32] Day 11, part 1, but horrible --- 11/build.zig | 16 ++++++ 11/input | 1 + 11/src/main.zig | 122 ++++++++++++++++++++++++++++++++++++++++ lib/intcode/intcode.zig | 6 +- 4 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 11/build.zig create mode 100644 11/input create mode 100644 11/src/main.zig diff --git a/11/build.zig b/11/build.zig new file mode 100644 index 0000000..0a9dbc2 --- /dev/null +++ b/11/build.zig @@ -0,0 +1,16 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("11", "src/main.zig"); + exe.setBuildMode(mode); + exe.addPackagePath("intcode", "../lib/intcode/intcode.zig"); + + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/11/input b/11/input new file mode 100644 index 0000000..4490d35 --- /dev/null +++ b/11/input @@ -0,0 +1 @@ +3,8,1005,8,304,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,1002,8,1,29,2,103,1,10,1,106,18,10,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,59,2,102,3,10,2,1101,12,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,88,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,101,0,8,110,2,108,9,10,1006,0,56,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,139,1,108,20,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,102,1,8,165,1,104,9,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,192,2,9,14,10,2,1103,5,10,1,1108,5,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,226,1006,0,73,1006,0,20,1,1106,11,10,1,1105,7,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,1001,8,0,261,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,1002,8,1,283,101,1,9,9,1007,9,1052,10,1005,10,15,99,109,626,104,0,104,1,21101,48062899092,0,1,21101,0,321,0,1105,1,425,21101,936995300108,0,1,21101,0,332,0,1106,0,425,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21102,209382902951,1,1,21101,379,0,0,1106,0,425,21102,179544747200,1,1,21102,390,1,0,1106,0,425,3,10,104,0,104,0,3,10,104,0,104,0,21102,1,709488292628,1,21102,1,413,0,1106,0,425,21101,0,983929868648,1,21101,424,0,0,1105,1,425,99,109,2,22101,0,-1,1,21102,40,1,2,21102,456,1,3,21101,446,0,0,1106,0,489,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,451,452,467,4,0,1001,451,1,451,108,4,451,10,1006,10,483,1102,0,1,451,109,-2,2105,1,0,0,109,4,1201,-1,0,488,1207,-3,0,10,1006,10,506,21102,1,0,-3,21202,-3,1,1,21201,-2,0,2,21101,0,1,3,21101,525,0,0,1105,1,530,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,553,2207,-4,-2,10,1006,10,553,21202,-4,1,-4,1105,1,621,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,572,0,1106,0,530,21201,1,0,-4,21101,0,1,-1,2207,-4,-2,10,1006,10,591,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,613,22101,0,-1,1,21101,0,613,0,106,0,488,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0 diff --git a/11/src/main.zig b/11/src/main.zig new file mode 100644 index 0000000..01f874c --- /dev/null +++ b/11/src/main.zig @@ -0,0 +1,122 @@ +const std = @import("std"); +const intcode = @import("intcode"); + +const boardX = 1024; +const boardY = 1024; + +const Point = struct { + x: usize, + y: usize, + + fn go(self: Point, d: Compass) Point { + var out = Point{.x = self.x, .y = self.y}; + + switch (d) { + .North => out.y -= 1, + .East => out.x += 1, + .South => out.y += 1, + .West => out.x -= 1, + } + + return out; + } +}; + +const Compass = enum(u8) { + North = 0, + East = 1, + South = 2, + West = 3, + + fn turn(self: Compass, direction: intcode.Word) Compass { + return switch (direction) { + 0 => self.widdershins(), + 1 => self.deasil(), + else => unreachable, + }; + } + + fn deasil(self: Compass) Compass { + if (self == .West) return .North; + + return @intToEnum(Compass, @enumToInt(self)+1); + } + + fn widdershins(self: Compass) Compass { + if (self == .North) return .West; + + return @intToEnum(Compass, @enumToInt(self)-1); + } +}; + +const Colour = enum(u8) { + Black = 0, + White = 1, +}; + +const Cell = struct { + colour: Colour, + touched: bool = false, +}; + +const Board = [boardY][boardX]Cell; + +fn runMachine(m: *intcode.Machine) void { + if (m.run()) {} else |err| { + std.debug.warn("Machine failed to run successfully: {}\n", err); + } +} + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + + const alloc = &arena.allocator; + + var board: Board = undefined; + for (board) |*row| { + for (row) |*cell| { + cell.* = Cell{.colour = .Black, .touched = false}; + } + } + + // Current state of the robot + var pos = Point{.x = boardX / 2, .y = boardY / 2}; + var direction = Compass.North; + + var program = try intcode.loadFromStdIn(alloc); + var machine = try intcode.Machine.init(alloc, program); + var robot = try std.Thread.spawn(&machine, runMachine); + + // Robot event loop + while (!machine.halted) { + // Feed it the colour at its current position + try machine.writeToInput(@enumToInt(board[pos.y][pos.x].colour)); + + // Read back instructions + var paintColour = try machine.readFromOutput(); + var turnDirection = try machine.readFromOutput(); + + // Paint + board[pos.y][pos.x].colour = @intToEnum(Colour, @intCast(u8, paintColour)); + board[pos.y][pos.x].touched = true; + + // Turn in the specified direction and move forward one square + direction = direction.turn(turnDirection); + pos = pos.go(direction); + + // Ugh. Give the other thread some time to decide to halt or not. + std.time.sleep(1000); + } + + robot.wait(); + + var touched: usize = 0; + for (board) |row| { + for (row) |cell| { + if (cell.touched) touched += 1; + } + } + + std.debug.warn("Day 11, Part 1: {}\n", touched); +} diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index c1a2fc6..aaf75aa 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -101,6 +101,8 @@ pub const Machine = struct { ip: usize = 0, + halted: bool = false, + input: CharDev, output: CharDev, @@ -257,9 +259,7 @@ pub const Machine = struct { self.rb += self.__read(0, insn.modes[0]); }, - .END => { - // std.debug.warn("{}: ended\n", self.idx); - }, + .END => self.halted = true, }; // Only modify IP if the instruction itself has not From fc21396bc86bc0f706225f4f6e1d8294d344ca53 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 11 Dec 2019 20:50:11 +0000 Subject: [PATCH 32/32] Day 11, part 2 --- 11/src/main.zig | 52 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/11/src/main.zig b/11/src/main.zig index 01f874c..2580b8e 100644 --- a/11/src/main.zig +++ b/11/src/main.zig @@ -1,8 +1,8 @@ const std = @import("std"); const intcode = @import("intcode"); -const boardX = 1024; -const boardY = 1024; +const boardX = 155; +const boardY = 100; const Point = struct { x: usize, @@ -67,11 +67,8 @@ fn runMachine(m: *intcode.Machine) void { } } -pub fn main() anyerror!void { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - - const alloc = &arena.allocator; +fn run(alloc: *std.mem.Allocator, program: []intcode.Word, part1: bool) !void { + const part2 = !part1; var board: Board = undefined; for (board) |*row| { @@ -84,8 +81,11 @@ pub fn main() anyerror!void { var pos = Point{.x = boardX / 2, .y = boardY / 2}; var direction = Compass.North; - var program = try intcode.loadFromStdIn(alloc); + // Start on a white panel in part 2 + if (part2) board[pos.y][pos.x].colour = .White; + var machine = try intcode.Machine.init(alloc, program); + defer machine.deinit(); var robot = try std.Thread.spawn(&machine, runMachine); // Robot event loop @@ -111,12 +111,36 @@ pub fn main() anyerror!void { robot.wait(); - var touched: usize = 0; - for (board) |row| { - for (row) |cell| { - if (cell.touched) touched += 1; + if (part1) { + var touched: usize = 0; + for (board) |row| { + for (row) |cell| { + if (cell.touched) touched += 1; + } + } + + std.debug.warn("Day 11, Part 1: {}\n", touched); + } else { + for (board) |row| { + for (row) |cell| { + switch (cell.colour) { + .Black => std.debug.warn(" "), + .White => std.debug.warn("#"), + } + } + std.debug.warn("\n"); } } - - std.debug.warn("Day 11, Part 1: {}\n", touched); +} + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + + const alloc = &arena.allocator; + + var program = try intcode.loadFromStdIn(alloc); + + try run(alloc, program, true); + try run(alloc, program, false); }