const std = @import("std"); const INPUT = "14,3,1,0,9,5"; const Str = []const u8; pub fn first(allocator: ?std.mem.Allocator) anyerror!usize { return getLast(allocator.?, INPUT, 2020, u11); } pub fn second(allocator: ?std.mem.Allocator) anyerror!usize { return getLast(allocator.?, INPUT, 30_000_000, u25); } fn getLast(allocator: std.mem.Allocator, input: Str, limit: usize, comptime ItemType: anytype) !usize { var spoken = std.ArrayList(ItemType).init(allocator); defer spoken.deinit(); // Zero means the number was not spoken yet. try spoken.appendNTimes(0, limit); var last: ItemType = undefined; // Fill in starting numbers. var starting = std.mem.tokenize(u8, input, ","); var round: ItemType = 1; while (starting.next()) |st| : (round += 1) { const num = try std.fmt.parseUnsigned(ItemType, st, 0); spoken.items[num] = round; last = num; } // Van Eck Sequence round -= 1; while (round < limit) : (round += 1) { const next = round - if (spoken.items[last] != 0) spoken.items[last] else round; spoken.items[last] = round; last = next; } return @intCast(usize, last); } test "day15a" { try std.testing.expectEqual(@as(usize, 614), try first(std.testing.allocator)); } test "day15b" { try std.testing.expectEqual(@as(usize, 1065), try second(std.testing.allocator)); }