const std = @import("std"); const mem = std.mem; const fs = std.fs; const print = std.debug.print; const ParseError = error{ RanOutOfWords, }; const Parser = struct { it: mem.SplitIterator(u8, .scalar), fn fromString(str: []const u8) Parser { return Parser{ .it = mem.splitScalar(u8, str, ' '), }; } fn take(self: *Parser) ![]const u8 { const wordo = self.it.next(); if (wordo) |word| { return word; } else { return ParseError.RanOutOfWords; } } fn skip(self: *Parser, cnt: usize) void { for (0..cnt) |_| { _ = self.it.next(); } } fn takeAsNumber(self: *Parser, Type: type) !Type { const wordo = self.it.next(); if (wordo) |word| { return std.fmt.parseInt(Type, word, 10); } else { return ParseError.RanOutOfWords; } } }; const Raindeer = struct { speed: usize, flight: usize, rest: usize, }; fn getLines(path: []const u8, alloc: mem.Allocator) !std.ArrayList(Raindeer) { const file = fs.cwd().openFile(path, .{}) catch |err| { std.log.err("Failed to open file {s}", .{@errorName(err)}); return err; }; defer file.close(); var raindeer = std.ArrayList(Raindeer).init(alloc); while (file.reader().readUntilDelimiterOrEofAlloc(alloc, '\n', std.math.maxInt(usize)) catch |err| { std.log.err("Failed to read line: {s}", .{@errorName(err)}); return err; }) |line| { defer alloc.free(line); var words = Parser.fromString(line); words.skip(3); const speed = try words.takeAsNumber(usize); words.skip(2); const flight = try words.takeAsNumber(usize); words.skip(6); const rest = try words.takeAsNumber(usize); try raindeer.append(.{ .speed = speed, .flight = flight, .rest = rest, }); } return raindeer; }