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); }