diff options
Diffstat (limited to 'day09.zig')
-rw-r--r-- | day09.zig | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/day09.zig b/day09.zig new file mode 100644 index 0000000..6f44ab0 --- /dev/null +++ b/day09.zig @@ -0,0 +1,68 @@ +const std = @import("std"); +const data = @embedFile("day09"); + +var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; +const gpa = general_purpose_allocator.allocator(); + +const Pair = struct { x: i32, y: i32 }; + +fn signum(n: i32) i32 { + if (n > 0) return 1; + if (n < 0) return -1; + return 0; +} + +fn move_after(head: Pair, tail: Pair) Pair { + if (std.math.absInt(head.x - tail.x) catch unreachable <= 1 and + std.math.absInt(head.y - tail.y) catch unreachable <= 1) + return tail; + return .{ .x = tail.x + signum(head.x - tail.x), + .y = tail.y + signum(head.y - tail.y) }; +} + +fn solve(comptime ropelen: usize) !usize { + var lines = std.mem.tokenize(u8, data, "\n"); + + var visited = std.AutoHashMap(Pair, void).init(gpa); + defer visited.deinit(); + + var rope = [_]Pair{.{.x = 0, .y = 0}} ** ropelen; + + try visited.put(rope[ropelen-1], {}); + + while (lines.next()) |line| { + if (line.len == 0) + break; + + var parts = std.mem.tokenize(u8, line, " "); + var dir = parts.next().?[0]; + var amt = try std.fmt.parseInt(usize, parts.next().?, 10); + + var n: usize = 0; + while (n < amt) : (n += 1) { + switch (dir) { + 'L' => rope[0].x -= 1, + 'R' => rope[0].x += 1, + 'U' => rope[0].y -= 1, + 'D' => rope[0].y += 1, + else => unreachable, + } + + var i: usize = 1; + while (i < ropelen) : (i += 1) { + rope[i] = move_after(rope[i-1], rope[i]); + } + + try visited.put(rope[ropelen-1], {}); + } + } + + return visited.count(); +} + +pub fn main() !void { + defer std.debug.assert(!general_purpose_allocator.deinit()); + + std.debug.print("{}\n", .{try solve(2)}); + std.debug.print("{}\n", .{try solve(10)}); +} |