Solved day 3 part 2. Adapted state machine to support do and dont.

Signed-off-by: jmug <u.g.a.mariano@gmail.com>
This commit is contained in:
Mariano Uvalle 2024-12-03 20:44:28 +00:00
parent 467657b4d7
commit 883190e2ee
2 changed files with 142 additions and 46 deletions

View file

@ -0,0 +1 @@
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))

View file

@ -5,38 +5,50 @@ const fmt = std.fmt;
const args = @import("lib/args.zig"); const args = @import("lib/args.zig");
const files = @import("lib/files.zig"); const files = @import("lib/files.zig");
// NOTE: These could probably be better defined, the state machine
// reads a little weird because first and second are technically
// a subset of mul.
const Phase = enum { const Phase = enum {
start, start,
mul, mul,
do,
dont,
first, first,
second, second,
}; };
const State = struct { const State = struct {
prev: u8 = 0, prev: u8 = 0,
phase: Phase = .start, phase: Phase = .start,
num1: [3]u8 = undefined, num1: [3]u8 = undefined,
num1_len: u8 = 0, num1_len: u8 = 0,
num2: [3]u8 = undefined, num2: [3]u8 = undefined,
num2_len: u8 = 0, num2_len: u8 = 0,
// The accumulator of all mul operations we've seen. // Accumulators that never get reset.
total: u64 = 0, total: u64 = 0,
mul_enabled: bool = true,
// restart clear all fields except the running total. // restartInstruction clears instruction related fields while keeping
fn restart(self: *State) void { // the running total and the mul_enabled state.
self.phase = .start; fn restartInstruction(self: *State, phase: Phase) void {
self.phase = phase;
self.prev = 0; self.prev = 0;
self.num1_len = 0; self.num1_len = 0;
self.num2_len = 0; self.num2_len = 0;
} }
fn processInstruction(self: *State) !void { fn processMul(self: *State) !void {
defer self.restartInstruction(.start);
if (!self.mul_enabled) {
return;
}
const num1 = try fmt.parseUnsigned(u32, self.num1[0..self.num1_len], 10); const num1 = try fmt.parseUnsigned(u32, self.num1[0..self.num1_len], 10);
const num2 = try fmt.parseUnsigned(u32, self.num2[0..self.num2_len], 10); const num2 = try fmt.parseUnsigned(u32, self.num2[0..self.num2_len], 10);
self.total += num1 * num2; self.total += num1 * num2;
self.restart();
} }
fn advance(self: *State, next: u8) !void { fn advance(self: *State, next: u8) !void {
@ -46,67 +58,150 @@ const State = struct {
.start => { .start => {
if (next == 'm') { if (next == 'm') {
self.phase = .mul; self.phase = .mul;
} else if (next == 'd') {
self.phase = .do;
} }
}, },
.mul => { .mul => {
switch (self.prev) { switch (next) {
'm' => {
if (next != 'u') {
self.restart();
}
},
'u' => { 'u' => {
if (next != 'l') { if (self.prev != 'm') {
self.restart(); self.restartInstruction(.start);
} }
}, },
'l' => { 'l' => {
if (next != '(') { if (self.prev != 'u') {
self.restart(); self.restartInstruction(.start);
} }
}, },
'(' => { '(' => {
if (next < '0' or next > '9') { if (self.prev != 'l') {
self.restart(); self.restartInstruction(.start);
}
},
'0'...'9' => {
if (self.prev != '(') {
self.restartInstruction(.start);
} else { } else {
self.num1[0] = next; self.num1[0] = next;
self.num1_len = 1; self.num1_len = 1;
self.phase = .first; self.phase = .first;
} }
}, },
else => unreachable, 'd' => {
self.restartInstruction(.do);
},
else => {
self.restartInstruction(.start);
},
} }
}, },
.first => { .first => {
if (next == ',') { switch (next) {
',' => {
self.phase = .second; self.phase = .second;
} else if (next >= '0' and next <= '9') { },
'0'...'9' => {
if (self.num1_len == 3) { if (self.num1_len == 3) {
self.restart(); self.restartInstruction(.start);
} else { } else {
self.num1[self.num1_len] = next; self.num1[self.num1_len] = next;
self.num1_len += 1; self.num1_len += 1;
} }
} else { },
self.restart(); 'd' => {
self.restartInstruction(.do);
},
else => {
self.restartInstruction(.start);
},
} }
}, },
.second => { .second => {
if (next == ')') { switch (next) {
')' => {
if (self.num2_len == 0) { if (self.num2_len == 0) {
self.restart(); self.restartInstruction(.start);
} else { } else {
try self.processInstruction(); try self.processMul();
} }
} else if (next >= '0' and next <= '9') { },
'0'...'9' => {
if (self.num2_len == 3) { if (self.num2_len == 3) {
self.restart(); self.restartInstruction(.start);
} else { } else {
self.num2[self.num2_len] = next; self.num2[self.num2_len] = next;
self.num2_len += 1; self.num2_len += 1;
} }
},
'd' => {
self.restartInstruction(.do);
},
else => {
self.restartInstruction(.start);
},
}
},
.do => {
switch (next) {
'o' => {
if (self.prev != 'd') {
self.restartInstruction(.start);
}
},
'(' => {
if (self.prev != 'o') {
self.restartInstruction(.start);
}
},
')' => {
if (self.prev != '(') {
self.restartInstruction(.start);
} else { } else {
self.restart(); self.mul_enabled = true;
}
},
'n' => {
self.restartInstruction(if (self.prev == 'o') .dont else .start);
},
'm' => {
self.restartInstruction(.mul);
},
else => {
self.restartInstruction(.start);
},
}
},
.dont => {
switch (next) {
'\'' => {
if (self.prev != 'n') {
self.restartInstruction(.start);
}
},
't' => {
if (self.prev != '\'') {
self.restartInstruction(.start);
}
},
'(' => {
if (self.prev != 't') {
self.restartInstruction(.start);
}
},
')' => {
if (self.prev != '(') {
self.restartInstruction(.start);
} else {
self.mul_enabled = false;
}
},
'm' => {
self.restartInstruction(.mul);
},
else => {
self.restartInstruction(.start);
},
} }
}, },
} }