1const std = @import("std");
2const Allocator = std.mem.Allocator;
3const TokenIterator = std.mem.TokenIterator;
4
5const NUM_LINES = 5;
6
7pub fn run(_: Allocator, input: []u8) !struct { u64, u64 } {
8 return .{ try part1(input), try part2(input) };
9}
10
11fn part1(input: []u8) !u64 {
12 const NUM_OPERANDS = NUM_LINES - 1;
13
14 var lines = std.mem.tokenizeScalar(u8, input, '\n');
15
16 var operand_strings: [NUM_OPERANDS]TokenIterator(u8, .any) = undefined;
17
18 for (0..NUM_OPERANDS) |i| {
19 operand_strings[i] = std.mem.tokenizeAny(u8, lines.next().?, " ");
20 }
21 var operator: TokenIterator(u8, .any) = std.mem.tokenizeAny(u8, lines.next().?, " ");
22
23 var answer1: u64 = 0;
24 while (operator.next()) |op| {
25 var operands: [NUM_OPERANDS]u64 = undefined;
26 for (0..NUM_OPERANDS) |i| {
27 operands[i] = try std.fmt.parseInt(u64, operand_strings[i].next().?, 10);
28 }
29
30 answer1 += switch (op[0]) {
31 '+' => blk: {
32 var result: u64 = 0;
33 for (operands) |o| result += o;
34 break :blk result;
35 },
36 '*' => blk: {
37 var result: u64 = 1;
38 for (operands) |o| result *= o;
39 break :blk result;
40 },
41 else => unreachable,
42 };
43 }
44
45 return answer1;
46}
47
48fn part2(input: []u8) !u64 {
49 const NUM_OPERAND_LINES = NUM_LINES - 1;
50
51 var lines = std.mem.tokenizeScalar(u8, input, '\n');
52
53 var operand_lines: [NUM_OPERAND_LINES][]const u8 = undefined;
54 for (0..NUM_OPERAND_LINES) |i| {
55 operand_lines[i] = lines.next().?;
56 }
57 const operator = lines.next().?;
58
59 var answer2: u64 = 0;
60
61 var current_operator: u8 = undefined;
62 var result: u64 = 0;
63 for (0..operator.len) |i| {
64 if (operator[i] != ' ') {
65 answer2 += result;
66 current_operator = operator[i];
67 result = switch (current_operator) {
68 '+' => 0,
69 '*' => 1,
70 else => unreachable,
71 };
72 }
73
74 var operand_str: [NUM_OPERAND_LINES]u8 = undefined;
75 for (0..NUM_OPERAND_LINES) |j| {
76 operand_str[j] = operand_lines[j][i];
77 }
78
79 const operand = std.fmt.parseUnsigned(u64, std.mem.trim(u8, operand_str[0..], " "), 10) catch continue;
80
81 switch (current_operator) {
82 '+' => result += operand,
83 '*' => result *= operand,
84 else => unreachable,
85 }
86 }
87
88 answer2 += result;
89
90 return answer2;
91}