i hate this slightly less
This commit is contained in:
134
03/src/main.zig
134
03/src/main.zig
@@ -34,23 +34,19 @@ test "test input part 2" {
|
|||||||
|
|
||||||
const STATE = enum { waiting, m, u, l, open, d, o, n, open_do, close_do, apo, t, open_dont, close_dont, rewind };
|
const STATE = enum { waiting, m, u, l, open, d, o, n, open_do, close_do, apo, t, open_dont, close_dont, rewind };
|
||||||
|
|
||||||
fn integerUntilDelimiter(reader: anytype, writer: anytype, delimiter: u8, optional_max_size: ?usize) anyerror!void {
|
fn parseIntFromReader(reader: anytype) anyerror!u64 {
|
||||||
if (optional_max_size) |max_size| {
|
const f = try reader.readByte();
|
||||||
for (0..max_size) |_| {
|
if (f < '0' or f > '9') return error.BadCharacter;
|
||||||
const byte: u8 = try reader.readByte();
|
var v: u64 = f - '0';
|
||||||
if (byte == delimiter) return;
|
|
||||||
if (byte < '0' or byte > '9') return error.BadCharacter;
|
|
||||||
try writer.writeByte(byte);
|
|
||||||
}
|
|
||||||
return error.StreamTooLong;
|
|
||||||
} else {
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const byte: u8 = try reader.readByte();
|
const c = try reader.readByte();
|
||||||
if (byte == delimiter) return;
|
if (c < '0' or c > '9') {
|
||||||
try writer.writeByte(byte);
|
break;
|
||||||
|
} else {
|
||||||
|
v = (v * 10) + (c - '0');
|
||||||
}
|
}
|
||||||
// Can not throw `error.StreamTooLong` since there are no boundary.
|
|
||||||
}
|
}
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run2(s: []const u8) !u64 {
|
fn run2(s: []const u8) !u64 {
|
||||||
@@ -60,7 +56,6 @@ fn run2(s: []const u8) !u64 {
|
|||||||
var s_fbs = std.io.fixedBufferStream(s);
|
var s_fbs = std.io.fixedBufferStream(s);
|
||||||
var reader = s_fbs.reader();
|
var reader = s_fbs.reader();
|
||||||
var state = STATE.waiting;
|
var state = STATE.waiting;
|
||||||
var buf: [1024]u8 = undefined;
|
|
||||||
var total: u64 = 0;
|
var total: u64 = 0;
|
||||||
var do_mul: bool = true;
|
var do_mul: bool = true;
|
||||||
|
|
||||||
@@ -68,38 +63,36 @@ fn run2(s: []const u8) !u64 {
|
|||||||
// god i don't know zig at all
|
// god i don't know zig at all
|
||||||
// this is so genuinely awful
|
// this is so genuinely awful
|
||||||
read: while (true) {
|
read: while (true) {
|
||||||
// state transition
|
const err_state = sw: { break :sw switch (state) {
|
||||||
state = sw: {
|
|
||||||
break :sw switch (state) {
|
|
||||||
STATE.rewind => {
|
STATE.rewind => {
|
||||||
try s_fbs.seekBy(-1);
|
try s_fbs.seekBy(-1);
|
||||||
break :sw STATE.waiting;
|
break :sw STATE.waiting;
|
||||||
},
|
},
|
||||||
|
|
||||||
STATE.waiting => {
|
STATE.waiting => {
|
||||||
switch (reader.readByte() catch { break :read; }) {
|
switch (reader.readByte() catch |e| break :sw e) {
|
||||||
'm' => { break :sw STATE.m; },
|
'm' => { break :sw STATE.m; },
|
||||||
'd' => { break :sw STATE.d; },
|
'd' => { break :sw STATE.d; },
|
||||||
else => { break :sw STATE.waiting; },
|
else => { break :sw STATE.waiting; },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
STATE.m => if (reader.readByte() catch { break :read; } == 'u') STATE.u else STATE.rewind,
|
STATE.m => if ((reader.readByte() catch |e| break :sw e) == 'u') STATE.u else STATE.rewind,
|
||||||
STATE.u => if (reader.readByte() catch { break :read; } == 'l') STATE.l else STATE.rewind,
|
STATE.u => if ((reader.readByte() catch |e| break :sw e) == 'l') STATE.l else STATE.rewind,
|
||||||
STATE.l => if (reader.readByte() catch { break :read; } == '(') STATE.open else STATE.rewind,
|
STATE.l => if ((reader.readByte() catch |e| break :sw e) == '(') STATE.open else STATE.rewind,
|
||||||
|
|
||||||
STATE.d => if (reader.readByte() catch { break :read; } == 'o') STATE.o else STATE.rewind,
|
STATE.d => if ((reader.readByte() catch |e| break :sw e) == 'o') STATE.o else STATE.rewind,
|
||||||
STATE.o => switch (reader.readByte() catch { break :read; }) {
|
STATE.o => switch (reader.readByte() catch |e| break :sw e) {
|
||||||
'n' => STATE.n,
|
'n' => STATE.n,
|
||||||
'(' => STATE.open_do,
|
'(' => STATE.open_do,
|
||||||
else => STATE.rewind,
|
else => STATE.rewind,
|
||||||
},
|
},
|
||||||
STATE.n => if (reader.readByte() catch { break :read; } == '\'') STATE.apo else STATE.rewind,
|
STATE.n => if ((reader.readByte() catch |e| break :sw e) == '\'') STATE.apo else STATE.rewind,
|
||||||
STATE.apo => if (reader.readByte() catch { break :read; } == 't') STATE.t else STATE.rewind,
|
STATE.apo => if ((reader.readByte() catch |e| break :sw e) == 't') STATE.t else STATE.rewind,
|
||||||
STATE.t => if (reader.readByte() catch { break :read; } == '(') STATE.open_dont else STATE.rewind,
|
STATE.t => if ((reader.readByte() catch |e| break :sw e) == '(') STATE.open_dont else STATE.rewind,
|
||||||
|
|
||||||
STATE.open_do => if (reader.readByte() catch { break :read; } == ')') STATE.close_do else STATE.rewind,
|
STATE.open_do => if ((reader.readByte() catch |e| break :sw e) == ')') STATE.close_do else STATE.rewind,
|
||||||
STATE.open_dont => if (reader.readByte() catch { break :read; } == ')') STATE.close_dont else STATE.rewind,
|
STATE.open_dont => if ((reader.readByte() catch |e| break :sw e) == ')') STATE.close_dont else STATE.rewind,
|
||||||
|
|
||||||
STATE.close_do => {
|
STATE.close_do => {
|
||||||
do_mul = true;
|
do_mul = true;
|
||||||
@@ -111,32 +104,25 @@ fn run2(s: []const u8) !u64 {
|
|||||||
},
|
},
|
||||||
|
|
||||||
STATE.open => {
|
STATE.open => {
|
||||||
var fbs = std.io.fixedBufferStream(&buf);
|
const num0 = parseIntFromReader(reader) catch |e| break :sw e;
|
||||||
integerUntilDelimiter(reader, fbs.writer(), ',', 1024) catch {
|
try s_fbs.seekBy(-1);
|
||||||
state = STATE.waiting;
|
if ((reader.readByte() catch |e| break :sw e) != ',') break :sw error.BadCharacter;
|
||||||
continue :read;
|
|
||||||
};
|
const num1 = parseIntFromReader(reader) catch |e| break :sw e;
|
||||||
const num0 = std.fmt.parseInt(u64, fbs.getWritten(), 10) catch {
|
try s_fbs.seekBy(-1);
|
||||||
state = STATE.waiting;
|
if ((reader.readByte() catch |e| break :sw e) != ')') break :sw error.BadCharacter;
|
||||||
continue :read;
|
|
||||||
};
|
|
||||||
fbs = std.io.fixedBufferStream(&buf);
|
|
||||||
integerUntilDelimiter(reader, fbs.writer(), ')', 1024) catch {
|
|
||||||
state = STATE.waiting;
|
|
||||||
continue :read;
|
|
||||||
};
|
|
||||||
const num1 = std.fmt.parseInt(u64, fbs.getWritten(), 10) catch {
|
|
||||||
state = STATE.waiting;
|
|
||||||
continue :read;
|
|
||||||
};
|
|
||||||
if (do_mul) {
|
|
||||||
std.debug.print("{d} {d}\n", .{ num0, num1 });
|
std.debug.print("{d} {d}\n", .{ num0, num1 });
|
||||||
total += num0 * num1;
|
if (do_mul) total += num0 * num1;
|
||||||
}
|
|
||||||
|
|
||||||
break :sw STATE.waiting;
|
break :sw STATE.waiting;
|
||||||
},
|
},
|
||||||
};
|
};};
|
||||||
|
|
||||||
|
state = err_state catch |e| switch (e) {
|
||||||
|
error.EndOfStream => { break :read; },
|
||||||
|
error.BadCharacter => STATE.rewind,
|
||||||
|
else => return e
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,47 +136,39 @@ fn run1(s: []const u8) !u64 {
|
|||||||
var s_fbs = std.io.fixedBufferStream(s);
|
var s_fbs = std.io.fixedBufferStream(s);
|
||||||
var reader = s_fbs.reader();
|
var reader = s_fbs.reader();
|
||||||
var state = STATE.waiting;
|
var state = STATE.waiting;
|
||||||
var buf: [1024]u8 = undefined;
|
|
||||||
var total: u64 = 0;
|
var total: u64 = 0;
|
||||||
|
|
||||||
// i tried a state machine.
|
// i tried a state machine.
|
||||||
// god i don't know zig at all
|
// god i don't know zig at all
|
||||||
// this is so genuinely awful
|
// this is so genuinely awful
|
||||||
read: while (true) {
|
read: while (true) {
|
||||||
// state transition
|
const err_state = sw: { break :sw switch (state) {
|
||||||
state = sw: {
|
STATE.waiting => if ((reader.readByte() catch |e| break :sw e) == 'm') STATE.m else STATE.waiting,
|
||||||
break :sw switch (state) {
|
STATE.m => if ((reader.readByte() catch |e| break :sw e) == 'u') STATE.u else STATE.waiting,
|
||||||
STATE.waiting => if (reader.readByte() catch { break :read; } == 'm') STATE.m else STATE.waiting,
|
STATE.u => if ((reader.readByte() catch |e| break :sw e) == 'l') STATE.l else STATE.waiting,
|
||||||
STATE.m => if (reader.readByte() catch { break :read; } == 'u') STATE.u else STATE.waiting,
|
STATE.l => if ((reader.readByte() catch |e| break :sw e) == '(') STATE.open else STATE.waiting,
|
||||||
STATE.u => if (reader.readByte() catch { break :read; } == 'l') STATE.l else STATE.waiting,
|
|
||||||
STATE.l => if (reader.readByte() catch { break :read; } == '(') STATE.open else STATE.waiting,
|
|
||||||
|
|
||||||
STATE.open => {
|
STATE.open => {
|
||||||
var fbs = std.io.fixedBufferStream(&buf);
|
const num0 = parseIntFromReader(reader) catch |e| break :sw e;
|
||||||
integerUntilDelimiter(reader, fbs.writer(), ',', 1024) catch {
|
try s_fbs.seekBy(-1);
|
||||||
state = STATE.waiting;
|
if ((reader.readByte() catch |e| break :sw e) != ',') break :sw error.BadCharacter;
|
||||||
continue :read;
|
|
||||||
};
|
const num1 = parseIntFromReader(reader) catch |e| break :sw e;
|
||||||
const num0 = std.fmt.parseInt(u64, fbs.getWritten(), 10) catch {
|
try s_fbs.seekBy(-1);
|
||||||
state = STATE.waiting;
|
if ((reader.readByte() catch |e| break :sw e) != ')') break :sw error.BadCharacter;
|
||||||
continue :read;
|
|
||||||
};
|
|
||||||
fbs = std.io.fixedBufferStream(&buf);
|
|
||||||
integerUntilDelimiter(reader, fbs.writer(), ')', 1024) catch {
|
|
||||||
state = STATE.waiting;
|
|
||||||
continue :read;
|
|
||||||
};
|
|
||||||
const num1 = std.fmt.parseInt(u64, fbs.getWritten(), 10) catch {
|
|
||||||
state = STATE.waiting;
|
|
||||||
continue :read;
|
|
||||||
};
|
|
||||||
std.debug.print("{d} {d}\n", .{ num0, num1 });
|
std.debug.print("{d} {d}\n", .{ num0, num1 });
|
||||||
total += num0 * num1;
|
total += num0 * num1;
|
||||||
|
|
||||||
break :sw STATE.waiting;
|
break :sw STATE.waiting;
|
||||||
},
|
},
|
||||||
else => STATE.waiting,
|
else => STATE.waiting,
|
||||||
};
|
};};
|
||||||
|
|
||||||
|
state = err_state catch |e| switch (e) {
|
||||||
|
error.EndOfStream => { break :read; },
|
||||||
|
error.BadCharacter => STATE.rewind,
|
||||||
|
else => return e
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user