diff --git a/02/src/main.zig b/02/src/main.zig index 3918edf..270da8c 100644 --- a/02/src/main.zig +++ b/02/src/main.zig @@ -1,6 +1,24 @@ const std = @import("std"); 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 { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); @@ -10,18 +28,18 @@ pub fn main() anyerror!void { var program = try intcode.loadFromStdIn(alloc); // 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. - var memory: []u32 = try alloc.alloc(u32, program.len); + var memory: []i32 = try alloc.alloc(i32, program.len); var done: bool = false; - var noun: u32 = 0; - var verb: u32 = 0; + var noun: i32 = 0; + var verb: i32 = 0; std.debug.warn("Part 2: Searching..."); while (!done) { - std.mem.copy(u32, memory, program); - const result = try intcode.run(memory, noun, verb); + std.mem.copy(i32, memory, program); + const result = run(memory, noun, verb); // Too high: 250800 (noun=33, verb=76) if (result == 19690720) { diff --git a/lib/intcode/intcode.zig b/lib/intcode/intcode.zig index 95a8f78..95a546d 100644 --- a/lib/intcode/intcode.zig +++ b/lib/intcode/intcode.zig @@ -1,14 +1,14 @@ const std = @import("std"); -pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]u32 { - var program = try alloc.alloc(u32, 1024); +pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 { + var program = try alloc.alloc(i32, 1024); var buf = [_]u8{0} ** 255; var i: u32 = 0; while (try stream.readUntilDelimiterOrEof(&buf, ',')) |num| { 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]); @@ -20,26 +20,14 @@ pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.S 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 stream = &file.inStream().stream; return loadFromStream(alloc, stream); } -pub fn runCopy(alloc: *std.mem.Allocator, program: []u32, noun: u32, verb: u32) anyerror!u32 { - 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; - +pub fn run(program: []i32) void { // Initial program state var ip: u32 = 0; 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); const opcode = switch (program[ip]) { 1 => { - var a = program[program[ip + 1]]; - var b = program[program[ip + 2]]; + var a = program[@intCast(usize, program[ip + 1])]; + var b = program[@intCast(usize, program[ip + 2])]; var dest = program[ip + 3]; var result = a + b; // std.debug.warn("ADD: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); - program[dest] = result; + program[@intCast(usize, dest)] = result; ip += 4; }, 2 => { - var a = program[program[ip + 1]]; - var b = program[program[ip + 2]]; + var a = program[@intCast(usize, program[ip + 1])]; + var b = program[@intCast(usize, program[ip + 2])]; var dest = program[ip + 3]; var result = a * b; // std.debug.warn("MULT: [{}] + [{}] => {} : {} + {} = {} => {}\n", ip + 1, ip + 2, dest, a, b, result, dest); - program[dest] = result; + program[@intCast(usize, dest)] = result; ip += 4; }, 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])); }