Day 9.1
This commit is contained in:
@@ -3,6 +3,7 @@ const std = @import("std");
|
||||
// We're using pipes as character devices
|
||||
pub const CharDev = [2]i32;
|
||||
pub const Word = i64;
|
||||
pub const MemSize = 1024 * 2;
|
||||
|
||||
pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]Word {
|
||||
var program = try alloc.alloc(Word, 1024);
|
||||
@@ -37,12 +38,14 @@ const Opcode = enum(u8) {
|
||||
JZ = 6,
|
||||
LT = 7,
|
||||
EQ = 8,
|
||||
RBO = 9,
|
||||
END = 99,
|
||||
};
|
||||
|
||||
const Mode = enum(u8) {
|
||||
Position = 0,
|
||||
Immediate = 1,
|
||||
Relative = 2,
|
||||
};
|
||||
|
||||
const Instruction = struct {
|
||||
@@ -79,6 +82,7 @@ const Instruction = struct {
|
||||
.JZ => 3,
|
||||
.LT => 4,
|
||||
.EQ => 4,
|
||||
.RBO => 2,
|
||||
.END => 1,
|
||||
};
|
||||
}
|
||||
@@ -93,6 +97,7 @@ pub const Machine = struct {
|
||||
idx: usize = 0, // handy for debugging
|
||||
|
||||
memory: []Word,
|
||||
rb: Word = 0,
|
||||
|
||||
ip: usize = 0,
|
||||
|
||||
@@ -108,9 +113,13 @@ pub const Machine = struct {
|
||||
}
|
||||
|
||||
pub fn init(alloc: *std.mem.Allocator, program: []Word) anyerror!Machine {
|
||||
var memory = try alloc.alloc(Word, MemSize);
|
||||
std.mem.set(Word, memory, 0);
|
||||
std.mem.copy(Word, memory, program);
|
||||
|
||||
return Machine{
|
||||
.alloc = alloc,
|
||||
.memory = program,
|
||||
.memory = memory,
|
||||
.input = try std.os.pipe(),
|
||||
.output = try std.os.pipe(),
|
||||
};
|
||||
@@ -121,6 +130,7 @@ pub const Machine = struct {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Machine) void {
|
||||
self.alloc.free(self.memory);
|
||||
std.os.close(self.input[0]);
|
||||
std.os.close(self.input[1]);
|
||||
std.os.close(self.output[0]);
|
||||
@@ -170,12 +180,18 @@ pub const Machine = struct {
|
||||
return switch (mode) {
|
||||
.Immediate => immediate,
|
||||
.Position => self.memory[@intCast(usize, immediate)],
|
||||
.Relative => self.memory[@intCast(usize, immediate + self.rb)],
|
||||
};
|
||||
}
|
||||
|
||||
inline fn __write(self: *Machine, parameter: usize, value: Word) void {
|
||||
inline fn __write(self: *Machine, parameter: usize, mode: Mode, value: Word) void {
|
||||
const dest = self.__read(parameter, .Immediate);
|
||||
self.memory[@intCast(usize, dest)] = value;
|
||||
|
||||
switch (mode) {
|
||||
.Immediate => unreachable,
|
||||
.Position => self.memory[@intCast(usize, dest)] = value,
|
||||
.Relative => self.memory[@intCast(usize, dest + self.rb)] = value,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(self: *Machine) anyerror!bool {
|
||||
@@ -187,18 +203,18 @@ pub const Machine = struct {
|
||||
const a = self.__read(0, insn.modes[0]);
|
||||
const b = self.__read(1, insn.modes[1]);
|
||||
|
||||
self.__write(2, a + b);
|
||||
self.__write(2, insn.modes[2], a + b);
|
||||
},
|
||||
|
||||
.MULT => {
|
||||
const a = self.__read(0, insn.modes[0]);
|
||||
const b = self.__read(1, insn.modes[1]);
|
||||
|
||||
self.__write(2, a * b);
|
||||
self.__write(2, insn.modes[2], a * b);
|
||||
},
|
||||
|
||||
.IN => {
|
||||
self.__write(0, try self.readFromInput()); // blocking read
|
||||
self.__write(0, insn.modes[0], try self.readFromInput()); // blocking read
|
||||
},
|
||||
|
||||
.OUT => {
|
||||
@@ -220,9 +236,9 @@ pub const Machine = struct {
|
||||
const b = self.__read(1, insn.modes[1]);
|
||||
|
||||
if (a < b) {
|
||||
self.__write(2, 1);
|
||||
self.__write(2, insn.modes[2], 1);
|
||||
} else {
|
||||
self.__write(2, 0);
|
||||
self.__write(2, insn.modes[2], 0);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -231,12 +247,16 @@ pub const Machine = struct {
|
||||
const b = self.__read(1, insn.modes[1]);
|
||||
|
||||
if (a == b) {
|
||||
self.__write(2, 1);
|
||||
self.__write(2, insn.modes[2], 1);
|
||||
} else {
|
||||
self.__write(2, 0);
|
||||
self.__write(2, insn.modes[2], 0);
|
||||
}
|
||||
},
|
||||
|
||||
.RBO => {
|
||||
self.rb += self.__read(0, insn.modes[0]);
|
||||
},
|
||||
|
||||
.END => {
|
||||
// std.debug.warn("{}: ended\n", self.idx);
|
||||
},
|
||||
@@ -256,54 +276,103 @@ test "day 2 example 1" {
|
||||
var before: [12]Word = .{ 1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50 };
|
||||
var after: [12]Word = .{ 3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50 };
|
||||
var machine = try Machine.Run(test_allocator, before[0..before.len]);
|
||||
defer machine.deinit();
|
||||
|
||||
assert(std.mem.eql(Word, before[0..before.len], after[0..after.len]));
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len]));
|
||||
}
|
||||
|
||||
test "day 2 example 2" {
|
||||
var before: [5]Word = .{ 1, 0, 0, 0, 99 };
|
||||
var after: [5]Word = .{ 2, 0, 0, 0, 99 };
|
||||
var machine = try Machine.Run(test_allocator, before[0..before.len]);
|
||||
defer machine.deinit();
|
||||
|
||||
assert(std.mem.eql(Word, before[0..before.len], after[0..after.len]));
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len]));
|
||||
}
|
||||
|
||||
test "day 2 example 3" {
|
||||
var before: [5]Word = .{ 2, 3, 0, 3, 99 };
|
||||
var after: [5]Word = .{ 2, 3, 0, 6, 99 };
|
||||
var machine = try Machine.Run(test_allocator, before[0..before.len]);
|
||||
defer machine.deinit();
|
||||
|
||||
assert(std.mem.eql(Word, before[0..before.len], after[0..after.len]));
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len]));
|
||||
}
|
||||
|
||||
test "day 2 example 4" {
|
||||
var before: [6]Word = .{ 2, 4, 4, 5, 99, 0 };
|
||||
var after: [6]Word = .{ 2, 4, 4, 5, 99, 9801 };
|
||||
var machine = try Machine.Run(test_allocator, before[0..before.len]);
|
||||
defer machine.deinit();
|
||||
|
||||
assert(std.mem.eql(Word, before[0..before.len], after[0..after.len]));
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len]));
|
||||
}
|
||||
|
||||
test "day 2 example 5" {
|
||||
var before: [9]Word = .{ 1, 1, 1, 4, 99, 5, 6, 0, 99 };
|
||||
var after: [9]Word = .{ 30, 1, 1, 4, 2, 5, 6, 0, 99 };
|
||||
var machine = try Machine.Run(test_allocator, before[0..before.len]);
|
||||
defer machine.deinit();
|
||||
|
||||
assert(std.mem.eql(Word, before[0..before.len], after[0..after.len]));
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len]));
|
||||
}
|
||||
|
||||
test "day 5 example 1" {
|
||||
var before: [5]Word = .{ 3, 0, 4, 0, 99 };
|
||||
var after: [5]Word = .{ 666, 0, 4, 0, 99 };
|
||||
var machine = try Machine.init(test_allocator, before[0..before.len]);
|
||||
defer machine.deinit();
|
||||
|
||||
try machine.writeToInput(666);
|
||||
try machine.run();
|
||||
|
||||
assert(std.mem.eql(Word, before[0..before.len], after[0..after.len]));
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len]));
|
||||
assert(666 == try machine.readFromOutput());
|
||||
}
|
||||
|
||||
test "day 9 example 1" {
|
||||
var before: [16]Word = .{ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 };
|
||||
var after: [16]Word = before;
|
||||
var output: [16]Word = undefined;
|
||||
|
||||
var machine = try Machine.init(test_allocator, before[0..before.len]);
|
||||
defer machine.deinit();
|
||||
try machine.run();
|
||||
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len]));
|
||||
|
||||
for (output) |*b| {
|
||||
b.* = try machine.readFromOutput();
|
||||
}
|
||||
|
||||
// This program produces a copy of itself as output
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], output[0..after.len]));
|
||||
}
|
||||
|
||||
test "day 9 example 2" {
|
||||
var before: [8]Word = .{ 1102, 34915192, 34915192, 7, 4, 7, 99, 0 };
|
||||
var after: [8]Word = .{ 1102, 34915192, 34915192, 7, 4, 7, 99, 1219070632396864 };
|
||||
|
||||
var machine = try Machine.init(test_allocator, before[0..before.len]);
|
||||
defer machine.deinit();
|
||||
try machine.run();
|
||||
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len]));
|
||||
std.debug.assert(1219070632396864 == try machine.readFromOutput());
|
||||
}
|
||||
|
||||
test "day 9 example 3" {
|
||||
var before: [3]Word = .{ 104, 1125899906842624, 99 };
|
||||
var after: [3]Word = before;
|
||||
|
||||
var machine = try Machine.init(test_allocator, before[0..before.len]);
|
||||
defer machine.deinit();
|
||||
try machine.run();
|
||||
|
||||
assert(std.mem.eql(Word, machine.memory[0..before.len], after[0..after.len]));
|
||||
std.debug.assert(1125899906842624 == try machine.readFromOutput());
|
||||
}
|
||||
|
||||
test "Instruction#decode ADD" {
|
||||
const insn = try Instruction.decode(1);
|
||||
|
||||
|
Reference in New Issue
Block a user