You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
2.3 KiB
Zig
92 lines
2.3 KiB
Zig
1 year ago
|
const std = @import("std");
|
||
|
|
||
|
pub fn main() !void {
|
||
|
const file = try std.fs.cwd().openFile("./data.txt", .{});
|
||
|
defer file.close();
|
||
|
|
||
|
var buffer: [40000]u8 = undefined;
|
||
|
_ = try file.readAll(&buffer);
|
||
|
|
||
|
var it = std.mem.split(u8, &buffer, "\n");
|
||
|
|
||
|
var total1: u64 = 0;
|
||
|
var total2: u64 = 0;
|
||
|
|
||
|
while (it.next()) |line| {
|
||
|
std.debug.print("line: {s}\n", .{line});
|
||
|
if (!std.ascii.isAlphanumeric(line[0])) {
|
||
|
continue;
|
||
|
}
|
||
|
var first: ?u8 = null;
|
||
|
var last: ?u8 = null;
|
||
|
|
||
|
// Part 1
|
||
|
for (line, 0..) |char, idx| {
|
||
|
if (std.ascii.isDigit(char)) {
|
||
|
var str = line[idx .. idx + 1];
|
||
|
const parsed = try std.fmt.parseInt(u8, str, 10);
|
||
|
|
||
|
if (first == null) {
|
||
|
first = parsed;
|
||
|
}
|
||
|
last = parsed;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
total1 += (first orelse 0) * 10 + (last orelse 0);
|
||
|
|
||
|
first = null;
|
||
|
last = null;
|
||
|
|
||
|
// Part 2
|
||
|
for (line, 0..) |_, idx| {
|
||
|
if (matchDigit(line[idx..line.len])) |parsed| {
|
||
|
std.debug.print("parsed: {any}\n", .{parsed});
|
||
|
|
||
|
if (first == null) {
|
||
|
first = parsed;
|
||
|
}
|
||
|
last = parsed;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
total2 += (first orelse 0) * 10 + (last orelse 0);
|
||
|
}
|
||
|
|
||
|
std.debug.print("part 1 total: {any}\n", .{total1});
|
||
|
std.debug.print("part 2 total: {any}\n", .{total2});
|
||
|
}
|
||
|
|
||
|
pub fn matchDigit(str: []const u8) ?u8 {
|
||
|
// is the first char a digit? if so, return it
|
||
|
if (std.ascii.isDigit(str[0])) {
|
||
|
const digit = std.fmt.parseInt(u8, str[0..1], 10) catch 0;
|
||
|
return digit;
|
||
|
} else {
|
||
|
const words = [_][]const u8{ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
|
||
|
|
||
|
for (words, 0..) |word, idx| {
|
||
|
if (startsWith(str, word)) {
|
||
|
return @intCast(idx + 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// does the outer string start with the inner string
|
||
|
pub fn startsWith(outer: []const u8, inner: []const u8) bool {
|
||
|
if (outer.len < inner.len) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
for (inner, 0..) |c, idx| {
|
||
|
if (c != outer[idx]) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|