const std = @import("std"); // NOTE: I know this is way too overengineered, but I wanted // to make it as efficient as possible. pub fn main() !void { const input = @embedFile("input"); // Putting part 1's solution as an extra :P std.debug.print("Part 1's solution: {}\n", .{sumTopNElves(input, 1)}); std.debug.print("Part 2's solution: {}\n", .{sumTopNElves(input, 3)}); } // Returns the sum of the elves with the most calories from pub fn sumTopNElves(input: []const u8, comptime cant: usize) usize { var iter = ElfIterator.init(input); // Initialize the buffer where the 3 numbers will lie var maxArr: [cant]usize = .{0} ** cant; // Keeps track of which is the smallest index of the array var min_i: usize = 0; // Iterate through each elf's sum of calories as usize while (iter.next()) |elf| { // Check if the current elf carries more // calories than the previous smallest max if (elf > maxArr[min_i]) { maxArr[min_i] = elf; // maxArr changed, update what is the smallest index var advance: usize = 1; while (advance < cant) : (advance += 1) { // Advance and wrap around const i = (min_i + advance) % cant; if (maxArr[i] < maxArr[min_i]) min_i = i; } } } var res: usize = 0; inline for (maxArr) |num| { res += num; } return res; } // Helper to return the total of calories per elf one at a time const ElfIterator = struct { iter: std.mem.SplitIterator(u8), pub fn init(input: []const u8) ElfIterator { return ElfIterator{ // We assume the input file is properly formatted .iter = std.mem.split(u8, input, "\n"), }; } pub fn next(self: *ElfIterator) ?usize { var res: usize = 0; while (self.iter.next()) |calories| { // If non numeric assume EOF (End Of elF) res += std.fmt.parseInt(usize, calories, 10) catch return res; } // If we reach EOF (End Of File, do not confuse with End Of elF), return null return null; } };