You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
11 KiB
237 lines
11 KiB
10 months ago
|
const std = @import("std");
|
||
|
|
||
|
// Cannot believe I'm doing this by hand,
|
||
|
// but both somewhat popular regex libraries for Zig
|
||
|
// have build scripts incompatible with latest Zig 0.11 (released on August 4th, 2023),
|
||
|
// and I'm not into trying to link this with regex.h
|
||
|
|
||
|
fn get_digit_at_start(substr: []const u8) ?u8 {
|
||
|
return switch (substr[0]) {
|
||
|
'0'...'9' => substr[0] - '0',
|
||
|
'o' => if (substr.len >= 3 and substr[1] == 'n' and substr[2] == 'e') 1 else null,
|
||
|
't' => if (substr.len >= 3)
|
||
|
switch (substr[1]) {
|
||
|
'w' => if (substr[2] == 'o') 2 else null,
|
||
|
'h' => if (substr.len >= 5 and substr[2] == 'r' and substr[3] == 'e' and substr[4] == 'e') 3 else null,
|
||
|
else => null,
|
||
|
}
|
||
|
else
|
||
|
null,
|
||
|
'f' => if (substr.len >= 4)
|
||
|
switch (substr[1]) {
|
||
|
'o' => if (substr[2] == 'u' and substr[3] == 'r') 4 else null,
|
||
|
'i' => if (substr[2] == 'v' and substr[3] == 'e') 5 else null,
|
||
|
else => null,
|
||
|
}
|
||
|
else
|
||
|
null,
|
||
|
's' => if (substr.len >= 3)
|
||
|
switch (substr[1]) {
|
||
|
'i' => if (substr[2] == 'x') 6 else null,
|
||
|
'e' => if (substr.len >= 5 and substr[2] == 'v' and substr[3] == 'e' and substr[4] == 'n') 7 else null,
|
||
|
else => null,
|
||
|
}
|
||
|
else
|
||
|
null,
|
||
|
'e' => if (substr.len >= 5 and substr[1] == 'i' and substr[2] == 'g' and substr[3] == 'h' and substr[4] == 't') 8 else null,
|
||
|
'n' => if (substr.len >= 4 and substr[1] == 'i' and substr[2] == 'n' and substr[3] == 'e') 9 else null,
|
||
|
else => null,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
fn get_digit_at_end(substr: []const u8) ?u8 {
|
||
|
const last = substr.len - 1;
|
||
|
return switch (substr[last]) {
|
||
|
'0'...'9' => substr[last] - '0',
|
||
|
'e' => if (substr.len >= 3)
|
||
|
switch (substr[last - 1]) {
|
||
|
'n' => switch (substr[last - 2]) {
|
||
|
'o' => 1,
|
||
|
'i' => if (substr.len >= 4 and substr[last - 3] == 'n') 9 else null,
|
||
|
else => null,
|
||
|
},
|
||
|
'e' => if (substr.len >= 5 and substr[last - 2] == 'r' and substr[last - 3] == 'h' and substr[last - 4] == 't') 3 else null,
|
||
|
'v' => if (substr.len >= 4 and substr[last - 2] == 'i' and substr[last - 3] == 'f') 5 else null,
|
||
|
else => null,
|
||
|
}
|
||
|
else
|
||
|
null,
|
||
|
'o' => if (substr.len >= 3 and substr[last - 1] == 'w' and substr[last - 2] == 't') 2 else null,
|
||
|
'r' => if (substr.len >= 4 and substr[last - 1] == 'u' and substr[last - 2] == 'o' and substr[last - 3] == 'f') 4 else null,
|
||
|
'x' => if (substr.len >= 3 and substr[last - 1] == 'i' and substr[last - 2] == 's') 6 else null,
|
||
|
'n' => if (substr.len >= 5 and substr[last - 1] == 'e' and substr[last - 2] == 'v' and substr[last - 3] == 'e' and substr[last - 4] == 's') 7 else null,
|
||
|
't' => if (substr.len >= 5 and substr[last - 1] == 'h' and substr[last - 2] == 'g' and substr[last - 3] == 'i' and substr[last - 4] == 'e') 8 else null,
|
||
|
else => null,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
fn get_first_digit(str: []const u8) u8 {
|
||
|
for (0..str.len) |i| {
|
||
|
const digit = get_digit_at_start(str[i..]);
|
||
|
if (digit != null) {
|
||
|
return digit.?;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
fn get_last_digit(str: []const u8) u8 {
|
||
|
for (0..str.len) |i| {
|
||
|
const digit = get_digit_at_end(str[0 .. str.len - i]);
|
||
|
if (digit != null) {
|
||
|
return digit.?;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
fn get_value(str: []const u8) u8 {
|
||
|
const first_digit = get_first_digit(str);
|
||
|
const last_digit = get_last_digit(str);
|
||
|
return first_digit * 10 + last_digit;
|
||
|
}
|
||
|
|
||
|
pub fn main() !void {
|
||
|
const stdout = std.io.getStdOut().writer();
|
||
|
|
||
|
const raw_in = std.io.getStdIn();
|
||
|
var buffered_reader = std.io.bufferedReader(raw_in.reader());
|
||
|
var reader = buffered_reader.reader();
|
||
|
|
||
|
var result: u32 = 0;
|
||
|
var line_buffer: [1000]u8 = undefined;
|
||
|
while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |line| {
|
||
|
result += get_value(line);
|
||
|
}
|
||
|
try stdout.print(
|
||
|
"{d}\n",
|
||
|
.{result},
|
||
|
);
|
||
|
}
|
||
|
|
||
|
test "get digit at start" {
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_digit_at_start("one"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_digit_at_start("one!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("on"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 2), get_digit_at_start("two"));
|
||
|
try std.testing.expectEqual(@as(?u8, 2), get_digit_at_start("two!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("tw"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 3), get_digit_at_start("three"));
|
||
|
try std.testing.expectEqual(@as(?u8, 3), get_digit_at_start("three!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("thre"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("thre!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("thr!e"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 4), get_digit_at_start("four"));
|
||
|
try std.testing.expectEqual(@as(?u8, 4), get_digit_at_start("four!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("fou"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 5), get_digit_at_start("five"));
|
||
|
try std.testing.expectEqual(@as(?u8, 5), get_digit_at_start("five!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("fiv"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 6), get_digit_at_start("six"));
|
||
|
try std.testing.expectEqual(@as(?u8, 6), get_digit_at_start("six!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("si"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 7), get_digit_at_start("seven"));
|
||
|
try std.testing.expectEqual(@as(?u8, 7), get_digit_at_start("seven!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("seve"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("s!ven"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("sev!n"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 8), get_digit_at_start("eight"));
|
||
|
try std.testing.expectEqual(@as(?u8, 8), get_digit_at_start("eight!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("eigh"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 9), get_digit_at_start("nine"));
|
||
|
try std.testing.expectEqual(@as(?u8, 9), get_digit_at_start("nine!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("nin"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("!!!!!!!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("t!!!!!!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("f!!!!!!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("s!!!!!!"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("t"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("f"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_start("s"));
|
||
|
}
|
||
|
|
||
|
test "get digit at end" {
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_digit_at_end("one"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_digit_at_end("!one"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("ne"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 2), get_digit_at_end("two"));
|
||
|
try std.testing.expectEqual(@as(?u8, 2), get_digit_at_end("!two"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("wo"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 3), get_digit_at_end("three"));
|
||
|
try std.testing.expectEqual(@as(?u8, 3), get_digit_at_end("!three"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("hree"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("thre!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("thr!e"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 4), get_digit_at_end("four"));
|
||
|
try std.testing.expectEqual(@as(?u8, 4), get_digit_at_end("!four"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("our"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 5), get_digit_at_end("five"));
|
||
|
try std.testing.expectEqual(@as(?u8, 5), get_digit_at_end("!five"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("ive"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 6), get_digit_at_end("six"));
|
||
|
try std.testing.expectEqual(@as(?u8, 6), get_digit_at_end("!six"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("ix"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 7), get_digit_at_end("seven"));
|
||
|
try std.testing.expectEqual(@as(?u8, 7), get_digit_at_end("!seven"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("even"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("s!ven"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("sev!n"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 8), get_digit_at_end("eight"));
|
||
|
try std.testing.expectEqual(@as(?u8, 8), get_digit_at_end("!eight"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("ight"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, 9), get_digit_at_end("nine"));
|
||
|
try std.testing.expectEqual(@as(?u8, 9), get_digit_at_end("!nine"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("ine"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("!!!!!!!"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("!!!!!!e"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("!!!!!ne"));
|
||
|
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("e"));
|
||
|
try std.testing.expectEqual(@as(?u8, null), get_digit_at_end("ne"));
|
||
|
}
|
||
|
|
||
|
test "get first digit" {
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_first_digit("1"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_first_digit("!1"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_first_digit("one"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_first_digit("onetwo"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_first_digit("oone"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_first_digit("onone"));
|
||
|
try std.testing.expectEqual(@as(?u8, 5), get_first_digit("fiveight"));
|
||
|
try std.testing.expectEqual(@as(?u8, 8), get_first_digit("seveight"));
|
||
|
try std.testing.expectEqual(@as(?u8, 0), get_first_digit("seveigh!"));
|
||
|
}
|
||
|
|
||
|
test "get last digit" {
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_last_digit("1"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_last_digit("1!"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_last_digit("one"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_last_digit("twoone"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_last_digit("onee"));
|
||
|
try std.testing.expectEqual(@as(?u8, 1), get_last_digit("onene"));
|
||
|
try std.testing.expectEqual(@as(?u8, 8), get_last_digit("fiveight"));
|
||
|
try std.testing.expectEqual(@as(?u8, 7), get_last_digit("sevene"));
|
||
|
try std.testing.expectEqual(@as(?u8, 0), get_last_digit("!evene"));
|
||
|
}
|