diff --git a/2019/.gitignore b/2019/.gitignore new file mode 100644 index 0000000..2040c29 --- /dev/null +++ b/2019/.gitignore @@ -0,0 +1 @@ +zig-cache diff --git a/2019/01/build.zig b/2019/01/build.zig new file mode 100644 index 0000000..2ab06e7 --- /dev/null +++ b/2019/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/2019/01/input b/2019/01/input new file mode 100644 index 0000000..dde704b --- /dev/null +++ b/2019/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/2019/01/src/main.zig b/2019/01/src/main.zig new file mode 100644 index 0000000..b357db7 --- /dev/null +++ b/2019/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); +} + diff --git a/2019/02/build.zig b/2019/02/build.zig new file mode 100644 index 0000000..1c55192 --- /dev/null +++ b/2019/02/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("part-02", "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/2019/02/input b/2019/02/input new file mode 100644 index 0000000..d58f471 --- /dev/null +++ b/2019/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/2019/02/src/main.zig b/2019/02/src/main.zig new file mode 100644 index 0000000..8bf61be --- /dev/null +++ b/2019/02/src/main.zig @@ -0,0 +1,56 @@ +const std = @import("std"); +const intcode = @import("intcode"); + +fn run(alloc: *std.mem.Allocator, program: []intcode.Word, noun: intcode.Word, verb: intcode.Word) !intcode.Word { + program[1] = noun; + program[2] = verb; + + var machine = try intcode.Machine.Run(alloc, program); + defer machine.deinit(); + + return machine.memory[0]; +} + +fn runCopy(alloc: *std.mem.Allocator, program: []intcode.Word, noun: intcode.Word, verb: intcode.Word) !intcode.Word { + return run(alloc, program, noun, verb); +} + +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); + + // Part 1 + 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: []intcode.Word = try alloc.alloc(intcode.Word, program.len); + var done: bool = false; + var noun: intcode.Word = 0; + var verb: intcode.Word = 0; + + std.debug.warn("Day 2, Part 2: "); + while (!done) { + std.mem.copy(intcode.Word, memory, program); + const result = try run(alloc, memory, noun, verb); + + // Too high: 250800 (noun=33, verb=76) + if (result == 19690720) { + std.debug.warn("noun={} verb={}\n", noun, verb); + done = true; + } + + noun += 1; + if (noun > 100) { + noun = 0; + verb += 1; + + if (verb > 100) { + std.debug.warn("failed!\n"); + } + } + } +} diff --git a/2019/03/build.zig b/2019/03/build.zig new file mode 100644 index 0000000..890999c --- /dev/null +++ b/2019/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/2019/03/input b/2019/03/input new file mode 100644 index 0000000..c0eaa6c --- /dev/null +++ b/2019/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/2019/03/src/main.zig b/2019/03/src/main.zig new file mode 100644 index 0000000..33a6d3c --- /dev/null +++ b/2019/03/src/main.zig @@ -0,0 +1,160 @@ +const std = @import("std"); + +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); + +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 Step = struct { + d: Direction, + l: i32, + + 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(i32, in[1..in.len], 10), + }; + } +}; + +const World = struct { + entries: Points, + ticks: i32, + x: i32, + y: i32, + + pub fn step(self: *World, in: Step) void { + std.debug.warn("Step {}: {}\n", self.ticks, in); + + var i: i32 = 0; + switch (in.d) { + .Up => { + while (i < in.l) : (i += 1) { + self.y -= 1; + self.fill(); + } + }, + .Down => { + while (i < in.l) : (i += 1) { + self.y += 1; + self.fill(); + } + }, + .Left => { + while (i < in.l) : (i += 1) { + self.x -= 1; + self.fill(); + } + }, + .Right => { + while (i < in.l) : (i += 1) { + self.x += 1; + self.fill(); + } + }, + } + } + + fn fill(self: *World) void { + self.ticks += 1; + + const point = Point{ .X = self.x, .Y = self.y, .Steps = self.ticks }; + std.debug.warn("\t{}\n", point); + self.entries.appendAssumeCapacity(point); + } +}; + +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) + 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(); + + const alloc = &arena.allocator; + const file = std.io.getStdIn(); + const stream = &file.inStream().stream; + + var world: World = World{ + .entries = try Points.initCapacity(alloc, maxEntries), + .ticks = 0, + .x = 0, + .y = 0, + }; + + // Line 1 + for (try getLine(stream)) |item| { + world.step(item); + } + + // reset to origin + const entriesA = world.entries; + world.entries = try Points.initCapacity(alloc, maxEntries); + world.ticks = 0; + world.x = 0; + world.y = 0; + + // Line 2 + for (try getLine(stream)) |item| { + world.step(item); + } + + const entriesB = world.entries; + + 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, b, manhattan(a.X, a.Y), a.Steps + b.Steps); + } + } + } +} diff --git a/2019/04/build.zig b/2019/04/build.zig new file mode 100644 index 0000000..843c820 --- /dev/null +++ b/2019/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/2019/04/src/main.zig b/2019/04/src/main.zig new file mode 100644 index 0000000..e524fad --- /dev/null +++ b/2019/04/src/main.zig @@ -0,0 +1,53 @@ +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). + +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; + + 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]; +} + +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 + 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 count1: i32 = 0; + var count2: i32 = 0; + var i: i32 = first; + + 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)) { + count2 += 1; + } + } + } + + //std.debug.warn(" 012345\n"); + + std.debug.warn("Part 1: matches: {}\n", count1); + std.debug.warn("Part 2: matches: {}\n", count2); +} diff --git a/2019/05/build.zig b/2019/05/build.zig new file mode 100644 index 0000000..c228b31 --- /dev/null +++ b/2019/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/2019/05/input b/2019/05/input new file mode 100644 index 0000000..2109937 --- /dev/null +++ b/2019/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/2019/05/src/main.zig b/2019/05/src/main.zig new file mode 100644 index 0000000..9d301ed --- /dev/null +++ b/2019/05/src/main.zig @@ -0,0 +1,29 @@ +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 p1 = try intcode.loadFromStdIn(alloc); + 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); + + try m1.writeToInput(1); // Air conditioner unit + try m1.run(); + + var out: intcode.Word = 0; + 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()); +} diff --git a/2019/06/build.zig b/2019/06/build.zig new file mode 100644 index 0000000..7300f55 --- /dev/null +++ b/2019/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/2019/06/input b/2019/06/input new file mode 100644 index 0000000..2364732 --- /dev/null +++ b/2019/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/2019/06/src/main.zig b/2019/06/src/main.zig new file mode 100644 index 0000000..6e7b753 --- /dev/null +++ b/2019/06/src/main.zig @@ -0,0 +1,138 @@ +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 NodeList = std.ArrayList(*Node); +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] == ')'); + + 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; + } +} + +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(); + + const alloc = &arena.allocator; + const file = std.io.getStdIn(); + const stream = &file.inStream().stream; + + var links = try parse(alloc, stream); + + // 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.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); + + // 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); + } +} diff --git a/2019/07/build.zig b/2019/07/build.zig new file mode 100644 index 0000000..16cb95e --- /dev/null +++ b/2019/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/2019/07/input b/2019/07/input new file mode 100644 index 0000000..5828532 --- /dev/null +++ b/2019/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/2019/07/src/main.zig b/2019/07/src/main.zig new file mode 100644 index 0000000..9fc7d70 --- /dev/null +++ b/2019/07/src/main.zig @@ -0,0 +1,344 @@ +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]intcode.Word{ + .{ 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 }, +}; + +const perm2 = [120][5]intcode.Word{ + .{ 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: []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(intcode.Word, 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(); + + const alloc = &arena.allocator; + var program = try intcode.loadFromStdIn(alloc); + + // 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(intcode.Word, 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]; + + 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 + machines[0].input = machines[4].output; + + std.debug.warn("Day 7, Part 2: {}\n", try run(program, &machines, perm2)); +} diff --git a/2019/08/build.zig b/2019/08/build.zig new file mode 100644 index 0000000..773a3c1 --- /dev/null +++ b/2019/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/2019/08/input b/2019/08/input new file mode 100644 index 0000000..cf062aa --- /dev/null +++ b/2019/08/input @@ -0,0 +1 @@ +222222222222220222122222220022222222222202222222222222220202222222222201212222120222222220222102222212222222222012222222002222221222222202222220022220222222222222222222122222220222222222022202222222222222220222222222222222202222221222222221222202222212222222222102222222202222220222222222222221222220222222222222221222122222221022222222222212222222222222221212222222222212222202220222220220222112222202222222222122222222122222220222222202222222222222222222222222221222122222221022222222122222222222222222221102222222222201202212021222220220222212222202222222222002222222202222220222222202222221222222222222222222221222222222222122222222022202222222222222220202222222222200202202121222222221222202222222222222222022222222012202220222222202222222122222222222222222222222222222222022222222122212222222222222220112222222222221222202221222221221222122222222222222222112222222212212222222222102222222222221222222222222220222022222220022222222022222222222222222221102222222222201222212020222222222222002222202222222222022222022002012222222222012222220222222222222222222221222222222221122222222220212022222222222220012222222222200202212220222222220222212212202222222222002222122002212222222222222222220222221222222222222220222222222220222222222020212022222222222220002222222222211222222022222221221222202222222222222222002222022212102221222222012222220122222222222222222220222122222221122222222120212022222222222022012222222222200202222221222220222202102202202222222222202222022222022220222222212222220222222222222222222220222022222222122222222220212222222222222222002222222222221202212220222221221202012222222222222222022222122202002221222220002222221222220222222222222221222222222221222222222020212222222222222222102222222222200202212220222222220202112202212222220222012222222212112221222222212222220022220222222222222220222022222221122222222120212122222222222020212222222222200002202221222220222212222202222222220222212222222001012221222220202222120122221222222222222221222202222222122222222220222022222222222022102222222222221222222020222221222212012202212222221222112222122011012221222221222222211022220222222222222220222122222122122222222221222122222222222021112222222222220002212221222221220222122202202222221222002222122020012221222220112222111222222212222222222220222002222220122222222221222222222222222021222222222222201012212020222220220222002222202222222222202222122121212220222220102222002122222202222222222222222022222222122222222020212222222222222222202222222222211002202121222221221222102212202222221222012222022202122220222221222220001022221202222222222221222222222220122222222121222222222222222021122222222222202012211120222221220202102222212222221222002222122110012222222222212222120222221222222222222220222112222222022222222222212122222222222120202222222222210012222220222221222202112212202222221222222222022022122220222220222222000022221212222222222221222012222020222222222120212022222222222120202222222222202222202220222221221202012002212222222222122222222012102220222220012222121122222202222222222222222002222022222222222120202022222222222121212222222222202122222220222222221202002102222222220222212222122212022221222220012221220022222212222221222221222012222122222220222121212022222222020120222222222222222202200120220220222212112102212222222222212222122120002221222222022221101122221222222220222222222122222222122220222221212022222222020220102222222222222112221122220222221202212002202222222222222222022022212222222221012222001122220212222220222220222002222121222222222120222022222222020120222222222222222002221120221221221222202222202222222222012222022201122221222220112221002222221222222220222221222222222122122221222120222022222222022020102222222222222222211122222222221212012202212222222222002222222002222220222221112222011122220222222222222220222202222122022220222022222220222222021222202222222222210222210021220221222222022212222222221222212222122012012222222220122221220222121202222220212221222122222120022221222122222122222222121022212222222222220012222020221220220202212122222222222222222222022210202221222220212220220222220222222220202221222222222021222221222120212220222222121120202222222222220122212121221221221212102122202222221222212222122101102221222222212222200222021212222221222222222022222022022221222022222220222222121220122222222222202222221122220222220222112102212212222222022222222200112222222222102221202222220222222221202222222212222210122222222220222220222222121221212222222222220110222022201222222222202012212222220222112222222111222220222220112221101222021212222221202221222112222022122222222121222121222222021120122222222222200110102121210221222222112222202212220222202222022101102221222220102221110122101212222121212221222112222011020220222022202022222222120020222222222222212212011020210221221222202102222222220222222222222111122220222221202221121122022202222020222221222202222211222220222021202222222222220220122222202222210222122120221222221202012012222222222222012222122100212221222221002221212022000212222221202221222222222100020222222020222120222222122121212222212222212122220120212220222212012012222022221222012222022001122220222221102221012222220202222220202222222122222012220220222022222121222222020022102222222222210220120020220221222212212002212102220222202222122000012222222221122222200022221202222122212222222212222201022221222021212121222212120222112222222222210001002122220220222212222012222112121222222222122020012220222222002222101022210212222022212220222122222000021222222122212220222222122222202222202222202112221020210222202202012212212122121222012222222020022221222222212220010222122212222221222221222102222220222222221012202221122212121021202222222222222210221122211220200212212102202122221222022222022211202221222222002220011022001222202120212220222212222110112202220111222222022222120022102222202222212102012221220221210222012122212012221222112222222120202222222222022221101022011202202220222221222202222210200201221012202120122212022220112222212222201120121121220222222212212022222002220222012222022200122220222221122221112022120222222221222222222212222212001201222112222121222202120122012222222222221011200120210221210212012022222002220222012222122220122221222221122221002022202212202122222220222202222121221210121010222222122212220020222222202222222000121021210220222212112022222202020222012222122000002220222222122220020122101212201221212222222212222010220220022202202120122222122221122222212222210022211222210222202222212002222002220222222222022121022221222220012222102222211212202221222220222222222011220221221012212222222212020021212222202222221201020121212221210212202112222102020222002222122202122221222221112221200122121202210122202222222202222211110221021022212122222212020122022222212222211022212220212220211202222222222212022222002222222001022220222222212222020222220212221021212222222122222101001212122102202121222222020222222222212222220101000222222222212212002022222002022222002222022220002120222221122221112022002222211122202222222012222122220211222222212122122222022222112222202222212122011021212222211212022202202202122222022222122120012220222221102220102022001202202222202220222222222210112002022120222221022202221120202222212222220212221222211220202212012222202002020222102222022211012020222221012220201022010202222022222220222112222022120100020120212020022212022221022222212222221110112020210221212222112102202022222222222222022210012021222220202222022122220202220221222222222202222120020002222212212022222202121022222222202222221022120021200220220212012122212122020222002222022200212120222222012222012022021222200022202221222012222101001020020221202122122222122220012222002221211221111021222221211202112122222122220222202222222011212120222222222221100222210202200020222222222012222100112002021121222122022222022122022222102220220221102121202221202202112112202112221222122222022022122221222220222220110222021222201221212221222022222102110000020201222020022202020022222222112222222221221122221221200212112122222002120221012222022212102222222220212222021022022212202022202222222102222020120011120022222122222202121221012222202220201122102120201220221212202002202122220221202222022110022121222220112221021022121212211222202222222102222200220200221012210221222222120102002222102222211221201020211221210212022222202202221220102222222020212022222220102221121222020212201220202220222112222211102010021112202222122222122201222222122220212122001221201221212212012222202112221222122222122201022222222222202220110122112222212121212221222222222220121120120010200120022202122122212222112220222120002222222220220222112212212102220222112222022201122022222221022222212122022202212221222221222112222110111112220220210120222202020100022222022022221202011020220220220222212102222112022220122222222220202220222222112221022122221202210122212220222102220021000202022120221120022222221221022222122120201120111022210222220222202212212112020221022222022001122022222220022220210122111202212220202220222202222110222201120111222121122222020210102222022120210100101020212221221222112102212112220222012222122202122220222222022220122220220222212122202222222112221111102210021002202020122222221100112222212122210200022120202222220222002022222222222222112222122000112020222222112221102021002202200020222220222022220012001111120001220020222202121011212222122202212120020222221220202212202002202102220222122222222001002222222220212221120220111012220221222222222222222200010011222211211121222202022010002222222022220012100120211222211212222012202022220220012222222202102120222221110202212120112202202222222222022212222212001020121020211221222222020222212222012110200100102122200222201212122202022012022221122222122112102011222220202220221022122222210120202222222112222000202021220100220221222202122110202222102212200210221021201222202222212202022022220220122212022100202111222222022200101020110201220020222221122002221212212112021220220221222212222220002222102200211000120121220222212202212022212022221221202202022111002012222221122201022222022002002020222221122022221220102222222201201122122222122020012222212100212200202221212221210212122112022122220221122212022100112020222221000210211121212210020220202221222012220012200211120102212122222202022122202222122120202010211020200220222222102222112222022220222202022201200110222221200212222221110200012221222221222222221111102021120000200221222202020001222222022010222212121122212220202202112222022122120220222202022021220021222220210202001220012012220222212221022112221200122222022011210222122212020000012222002200220202210121202221202202102202102112220222102212022122000222222220112202200121222112111022202220122002221020000200121011220220222212222010002222202120222212112022202221222222212122122112220220122202022102200121222220001210122220010202200221002221122112221021112212020111201122122212120102022222212010212102201222220222112222022202112002120221112202022222112210222222102211220222111101121222012220222002221211111022220010212020222222220220102222012222200010200121200222110212022202002202121222010202122202112120222220001211002120222100010221102021122222222211101021221001200121022212020101002222012122201212011222111221002202112012002112022221221222222000212102222220100201120122210021012021122022022012220102221221121211200120122212020001202222122000211021201121120220112222122112202212222220122222222121201110222222122210102121102111200220102221022012221002221110022022201011122222022102012222002211221221202220221221210212102102222202222222011222222001201012222220222212010122112202010221212221122212221122200002120000020200022212021012002220002110200112102121121221201222002212102202120222121202122012211212222220210200022021201102000022102121022002220022122122121222221100122212022002022122002102200222222220212221001222222102102212120202012212122022221112222221210211200121211211222122112221022102221012122122220010102011222222121120112220122102222121121020221221010222122202122112121211202222122100221010222220102222220122010200011120122220222102221221221121022102000001122222221100222121102122211012212221120220212202212112202002020211022202022221211000222221111220222122212102110121122022122202222120010121020121210101222212120101012120212211200120120122102221111222122112112122021221120212222201101011222221112222020120011022011221212120022102222110022220021012212210022212022202002222112202202100200120200222201212002022022112122221102202122221121111222220111210101121122021021120112122022112220111202102222021020020122222120110122222222111200022002120020221212212012022022022121210212212122201112202222222202111011021202222101121112222122202220020221212221201020211022202222211202120212121201120111120102222200202222012012022121202101212222000200111222220211111102122100212222022122120222012222200100220020220022212222222022121202021202122211022101022200220020222022112012022120202101212022012100211222221111021211120111021011120102021022102222112111100022012112111122222020121012022012200201002000022101221201212012012112102120200022202022021010212222221211202121121021012212120112220021102220111102011022221220110222222222102212221112021222120011222211222020222222002122122021200102202222102011112222220202110202121021201000222102120020112220120110202222210020101022202221012012021102112211100100020101221210202222112102112120220002212122211022120222220122200210222210111212222122222120212021102112122220212011220222212121112212220102111201201002122222220220202222212102202120211201202222202010211222222011011120100212110211220112020020102021120202222222100201120022202222020112021002012221120201221212221110222002022202222020202122212122210110011222222101201210111211101022222002120221122020210112112022220101102222212120212012020102201212010210221111222110222212012002012220221011212022112110012222222212021212100002102202122012020121112021002201222021221220112122212021120102120002212210121200222221222212202222022022100022201010202222112001210222212220201201001021110112122102120001122222221010102121221002120222212022212112221202200211120202022202221011212022012122101021220100202122212111011222200122211101012121111111122112221200122022211101021221020201222022202220221112122022121212200001221222221000222212002212212122010212222122122101212222220121020020111100000110122102120122202220201221011222212020221220212022221102221202212202121101122010220001212012212112201021211000022222220202100222211112020021221121122202121022222022222220102022002122120211011220212020021022222102022222210012222101021222212012012122111121110120122122202001101222220020112021102002110210221212220002022221122001011220212000021222212221102222122012110201020121020100122222202022222202211121110212102022012122112222100101202010201121110010220102222202022220111201122021000221102222212220111202220122122202021202120021221021212212102102102122222212222222212201122222202021210110222112011121221012020001222020022201201101210010202020202000102222120022010220201121220122221122212112012112211120211200202022202120021222021222012112012110120010012210212121121201011020012122110012202102011101220220212200121020000101100100111012010120120000122100110011200110100002001011101102110002120111 diff --git a/2019/08/src/main.zig b/2019/08/src/main.zig new file mode 100644 index 0000000..2ca178b --- /dev/null +++ b/2019/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); +} diff --git a/2019/09/build.zig b/2019/09/build.zig new file mode 100644 index 0000000..5cfd066 --- /dev/null +++ b/2019/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/2019/09/input b/2019/09/input new file mode 100644 index 0000000..10cef79 --- /dev/null +++ b/2019/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/2019/09/src/main.zig b/2019/09/src/main.zig new file mode 100644 index 0000000..f8bf3c3 --- /dev/null +++ b/2019/09/src/main.zig @@ -0,0 +1,22 @@ +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()); + + try machine.writeToInput(2); // BOOST program in sensor boost mode + try machine.run(); + + std.debug.warn("Day 9, Part 2: {}\n", try machine.readFromOutput()); +} diff --git a/2019/10/build.zig b/2019/10/build.zig new file mode 100644 index 0000000..6edf1ed --- /dev/null +++ b/2019/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/2019/10/input b/2019/10/input new file mode 100644 index 0000000..c3f66aa --- /dev/null +++ b/2019/10/input @@ -0,0 +1,25 @@ +#..#.#.#.######..#.#...## +##.#..#.#..##.#..######.# +.#.##.#..##..#.#.####.#.. +.#..##.#.#..#.#...#...#.# +#...###.##.##..##...#..#. +##..#.#.#.###...#.##..#.# +###.###.#.##.##....#####. +.#####.#.#...#..#####..#. +.#.##...#.#...#####.##... +######.#..##.#..#.#.#.... +###.##.#######....##.#..# +.####.##..#.##.#.#.##...# +##...##.######..##..#.### +...###...#..#...#.###..#. +.#####...##..#..#####.### +.#####..#.#######.###.##. +#...###.####.##.##.#.##.# +.#.#.#.#.#.##.#..#.#..### +##.#.####.###....###..##. +#..##.#....#..#..#.#..#.# +##..#..#...#..##..####..# +....#.....##..#.##.#...## +.##..#.#..##..##.#..##..# +.##..#####....#####.#.#.# +#..#..#..##...#..#.#.#.## diff --git a/2019/10/src/main.zig b/2019/10/src/main.zig new file mode 100644 index 0000000..f5e6584 --- /dev/null +++ b/2019/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); +} diff --git a/2019/11/build.zig b/2019/11/build.zig new file mode 100644 index 0000000..0a9dbc2 --- /dev/null +++ b/2019/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/2019/11/input b/2019/11/input new file mode 100644 index 0000000..4490d35 --- /dev/null +++ b/2019/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/2019/11/src/main.zig b/2019/11/src/main.zig new file mode 100644 index 0000000..2580b8e --- /dev/null +++ b/2019/11/src/main.zig @@ -0,0 +1,146 @@ +const std = @import("std"); +const intcode = @import("intcode"); + +const boardX = 155; +const boardY = 100; + +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); + } +} + +fn run(alloc: *std.mem.Allocator, program: []intcode.Word, part1: bool) !void { + const part2 = !part1; + + 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; + + // 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 + 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(); + + 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"); + } + } +} + +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); +} diff --git a/2019/README.md b/2019/README.md new file mode 100644 index 0000000..3ac0bff --- /dev/null +++ b/2019/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) diff --git a/2019/lib/intcode/intcode.zig b/2019/lib/intcode/intcode.zig new file mode 100644 index 0000000..aaf75aa --- /dev/null +++ b/2019/lib/intcode/intcode.zig @@ -0,0 +1,437 @@ +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); + + 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(Word, trimmed, 10); + i += 1; + } + + std.debug.warn("\n"); + + return program[0..program.len]; +} + +pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]Word { + const file = std.io.getStdIn(); + const stream = &file.inStream().stream; + + return loadFromStream(alloc, stream); +} + +const Opcode = enum(u8) { + ADD = 1, + MULT = 2, + IN = 3, + OUT = 4, + JNZ = 5, + JZ = 6, + LT = 7, + EQ = 8, + RBO = 9, + END = 99, +}; + +const Mode = enum(u8) { + Position = 0, + Immediate = 1, + Relative = 2, +}; + +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: Word) !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, + .JNZ => 3, + .JZ => 3, + .LT => 4, + .EQ => 4, + .RBO => 2, + .END => 1, + }; + } + + pub fn halt(self: Instruction) bool { + return self.op == .END; + } +}; + +pub const Machine = struct { + alloc: *std.mem.Allocator, + idx: usize = 0, // handy for debugging + + memory: []Word, + rb: Word = 0, + + ip: usize = 0, + + halted: bool = false, + + input: CharDev, + output: CharDev, + + pub fn Run(alloc: *std.mem.Allocator, program: []Word) anyerror!Machine { + var machine = try init(alloc, program); + + try machine.run(); + + return machine; + } + + 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 = memory, + .input = try std.os.pipe(), + .output = try std.os.pipe(), + }; + } + + pub fn run(self: *Machine) anyerror!void { + while (try self.step()) {} + } + + 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]); + std.os.close(self.output[1]); + } + + pub fn readFromInput(self: *Machine) !Word { + return self.__in(self.input); + } + + pub fn writeToInput(self: *Machine, val: Word) !void { + return self.__out(self.input, val); + } + + pub fn readFromOutput(self: *Machine) !Word { + return self.__in(self.output); + } + + pub fn writeToOutput(self: *Machine, val: Word) !void { + return self.__out(self.output, val); + } + + fn __in(self: *Machine, dev: CharDev) !Word { + const fd = dev[0]; // Read from the pipe + 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 == 8); // TODO: handle partial reads + + return std.mem.readIntNative(Word, &store); + } + + fn __out(self: *Machine, dev: CharDev, val: Word) !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); + } + + /// 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) Word { + const immediate = self.memory[self.ip + parameter + 1]; + + 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, mode: Mode, value: Word) void { + const dest = self.__read(parameter, .Immediate); + + 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 { + const insn = try Instruction.decode(self.memory[self.ip]); + const start_ip = self.ip; + + const opcode = switch (insn.op) { + .ADD => { + const a = self.__read(0, insn.modes[0]); + const b = self.__read(1, insn.modes[1]); + + 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, insn.modes[2], a * b); + }, + + .IN => { + self.__write(0, insn.modes[0], try self.readFromInput()); // blocking read + }, + + .OUT => { + try self.writeToOutput(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, insn.modes[2], 1); + } else { + self.__write(2, insn.modes[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, insn.modes[2], 1); + } else { + self.__write(2, insn.modes[2], 0); + } + }, + + .RBO => { + self.rb += self.__read(0, insn.modes[0]); + }, + + .END => self.halted = true, + }; + + // Only modify IP if the instruction itself has not + if (self.ip == start_ip) self.ip += insn.size(); + + return !insn.halt(); + } +}; + +const assert = std.debug.assert; +const test_allocator = std.heap.page_allocator; + +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, 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, 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, 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, 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, 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, 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); + + 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); +} diff --git a/2019/run-intcodes b/2019/run-intcodes new file mode 100755 index 0000000..c874ac0 --- /dev/null +++ b/2019/run-intcodes @@ -0,0 +1,6 @@ +#!/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 build --build-file 09/build.zig run < 09/input