const std = @import("std"); const digits = "0123456789"; const words = [_][]const u8{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", }; const w2d = std.comptime_string_map.ComptimeStringMap(u8, .{ .{ "0", 0 }, .{ "1", 1 }, .{ "2", 2 }, .{ "3", 3 }, .{ "4", 4 }, .{ "5", 5 }, .{ "6", 6 }, .{ "7", 7 }, .{ "8", 8 }, .{ "9", 9 }, .{ "zero", 0 }, .{ "one", 1 }, .{ "two", 2 }, .{ "three", 3 }, .{ "four", 4 }, .{ "five", 5 }, .{ "six", 6 }, .{ "seven", 7 }, .{ "eight", 8 }, .{ "nine", 9 }, }); const Input = struct { const Part = enum { pt1, pt2 }; file: []const u8, part: Part, }; pub fn getInput() !Input { var p = std.process.args(); var in: Input = .{ .file = "", .part = .pt1, }; if (!p.skip()) return error.NoProgramName; if (p.next()) |pp| { if (std.mem.eql(u8, pp, "pt1")) { in.part = .pt1; } else if (std.mem.eql(u8, pp, "pt2")) { in.part = .pt2; } else { return error.BadPartSpecified; } } else { return error.NoPartSpecified; } if (p.next()) |pp| { in.file = pp; } else { return error.NoPartSpecified; } return in; } pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const a = gpa.allocator(); const in = try getInput(); var f = try std.fs.cwd().openFile(in.file, .{}); defer f.close(); var c = try f.readToEndAlloc(a, std.math.maxInt(u32)); defer a.free(c); var l = std.mem.splitScalar(u8, c, '\n'); var t: u64 = 0; while (l.next()) |n| { switch (in.part) { .pt1 => { const ix1 = std.mem.indexOfAny(u8, n, digits) orelse return error.NoDigits; const ix2 = std.mem.lastIndexOfAny(u8, n, digits) orelse return error.NoDigits; const v1 = n[ix1] - '0'; // ascii -> number const v2 = n[ix2] - '0'; const x = 10 * v1 + v2; t += x; }, .pt2 => { var ix1: ?usize = null; var v1: u8 = 0; var ix2: ?usize = null; var v2: u8 = 0; for (words) |word| { if (std.mem.indexOf(u8, n, word)) |mix1| { if (ix1) |rix1| { if (mix1 < rix1) { ix1 = mix1; v1 = w2d.get(word) orelse return error.Wtf; } } else { ix1 = mix1; v1 = w2d.get(word) orelse return error.Wtf; } } if (std.mem.lastIndexOf(u8, n, word)) |mix2| { if (ix2) |rix2| { if (mix2 > rix2) { ix2 = mix2; v2 = w2d.get(word) orelse return error.Wtf; } } else { ix2 = mix2; v2 = w2d.get(word) orelse return error.Wtf; } } } //std.log.warn("n {s} v1 {} v2 {}", .{ n, v1, v2 }); if (ix1 == null or ix2 == null) return error.NoDigits; t += (10 * v1) + v2; }, } } try std.fmt.format(std.io.getStdOut().writer(), "sum of calibration values: {}\n", .{t}); }