From 9864e914ba0b1a3524f6d33680f78b410f9a9ee1 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sat, 7 Dec 2019 22:41:14 +0000 Subject: [PATCH] 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