const std = @import("std"); const mem = std.mem; const math = std.math; pub fn main() !void { const input: []const u8 = @embedFile("input.txt"); const part1, const part2 = try problem(input); std.debug.print("Part 1: {}\n", .{part1}); std.debug.print("Part 2: {}\n", .{part2}); } fn problem(input: []const u8) !struct { u64, u64 } { const lines: mem.TokenIterator(u8, .scalar) = mem.tokenizeScalar(u8, input, '\n'); const part1: u64 = try p1(lines); const part2: u64 = try p2(lines); return .{ part1, part2 }; } fn parseline(l: []const u8) !i64 { return switch (l[0]) { 'L' => try std.fmt.parseInt(i64, l[1..], 10), 'R' => - try std.fmt.parseInt(i64, l[1..], 10), else => error{InvalidLine}.InvalidLine, }; } inline fn rotatepos(pos: u32, n: i64) u32 { return @truncate(@abs(@mod(pos + n, 100))); } fn countzeros(pos: u64, n: i64) u64 { var zeros: u64 = 0; var x: u32 = @intCast(pos); var clicks: u64 = @abs(n); const y: i64 = if (n < 0) -1 else 1; while (clicks > 0) : (clicks -= 1){ x = rotatepos(x, y); if (x == 0) zeros += 1; } return zeros; } fn p1(constLines: mem.TokenIterator(u8, .scalar)) !u64 { var pos: u32 = 50; var zeros: u64 = 0; var lines = constLines; while (lines.next()) |line| { pos = rotatepos(pos, try parseline(line)); if (pos == 0) zeros += 1; } return zeros; } fn p2(constLines: mem.TokenIterator(u8, .scalar)) !u64 { var pos: u32 = 50; var zeros: u64 = 0; var lines = constLines; while (lines.next()) |line| { const n = try parseline(line); zeros += countzeros(pos, n); pos = rotatepos(pos, n); } return zeros; } test "Sample Input" { const input: []const u8 = @embedFile("input_sample.txt"); const part1, const part2 = try problem(input); std.debug.print("Part 1: {}\n", .{part1}); std.debug.print("Part 2: {}\n", .{part2}); try std.testing.expectEqual(3, part1); try std.testing.expectEqual(6, part2); }