const std = @import("std"); const PATH = "input/day14.txt"; const Str = []const u8; pub fn first(allocator: std.mem.Allocator) !usize { _ = allocator; const RACE_TIME = 2503; var max: usize = 0; var lines = std.mem.tokenize(u8, @embedFile(PATH), "\n"); while (lines.next()) |line| { var words = std.mem.tokenize(u8, line, " "); for (.{ "deer", "can", "fly" }) |_| { _ = words.next(); } const speed = try std.fmt.parseUnsigned(usize, words.next().?, 10); for (.{ "km/s", "for" }) |_| { _ = words.next(); } const duration = try std.fmt.parseUnsigned(usize, words.next().?, 10); for (.{ "seconds,", "but", "then", "must", "rest", "for" }) |_| { _ = words.next(); } const rest = try std.fmt.parseUnsigned(usize, words.next().?, 10); const full_runs = RACE_TIME / (duration + rest); const left_time = RACE_TIME % (duration + rest); const run: usize = speed * duration * full_runs + std.math.min(duration, left_time) * speed; if (run > max) max = run; } return max; } pub fn second(allocator: std.mem.Allocator) !usize { const RACE_TIME = 2503; var deers = try parseInput(allocator, @embedFile(PATH)); defer allocator.free(deers); var lead: usize = 0; var time: usize = 0; while (time < RACE_TIME) : (time += 1) { for (deers) |*deer| { const my_time = time % (deer.duration + deer.rest); if (my_time < deer.duration) deer.pos += deer.speed; if (deer.pos > lead) lead = deer.pos; } // give reward points for (deers) |*deer| { if (deer.pos == lead) deer.points += 1; } } var max: usize = 0; for (deers) |deer| { if (deer.points > max) max = deer.points; } return max; } const Deer = struct { speed: usize, duration: usize, rest: usize, pos: usize = 0, points: usize = 0, }; fn parseInput(allocator: std.mem.Allocator, in: Str) ![]Deer { var deers = std.ArrayList(Deer).init(allocator); var lines = std.mem.tokenize(u8, in, "\n"); while (lines.next()) |line| { var words = std.mem.tokenize(u8, line, " "); for (.{ "deer", "can", "fly" }) |_| { _ = words.next(); } const speed = try std.fmt.parseUnsigned(usize, words.next().?, 10); for (.{ "km/s", "for" }) |_| { _ = words.next(); } const duration = try std.fmt.parseUnsigned(usize, words.next().?, 10); for (.{ "seconds,", "but", "then", "must", "rest", "for" }) |_| { _ = words.next(); } const rest = try std.fmt.parseUnsigned(usize, words.next().?, 10); try deers.append(.{ .speed = speed, .duration = duration, .rest = rest }); } return try deers.toOwnedSlice(); } test "day14a" { try std.testing.expectEqual(@as(usize, 2660), try first(std.testing.allocator)); } test "day14b" { try std.testing.expectEqual(@as(usize, 1256), try second(std.testing.allocator)); } const test_input = \\Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds. \\Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds. ;