const std = @import("std");
const path = "data/day10/input.txt";
const Pairs = [4][2]u8{
.{ '(', ')' },
.{ '[', ']' },
.{ '{', '}' },
.{ '<', '>' },
};
const RetType = u64;
fn parseInput() anyerror!RetType {
const input = @embedFile(path);
var lines = std.mem.tokenize(u8, input, "\n");
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var pairs = std.ArrayList(u8).init(allocator);
defer pairs.deinit();
var scores = std.ArrayList(RetType).init(allocator);
defer scores.deinit();
lines: while (lines.next()) |line| {
pairs.clearRetainingCapacity();
chars: for (line) |ch| {
for (Pairs) |p| {
if (ch == p[1]) { // closing pair
const last = pairs.popOrNull();
// XXX: zig compiler error!
if (last == null) {
continue :lines;
} else if (last != p[0]) {
continue :lines;
}
continue :chars;
}
}
try pairs.append(ch);
}
var score: RetType = 0;
var i: usize = pairs.items.len;
while (i > 0) : (i -= 1) {
score *= 5;
score += getValue(pairs.items[i - 1]);
}
try scores.append(score);
}
std.sort.sort(RetType, scores.items, {}, comptime std.sort.asc(RetType));
return scores.items[scores.items.len / 2];
}
fn getValue(ch: u8) RetType {
var ret: RetType = undefined;
switch (ch) {
'(' => ret = 1,
'[' => ret = 2,
'{' => ret = 3,
'<' => ret = 4,
else => unreachable,
}
return ret;
}
pub fn second(allocator: ?std.mem.Allocator) anyerror!RetType {
_ = allocator;
return try parseInput();
}
pub fn main() anyerror!void {
var timer = try std.time.Timer.start();
const ret = try second(null);
const f = timer.lap() / 1000;
try std.testing.expectEqual(ret, @as(RetType, 3122628974));
std.debug.print("Day 10b result: {d} \ttime: {d}us\n", .{ ret, f });
}
test "day10b" {
try std.testing.expectEqual(@as(RetType, 3122628974), try second(std.testing.allocator));
}