This commit is contained in:
		
							
								
								
									
										107
									
								
								src/day15.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/day15.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user