1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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});
}
|