aboutsummaryrefslogtreecommitdiff
path: root/day1.zig
diff options
context:
space:
mode:
Diffstat (limited to 'day1.zig')
-rw-r--r--day1.zig139
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});
+}