99 lines
2.7 KiB
Zig
99 lines
2.7 KiB
Zig
|
const std = @import("std");
|
||
|
|
||
|
const input = @embedFile("day07");
|
||
|
const Equation = struct {
|
||
|
result: u64,
|
||
|
values: std.ArrayList(u32)
|
||
|
};
|
||
|
var puzzle: std.ArrayList(Equation) = undefined;
|
||
|
|
||
|
pub fn main () !void {
|
||
|
|
||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||
|
defer {
|
||
|
switch (gpa.deinit()) {
|
||
|
.leak => @panic("leaked memory"),
|
||
|
else => {},
|
||
|
}
|
||
|
}
|
||
|
const gpa_alloc = gpa.allocator();
|
||
|
var arena = std.heap.ArenaAllocator.init(gpa_alloc);
|
||
|
defer arena.deinit();
|
||
|
|
||
|
const alloc = arena.allocator();
|
||
|
|
||
|
try parse_puzzle(alloc);
|
||
|
|
||
|
var result1: u64 = 0;
|
||
|
var result2: u64 = 0;
|
||
|
for(0..puzzle.items.len) |eqi| {
|
||
|
const eq = puzzle.items[eqi];
|
||
|
const val = eq.values.items[0];
|
||
|
const val_cnt = eq.values.items.len;
|
||
|
if(part1(eqi, 1, val_cnt, val)) {
|
||
|
result1 += eq.result;
|
||
|
}
|
||
|
if(part2(eqi, 1, val_cnt, val)) {
|
||
|
result2 += eq.result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const out = std.io.getStdOut().writer();
|
||
|
try out.print("Result 1: {d}\n", .{result1});
|
||
|
try out.print("Result 2: {d}\n", .{result2});
|
||
|
}
|
||
|
|
||
|
fn part1(eqi: usize, vali: usize, endi: usize, cur: u64) bool {
|
||
|
const eq = puzzle.items[eqi];
|
||
|
|
||
|
if(cur>eq.result) return false;
|
||
|
if(vali==endi and cur==eq.result) return true;
|
||
|
if(vali==endi) return false;
|
||
|
|
||
|
|
||
|
const val = eq.values.items[vali];
|
||
|
return part1(eqi, vali+1, endi, cur+val)
|
||
|
or part1(eqi, vali+1, endi, cur*val);
|
||
|
}
|
||
|
|
||
|
inline fn concat(a: u64, b: u32) u64 {
|
||
|
var buf: [20]u8 = undefined;
|
||
|
const str = std.fmt.bufPrint(&buf, "{d}{d}", .{a,b}) catch @panic("lol");
|
||
|
return std.fmt.parseInt(u64, str, 10) catch @panic("lol");
|
||
|
}
|
||
|
|
||
|
fn part2(eqi: usize, vali: usize, endi: usize, cur: u64) bool {
|
||
|
const eq = puzzle.items[eqi];
|
||
|
|
||
|
if(cur>eq.result) return false;
|
||
|
if(vali==endi and cur==eq.result) return true;
|
||
|
if(vali==endi) return false;
|
||
|
|
||
|
const val = eq.values.items[vali];
|
||
|
return part2(eqi, vali+1, endi, cur+val)
|
||
|
or part2(eqi, vali+1, endi, cur*val)
|
||
|
or part2(eqi, vali+1, endi, concat(cur,val));
|
||
|
}
|
||
|
|
||
|
fn parse_puzzle(alloc: std.mem.Allocator) !void {
|
||
|
puzzle = std.ArrayList(Equation).init(alloc);
|
||
|
errdefer puzzle.deinit();
|
||
|
|
||
|
var line_it = std.mem.tokenizeScalar(u8, input, '\n');
|
||
|
while(line_it.next()) |line| {
|
||
|
var res_it = std.mem.tokenizeScalar(u8, line, ':');
|
||
|
|
||
|
const result: u64 = try std.fmt.parseInt(u64, res_it.next().?, 10);
|
||
|
|
||
|
var values = std.ArrayList(u32).init(alloc);
|
||
|
errdefer values.deinit();
|
||
|
|
||
|
var val_it = std.mem.tokenizeScalar(u8, res_it.next().?, ' ');
|
||
|
while(val_it.next()) |val| {
|
||
|
try values.append(try std.fmt.parseInt(u32, val, 10));
|
||
|
}
|
||
|
|
||
|
try puzzle.append(.{.result=result, .values=values});
|
||
|
}
|
||
|
}
|