aboutsummaryrefslogtreecommitdiff
path: root/2022/11-monkey-in-the-middle/second.zig
diff options
context:
space:
mode:
authorJulien Dessaux2022-12-11 17:47:46 +0100
committerJulien Dessaux2022-12-11 17:47:46 +0100
commit1bec3f3b1b41230c5c4812024c56651e1fc24b7a (patch)
tree1e65af88e582f52a1168c33dca83fd89ea59848f /2022/11-monkey-in-the-middle/second.zig
parent2022-10 in zig (diff)
downloadadvent-of-code-1bec3f3b1b41230c5c4812024c56651e1fc24b7a.tar.gz
advent-of-code-1bec3f3b1b41230c5c4812024c56651e1fc24b7a.tar.bz2
advent-of-code-1bec3f3b1b41230c5c4812024c56651e1fc24b7a.zip
2022-11 in zig
Diffstat (limited to '')
-rw-r--r--2022/11-monkey-in-the-middle/second.zig129
1 files changed, 129 insertions, 0 deletions
diff --git a/2022/11-monkey-in-the-middle/second.zig b/2022/11-monkey-in-the-middle/second.zig
new file mode 100644
index 0000000..86b74ff
--- /dev/null
+++ b/2022/11-monkey-in-the-middle/second.zig
@@ -0,0 +1,129 @@
+const std = @import("std");
+
+const example = @embedFile("example");
+const input = @embedFile("input");
+
+pub fn main() anyerror!void {
+ var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
+ defer arena.deinit();
+ const allocator = arena.allocator();
+
+ try std.testing.expectEqual(try solve(example, allocator), 2713310158);
+ const result = try solve(input, allocator);
+ try std.io.getStdOut().writer().print("{}\n", .{result});
+}
+
+const Operation = struct {
+ first: ?u64,
+ operand: u8,
+ second: ?u64,
+ fn init(line: []const u8, allocator: std.mem.Allocator) !*Operation {
+ var o = try allocator.create(Operation);
+ var it = std.mem.tokenize(u8, line, " ");
+ _ = it.next() orelse unreachable; // Operation:
+ _ = it.next() orelse unreachable; // new
+ _ = it.next() orelse unreachable; // =
+ o.first = std.fmt.parseInt(u64, it.next() orelse unreachable, 10) catch null;
+ const tmp = it.next() orelse unreachable;
+ o.operand = tmp[0];
+ o.second = std.fmt.parseInt(u64, it.next() orelse unreachable, 10) catch null;
+ return o;
+ }
+ fn run(o: Operation, v: u64) u64 {
+ const first = if (o.first) |f| f else v;
+ const second = if (o.second) |f| f else v;
+ switch (o.operand) {
+ '+' => return first + second,
+ '-' => return first - second,
+ '*' => return first * second,
+ '/' => return first / second,
+ else => unreachable,
+ }
+ }
+};
+
+const Monkey = struct {
+ inspections: u64,
+ items: std.ArrayList(u64),
+ operation: *Operation,
+ divisible: u64, // divisible by
+ testTrue: u64,
+ testFalse: u64,
+ fn init(it: *std.mem.TokenIterator(u8), allocator: std.mem.Allocator) !*Monkey {
+ var m = try allocator.create(Monkey);
+ m.inspections = 0;
+ m.items = std.ArrayList(u64).init(allocator);
+ var items = std.mem.tokenize(u8, it.next() orelse unreachable, " ,");
+ _ = items.next() orelse unreachable; // starting
+ _ = items.next() orelse unreachable; // items:
+ while (items.next()) |item| {
+ try m.items.append(std.fmt.parseInt(u64, item, 10) catch unreachable);
+ }
+ m.operation = try Operation.init(it.next() orelse unreachable, allocator);
+ var divisible = std.mem.tokenize(u8, it.next() orelse unreachable, " ");
+ _ = divisible.next() orelse unreachable; // test:
+ _ = divisible.next() orelse unreachable; // divisible
+ _ = divisible.next() orelse unreachable; // by
+ m.divisible = std.fmt.parseInt(u64, divisible.next() orelse unreachable, 10) catch unreachable;
+ var testTrue = std.mem.tokenize(u8, it.next() orelse unreachable, " ");
+ _ = testTrue.next() orelse unreachable; // if
+ _ = testTrue.next() orelse unreachable; // true:
+ _ = testTrue.next() orelse unreachable; // throw
+ _ = testTrue.next() orelse unreachable; // to
+ _ = testTrue.next() orelse unreachable; // monkey
+ m.testTrue = std.fmt.parseInt(u64, testTrue.next() orelse unreachable, 10) catch unreachable;
+ var testFalse = std.mem.tokenize(u8, it.next() orelse unreachable, " ");
+ _ = testFalse.next() orelse unreachable; // if
+ _ = testFalse.next() orelse unreachable; // true:
+ _ = testFalse.next() orelse unreachable; // throw
+ _ = testFalse.next() orelse unreachable; // to
+ _ = testFalse.next() orelse unreachable; // monkey
+ m.testFalse = std.fmt.parseInt(u64, testFalse.next() orelse unreachable, 10) catch unreachable;
+ return m;
+ }
+ fn step(m: *Monkey, monkeys: []*Monkey, bigModulo: u64) !void {
+ m.inspections += m.items.items.len;
+ for (m.items.items) |item| {
+ const v = @mod(m.operation.run(item), bigModulo);
+ if (@mod(v, m.divisible) == 0) {
+ try monkeys[m.testTrue].items.append(v);
+ } else {
+ try monkeys[m.testFalse].items.append(v);
+ }
+ }
+ m.items.items.len = 0;
+ }
+};
+
+fn solve(puzzle: []const u8, allocator: std.mem.Allocator) !u64 {
+ var it = std.mem.tokenize(u8, puzzle, "\n");
+ var monkeys = std.ArrayList(*Monkey).init(allocator);
+ var bigModulo: u64 = 1;
+ // process input
+ while (it.next()) |_| {
+ var m = try monkeys.addOne();
+ m.* = try Monkey.init(&it, allocator);
+ bigModulo *= m.*.divisible;
+ }
+ // run 10k rounds
+ var rounds: usize = 0;
+ while (rounds < 10000) : (rounds += 1) {
+ for (monkeys.items) |m| {
+ try m.step(monkeys.items, bigModulo);
+ }
+ }
+ // find answer
+ var m1: u64 = 0;
+ var m2: u64 = 0;
+ for (monkeys.items) |m| {
+ if (m.inspections > m1) {
+ m2 = m1;
+ m1 = m.inspections;
+ continue;
+ }
+ if (m.inspections > m2) {
+ m2 = m.inspections;
+ }
+ }
+ return m1 * m2;
+}