diff options
Diffstat (limited to 'day1.zig')
-rw-r--r-- | day1.zig | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/day1.zig b/day1.zig new file mode 100644 index 0000000..ed6d7e9 --- /dev/null +++ b/day1.zig @@ -0,0 +1,139 @@ +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}); +} |