Refactor intcode in preparation for day 5

This commit is contained in:
2019-12-05 19:45:14 +00:00
parent 3ddda35eec
commit 2f4ca301ad
2 changed files with 77 additions and 31 deletions

View File

@@ -1,6 +1,24 @@
const std = @import("std"); const std = @import("std");
const intcode = @import("intcode"); const intcode = @import("intcode");
fn run(program: []i32, noun: i32, verb: i32) i32 {
program[1] = noun;
program[2] = verb;
intcode.run(program);
return program[0];
}
fn runCopy(alloc: *std.mem.Allocator, program: []i32, noun: i32, verb: i32) anyerror!i32 {
var memory = try alloc.alloc(i32, program.len);
defer alloc.free(memory);
std.mem.copy(i32, memory, program);
return run(memory, noun, verb);
}
pub fn main() anyerror!void { pub fn main() anyerror!void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit(); defer arena.deinit();
@@ -10,18 +28,18 @@ pub fn main() anyerror!void {
var program = try intcode.loadFromStdIn(alloc); var program = try intcode.loadFromStdIn(alloc);
// Part 1 // Part 1
std.debug.warn("Part 1: {}\n", try intcode.runCopy(alloc, program, 12, 2)); std.debug.warn("Part 1: {}\n", try runCopy(alloc, program, 12, 2));
// Part 2: 100*100 = 10,000 combinations to try. // Part 2: 100*100 = 10,000 combinations to try.
var memory: []u32 = try alloc.alloc(u32, program.len); var memory: []i32 = try alloc.alloc(i32, program.len);
var done: bool = false; var done: bool = false;
var noun: u32 = 0; var noun: i32 = 0;
var verb: u32 = 0; var verb: i32 = 0;
std.debug.warn("Part 2: Searching..."); std.debug.warn("Part 2: Searching...");
while (!done) { while (!done) {
std.mem.copy(u32, memory, program); std.mem.copy(i32, memory, program);
const result = try intcode.run(memory, noun, verb); const result = run(memory, noun, verb);
// Too high: 250800 (noun=33, verb=76) // Too high: 250800 (noun=33, verb=76)
if (result == 19690720) { if (result == 19690720) {

View File

@@ -1,14 +1,14 @@
const std = @import("std"); const std = @import("std");
pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]u32 { pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 {
var program = try alloc.alloc(u32, 1024); var program = try alloc.alloc(i32, 1024);
var buf = [_]u8{0} ** 255; var buf = [_]u8{0} ** 255;
var i: u32 = 0; var i: u32 = 0;
while (try stream.readUntilDelimiterOrEof(&buf, ',')) |num| { while (try stream.readUntilDelimiterOrEof(&buf, ',')) |num| {
var trimmed = std.mem.trimRight(u8, num, "\r\n"); var trimmed = std.mem.trimRight(u8, num, "\r\n");
program[i] = try std.fmt.parseInt(u32, trimmed, 10); program[i] = try std.fmt.parseInt(i32, trimmed, 10);
std.debug.warn("{},", program[i]); std.debug.warn("{},", program[i]);
@@ -20,26 +20,14 @@ pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.S
return program[0..program.len]; return program[0..program.len];
} }
pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]u32 { pub fn loadFromStdIn(alloc: *std.mem.Allocator) anyerror![]i32 {
const file = std.io.getStdIn(); const file = std.io.getStdIn();
const stream = &file.inStream().stream; const stream = &file.inStream().stream;
return loadFromStream(alloc, stream); return loadFromStream(alloc, stream);
} }
pub fn runCopy(alloc: *std.mem.Allocator, program: []u32, noun: u32, verb: u32) anyerror!u32 { pub fn run(program: []i32) void {
var memory = try alloc.alloc(u32, program.len);
defer alloc.free(memory);
std.mem.copy(u32, memory, program);
return run(memory, noun, verb);
}
pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 {
program[1] = noun;
program[2] = verb;
// Initial program state // Initial program state
var ip: u32 = 0; var ip: u32 = 0;
var exit: bool = false; var exit: bool = false;
@@ -50,23 +38,23 @@ pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 {
// std.debug.warn(" IP {d:4}: ", ip); // std.debug.warn(" IP {d:4}: ", ip);
const opcode = switch (program[ip]) { const opcode = switch (program[ip]) {
1 => { 1 => {
var a = program[program[ip + 1]]; var a = program[@intCast(usize, program[ip + 1])];
var b = program[program[ip + 2]]; var b = program[@intCast(usize, program[ip + 2])];
var dest = program[ip + 3]; var dest = program[ip + 3];
var result = a + b; var result = a + b;
// std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); // std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest);
program[dest] = result; program[@intCast(usize, dest)] = result;
ip += 4; ip += 4;
}, },
2 => { 2 => {
var a = program[program[ip + 1]]; var a = program[@intCast(usize, program[ip + 1])];
var b = program[program[ip + 2]]; var b = program[@intCast(usize, program[ip + 2])];
var dest = program[ip + 3]; var dest = program[ip + 3];
var result = a * b; var result = a * b;
// std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); // std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest);
program[dest] = result; program[@intCast(usize, dest)] = result;
ip += 4; ip += 4;
}, },
99 => { 99 => {
@@ -79,6 +67,46 @@ pub fn run(program: []u32, noun: u32, verb: u32) anyerror!u32 {
}, },
}; };
} }
}
return program[0];
const assert = std.debug.assert;
test "day 2 example 1" {
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 };
run(before[0..before.len]);
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
}
test "day 2 example 2" {
var before: [5]i32 = .{ 1, 0, 0, 0, 99 };
var after: [5]i32 = .{ 2, 0, 0, 0, 99 };
run(before[0..before.len]);
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
}
test "day 2 example 3" {
var before: [5]i32 = .{ 2, 3, 0, 3, 99 };
var after: [5]i32 = .{ 2, 3, 0, 6, 99 };
run(before[0..before.len]);
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
}
test "day 2 example 4" {
var before: [6]i32 = .{ 2, 4, 4, 5, 99, 0 };
var after: [6]i32 = .{ 2, 4, 4, 5, 99, 9801 };
run(before[0..before.len]);
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
}
test "day 2 example 5" {
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 };
run(before[0..before.len]);
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
} }