Switch to using OS pipes
This commit is contained in:
@@ -18,16 +18,12 @@ pub fn main() anyerror!void {
|
|||||||
try m1.run();
|
try m1.run();
|
||||||
|
|
||||||
var out: i32 = 0;
|
var out: i32 = 0;
|
||||||
while (m1.readFromOutput(false)) |item| {
|
while (out == 0) : (out = try m1.readFromOutput()) {}
|
||||||
out = item;
|
|
||||||
} else |err| {
|
|
||||||
std.debug.assert(err == std.os.ReadError.WouldBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
std.debug.warn("Day 5, Part 1: {}\n", out);
|
std.debug.warn("Day 5, Part 1: {}\n", out);
|
||||||
|
|
||||||
try m2.writeToInput(5); // Thermal radiator controller
|
try m2.writeToInput(5); // Thermal radiator controller
|
||||||
try m2.run();
|
try m2.run();
|
||||||
|
|
||||||
std.debug.warn("Day 5, Part 2: {}\n", try m2.readFromOutput(false));
|
std.debug.warn("Day 5, Part 2: {}\n", try m2.readFromOutput());
|
||||||
}
|
}
|
||||||
|
@@ -136,42 +136,74 @@ pub fn main() anyerror!void {
|
|||||||
// 5 intcode computers act as the amps
|
// 5 intcode computers act as the amps
|
||||||
var machines: [5]intcode.Machine = undefined;
|
var machines: [5]intcode.Machine = undefined;
|
||||||
|
|
||||||
|
// Allocate memory once only.
|
||||||
|
for (machines) |*machine| {
|
||||||
|
machine.alloc = alloc;
|
||||||
|
machine.memory = try alloc.alloc(i32, program.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now wire up the machines correctly. The output of each machine should be
|
||||||
|
// the input to the next.
|
||||||
|
const pipes: [6]intcode.CharDev = .{
|
||||||
|
try std.os.pipe(),
|
||||||
|
try std.os.pipe(),
|
||||||
|
try std.os.pipe(),
|
||||||
|
try std.os.pipe(),
|
||||||
|
try std.os.pipe(),
|
||||||
|
try std.os.pipe(),
|
||||||
|
};
|
||||||
|
|
||||||
|
machines[0].input = pipes[0];
|
||||||
|
machines[0].output = pipes[1];
|
||||||
|
|
||||||
|
machines[1].input = machines[0].output;
|
||||||
|
machines[1].output = pipes[2];
|
||||||
|
|
||||||
|
machines[2].input = machines[1].output;
|
||||||
|
machines[2].output = pipes[3];
|
||||||
|
|
||||||
|
machines[3].input = machines[2].output;
|
||||||
|
machines[3].output = pipes[4];
|
||||||
|
|
||||||
|
machines[4].input = machines[3].output;
|
||||||
|
machines[4].output = pipes[5];
|
||||||
|
|
||||||
// 120 phase permutations. Find the highest.
|
// 120 phase permutations. Find the highest.
|
||||||
var max: i32 = 0;
|
var max: i32 = 0;
|
||||||
for (perm1) |inputs| {
|
for (perm1) |inputs| {
|
||||||
for (machines) |*machine| {
|
for (machines) |*machine| {
|
||||||
var copy = try alloc.alloc(i32, program.len);
|
std.mem.copy(i32, machine.memory, program);
|
||||||
std.mem.copy(i32, copy, program);
|
machine.ip = 0;
|
||||||
|
|
||||||
machine.* = try intcode.Machine.init(alloc, copy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase input
|
// Phase inputs
|
||||||
for (inputs) |input, i| {
|
for (inputs) |input, i| {
|
||||||
try machines[i].writeToInput(input);
|
try machines[i].writeToInput(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
// amplifier input
|
// Provide starting value of 0
|
||||||
for (machines) |*machine, i| {
|
try machines[0].writeToInput(0);
|
||||||
var ampInput: i32 = 0;
|
|
||||||
if (i > 0) ampInput = try machines[i - 1].readFromOutput(false);
|
|
||||||
|
|
||||||
try machine.writeToInput(ampInput);
|
// run the program
|
||||||
|
for (machines) |*machine, i| {
|
||||||
try machine.run();
|
try machine.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
const final = try machines[4].readFromOutput(false);
|
const final = try machines[4].readFromOutput();
|
||||||
if (final > max)
|
if (final > max)
|
||||||
max = final;
|
max = final;
|
||||||
|
|
||||||
// Don't forget to free everything!
|
// Don't forget to free everything!
|
||||||
for (machines) |*machine, i| {
|
for (machines) |*machine, i| {
|
||||||
alloc.free(machine.memory);
|
alloc.free(machine.memory);
|
||||||
machine.deinit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std.debug.warn("Day 7, Part 1: {}\n", max);
|
std.debug.warn("Day 7, Part 1: {}\n", max);
|
||||||
|
|
||||||
// In part 2, the machines need to be wired into a feedback loop
|
// 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;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const CharDev = std.atomic.Queue(i32);
|
// We're using pipes as character devices
|
||||||
|
pub const CharDev = [2]i32;
|
||||||
|
|
||||||
pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 {
|
pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 {
|
||||||
var program = try alloc.alloc(i32, 1024);
|
var program = try alloc.alloc(i32, 1024);
|
||||||
@@ -111,8 +112,8 @@ pub const Machine = struct {
|
|||||||
return Machine{
|
return Machine{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
.memory = program,
|
.memory = program,
|
||||||
.input = CharDev.init(),
|
.input = try std.os.pipe(),
|
||||||
.output = CharDev.init(),
|
.output = try std.os.pipe(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,47 +122,43 @@ pub const Machine = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Machine) void {
|
pub fn deinit(self: *Machine) void {
|
||||||
// TODO
|
std.os.close(self.input[0]);
|
||||||
|
std.os.close(self.input[1]);
|
||||||
|
std.os.close(self.output[0]);
|
||||||
|
std.os.close(self.output[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readFromInput(self: *Machine, blocking: bool) !i32 {
|
pub fn readFromInput(self: *Machine) !i32 {
|
||||||
return self.__in(&self.input, blocking);
|
return self.__in(self.input);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeToInput(self: *Machine, val: i32) !void {
|
pub fn writeToInput(self: *Machine, val: i32) !void {
|
||||||
return self.__out(&self.input, val);
|
return self.__out(self.input, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readFromOutput(self: *Machine, blocking: bool) !i32 {
|
pub fn readFromOutput(self: *Machine) !i32 {
|
||||||
return self.__in(&self.output, blocking);
|
return self.__in(self.output);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeToOutput(self: *Machine, val: i32) !void {
|
pub fn writeToOutput(self: *Machine, val: i32) !void {
|
||||||
return self.__out(&self.output, val);
|
return self.__out(self.output, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn __in(self: *Machine, dev: *CharDev, blocking: bool) !i32 {
|
inline fn __in(self: *Machine, dev: CharDev) !i32 {
|
||||||
var node = dev.get();
|
const fd = dev[0]; // Read from the pipe
|
||||||
|
var store: [4]u8 = undefined;
|
||||||
|
|
||||||
if (node == null) {
|
var n = try std.os.read(fd, &store);
|
||||||
if (!blocking) return std.os.ReadError.WouldBlock;
|
std.debug.assert(n == 4); // TODO: handle partial reads
|
||||||
// Just busy-wait for now
|
|
||||||
while (node == null) node = dev.get();
|
return std.mem.readIntNative(i32, &store);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node) |n| {
|
inline fn __out(self: *Machine, dev: CharDev, val: i32) !void {
|
||||||
defer self.alloc.destroy(n);
|
const fd = dev[1]; // Write to the pipe
|
||||||
return n.data;
|
const bytes = std.mem.asBytes(&val);
|
||||||
}
|
|
||||||
|
|
||||||
unreachable;
|
try std.os.write(fd, bytes);
|
||||||
}
|
|
||||||
|
|
||||||
inline fn __out(self: *Machine, dev: *CharDev, val: i32) !void {
|
|
||||||
var node = try self.alloc.create(CharDev.Node);
|
|
||||||
node.data = val;
|
|
||||||
|
|
||||||
dev.put(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read an immediate or position value from memory. Parameter determines
|
/// Read an immediate or position value from memory. Parameter determines
|
||||||
@@ -200,7 +197,7 @@ pub const Machine = struct {
|
|||||||
},
|
},
|
||||||
|
|
||||||
.IN => {
|
.IN => {
|
||||||
self.__write(0, try self.readFromInput(true)); // blocking read
|
self.__write(0, try self.readFromInput()); // blocking read
|
||||||
},
|
},
|
||||||
|
|
||||||
.OUT => {
|
.OUT => {
|
||||||
@@ -301,7 +298,7 @@ test "day 5 example 1" {
|
|||||||
try machine.run();
|
try machine.run();
|
||||||
|
|
||||||
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
||||||
assert(666 == try machine.readFromOutput(false));
|
assert(666 == try machine.readFromOutput());
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Instruction#decode ADD" {
|
test "Instruction#decode ADD" {
|
||||||
|
Reference in New Issue
Block a user