diff --git a/src/day15.zig b/src/day15.zig new file mode 100644 index 0000000..866ab54 --- /dev/null +++ b/src/day15.zig @@ -0,0 +1,107 @@ +const std = @import("std"); +const util = @import("util.zig"); +const mem = std.mem; + +pub fn main() !void { + const input = @embedFile("data/day15.txt"); + const sln = try solve(util.gpa, input); + std.debug.print("{d}\n", .{sln.a}); + std.debug.print("{d}\n", .{sln.b}); +} + +const Solution = struct { + a: usize, + b: usize, +}; + +fn hash(input: []const u8) u32 { + var v: u32 = 0; + for (input) |c| { + v += c; + v *= 17; + v %= 256; + } + return v; +} + +fn solve(alloc: mem.Allocator, input: []const u8) !Solution { + const trimmed = mem.trimRight(u8, input, "\n\r"); + + var hash_sum: u32 = 0; + var it = util.split(trimmed, ','); + while (it.next()) |line| { + if (line.len == 0) continue; + hash_sum += hash(line); + } + + var boxes: [256]?std.StringArrayHashMap(u8) = [_]?std.StringArrayHashMap(u8){null} ** 256; + it = util.split(trimmed, ','); + while (it.next()) |line| { + if (line.len == 0) continue; + const op = mem.indexOfAny(u8, line, "-=") orelse unreachable; + const label = line[0..op]; + const label_hash = hash(label); + + // Split init instead of using orelse because references. + if (boxes[label_hash] == null) { + boxes[label_hash] = std.StringArrayHashMap(u8).init(alloc); + } + var box = &(boxes[label_hash] orelse unreachable); + + switch (line[op]) { + '-' => _ = box.orderedRemove(label), + '=' => { + const focus = try std.fmt.parseInt(u8, line[op + 1 ..], 10); + try box.put(label, focus); + }, + else => unreachable, + } + + // std.debug.print("{s}\n", .{ line }); + // for (boxes, 0..) |bx, n| { + // if (bx) |b| { + // std.debug.print("box {}: {any} = {any}\n", .{ n, b.keys(), b.values() }); + // } + // } + // std.debug.print("---\n", .{}); + } + + var focus: usize = 0; + for (boxes, 1..) |maybe_box, box_n| { + var box = maybe_box orelse continue; + var box_it = box.iterator(); + var lens_n: usize = 1; + while (box_it.next()) |entry| { + const label = entry.key_ptr.*; + _ = label; + const focal_len = entry.value_ptr.*; + const focus_power = box_n * lens_n * focal_len; + // std.debug.print("{s}: box {} * slot {} * focal length {} = {}\n", .{ label, box_n, lens_n, focal_len, focus_power }); + focus += focus_power; + lens_n += 1; + } + box.deinit(); + } + + return .{ .a = hash_sum, .b = focus }; +} + +test "sample hash" { + try std.testing.expectEqual(@as(usize, 52), hash("HASH")); +} + +test "silver" { + const input = + \\rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 + ; + const sln = try solve(std.testing.allocator, input); + try std.testing.expectEqual(@as(usize, 1320), sln.a); +} + +test "gold" { + const input = + \\rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 + ; + const sln = try solve(std.testing.allocator, input); + try std.testing.expectEqual(@as(usize, 145), sln.b); +}