var arena = std.heap.ArenaAllocator.init(allocator.?);
defer arena.deinit();
const file = @embedFile(PATH);
var lines = std.mem.tokenize(u8, file, "\n");
var sum: usize = 0;
while (lines.next()) |line| {
sum += try shuntingYard(arena.allocator(), line);
}
return sum;
}
fn lower(a: u8, b: u8) bool {
const Associativity = enum {
left,
right,
};
const Oper = struct {
prec: u1,
assoc: Associativity,
};
const x: Oper = switch (a) {
'*' => .{ .prec = 0, .assoc = .left },
'+' => .{ .prec = 1, .assoc = .left },
else => unreachable,
};
const y: Oper = switch (b) {
'*' => .{ .prec = 0, .assoc = .left },
'+' => .{ .prec = 1, .assoc = .left },
else => unreachable,
};
if ((x.assoc == .left and x.prec <= y.prec) or
(x.assoc == .right and x.prec < y.prec)) return true;
return false;
}
fn shuntingYard(allocator: std.mem.Allocator, input: Str) !usize {
var stack = std.ArrayList(u8).init(allocator);
defer stack.deinit();
// var output = std.ArrayList(u8).init(allocator);
// defer output.deinit();
var nums = std.ArrayList(usize).init(allocator);
defer nums.deinit();
for (input) |ch| {
switch (ch) {
' ' => {},
'*', '+' => {
while (stack.popOrNull()) |op| {
if (op != '(' and lower(ch, op)) {
// try output.append(op);
switch (op) {
'*' => try nums.append(nums.pop() * nums.pop()),
'+' => try nums.append(nums.pop() + nums.pop()),
else => unreachable,
}
} else {
try stack.append(op);
break;
}
}
try stack.append(ch);
},
'(' => {
try stack.append(ch);
},
')' => {
while (stack.popOrNull()) |op| {
if (op != '(') {
// try output.append(op);
switch (op) {
'*' => try nums.append(nums.pop() * nums.pop()),
'+' => try nums.append(nums.pop() + nums.pop()),
else => unreachable,
}
} else break;
}
},
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9' => {
// try output.append(ch);
try nums.append(try std.fmt.parseUnsigned(usize, &[_]u8{ch}, 10));
},
else => unreachable,
}
}
while (stack.popOrNull()) |op| {
// try output.append(op);
switch (op) {
'*' => try nums.append(nums.pop() * nums.pop()),
'+' => try nums.append(nums.pop() + nums.pop()),
else => unreachable,
}
}
// for (output.items) |item| {
// std.debug.print("{c}", .{item});
// }
// std.debug.print("\n", .{});
return nums.items[0];