More intcode refactoring
This commit is contained in:
@@ -5,7 +5,9 @@ fn run(program: []i32, noun: i32, verb: i32) i32 {
|
|||||||
program[1] = noun;
|
program[1] = noun;
|
||||||
program[2] = verb;
|
program[2] = verb;
|
||||||
|
|
||||||
intcode.run(program);
|
var machine = &intcode.Machine{ .memory = program, .ip = 0 };
|
||||||
|
|
||||||
|
machine.run();
|
||||||
|
|
||||||
return program[0];
|
return program[0];
|
||||||
}
|
}
|
||||||
|
@@ -27,86 +27,101 @@ pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]i32 {
|
|||||||
return loadFromStream(alloc, stream);
|
return loadFromStream(alloc, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(program: []i32) void {
|
pub const Machine = struct {
|
||||||
// Initial program state
|
memory: []i32,
|
||||||
var ip: u32 = 0;
|
|
||||||
var exit: bool = false;
|
|
||||||
|
|
||||||
// TODO: create a nice struct
|
ip: usize = 0,
|
||||||
|
|
||||||
while (!exit) {
|
pub fn Run(program: []i32) anyerror!Machine {
|
||||||
// std.debug.warn(" IP {d:4}: ", ip);
|
var machine = try init(program);
|
||||||
const opcode = switch (program[ip]) {
|
|
||||||
|
machine.run();
|
||||||
|
|
||||||
|
return machine;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(program: []i32) anyerror!Machine {
|
||||||
|
return Machine{ .memory = program };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(self: *Machine) void {
|
||||||
|
while (self.step()) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn step(self: *Machine) bool {
|
||||||
|
var program = self.memory;
|
||||||
|
|
||||||
|
const opcode = switch (program[self.ip]) {
|
||||||
1 => {
|
1 => {
|
||||||
var a = program[@intCast(usize, program[ip + 1])];
|
var a = program[@intCast(usize, program[self.ip + 1])];
|
||||||
var b = program[@intCast(usize, program[ip + 2])];
|
var b = program[@intCast(usize, program[self.ip + 2])];
|
||||||
var dest = program[ip + 3];
|
var dest = program[self.ip + 3];
|
||||||
var result = a + b;
|
var result = a + b;
|
||||||
|
|
||||||
// std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest);
|
|
||||||
program[@intCast(usize, dest)] = result;
|
program[@intCast(usize, dest)] = result;
|
||||||
ip += 4;
|
self.ip += 4;
|
||||||
},
|
},
|
||||||
2 => {
|
2 => {
|
||||||
var a = program[@intCast(usize, program[ip + 1])];
|
var a = program[@intCast(usize, program[self.ip + 1])];
|
||||||
var b = program[@intCast(usize, program[ip + 2])];
|
var b = program[@intCast(usize, program[self.ip + 2])];
|
||||||
var dest = program[ip + 3];
|
var dest = program[self.ip + 3];
|
||||||
var result = a * b;
|
var result = a * b;
|
||||||
|
|
||||||
// std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest);
|
|
||||||
program[@intCast(usize, dest)] = result;
|
program[@intCast(usize, dest)] = result;
|
||||||
ip += 4;
|
self.ip += 4;
|
||||||
},
|
},
|
||||||
99 => {
|
99 => {
|
||||||
// std.debug.warn("EXIT\n");
|
self.ip += 1;
|
||||||
exit = true;
|
return false;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
std.debug.warn("Unknown opcode at IP {}: {}", ip, program[ip]);
|
std.debug.warn("Unknown opcode at IP {}: {}", self.ip, program[self.ip]);
|
||||||
exit = true;
|
return false;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
test "day 2 example 1" {
|
test "day 2 example 1" {
|
||||||
var before: [12]i32 = .{ 1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50 };
|
var before: [12]i32 = .{ 1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50 };
|
||||||
var after: [12]i32 = .{ 3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50 };
|
var after: [12]i32 = .{ 3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50 };
|
||||||
|
var machine = Machine.Run(before[0..before.len]);
|
||||||
|
|
||||||
run(before[0..before.len]);
|
|
||||||
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "day 2 example 2" {
|
test "day 2 example 2" {
|
||||||
var before: [5]i32 = .{ 1, 0, 0, 0, 99 };
|
var before: [5]i32 = .{ 1, 0, 0, 0, 99 };
|
||||||
var after: [5]i32 = .{ 2, 0, 0, 0, 99 };
|
var after: [5]i32 = .{ 2, 0, 0, 0, 99 };
|
||||||
|
var machine = Machine.Run(before[0..before.len]);
|
||||||
|
|
||||||
run(before[0..before.len]);
|
|
||||||
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "day 2 example 3" {
|
test "day 2 example 3" {
|
||||||
var before: [5]i32 = .{ 2, 3, 0, 3, 99 };
|
var before: [5]i32 = .{ 2, 3, 0, 3, 99 };
|
||||||
var after: [5]i32 = .{ 2, 3, 0, 6, 99 };
|
var after: [5]i32 = .{ 2, 3, 0, 6, 99 };
|
||||||
|
var machine = Machine.Run(before[0..before.len]);
|
||||||
|
|
||||||
run(before[0..before.len]);
|
|
||||||
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "day 2 example 4" {
|
test "day 2 example 4" {
|
||||||
var before: [6]i32 = .{ 2, 4, 4, 5, 99, 0 };
|
var before: [6]i32 = .{ 2, 4, 4, 5, 99, 0 };
|
||||||
var after: [6]i32 = .{ 2, 4, 4, 5, 99, 9801 };
|
var after: [6]i32 = .{ 2, 4, 4, 5, 99, 9801 };
|
||||||
|
var machine = Machine.Run(before[0..before.len]);
|
||||||
|
|
||||||
run(before[0..before.len]);
|
|
||||||
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "day 2 example 5" {
|
test "day 2 example 5" {
|
||||||
var before: [9]i32 = .{ 1, 1, 1, 4, 99, 5, 6, 0, 99 };
|
var before: [9]i32 = .{ 1, 1, 1, 4, 99, 5, 6, 0, 99 };
|
||||||
var after: [9]i32 = .{ 30, 1, 1, 4, 2, 5, 6, 0, 99 };
|
var after: [9]i32 = .{ 30, 1, 1, 4, 2, 5, 6, 0, 99 };
|
||||||
|
var machine = Machine.Run(before[0..before.len]);
|
||||||
|
|
||||||
run(before[0..before.len]);
|
|
||||||
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user