Day 10
This commit is contained in:
parent
eaa958fbbf
commit
5b8558cac3
|
@ -0,0 +1,27 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.build.Builder) void {
|
||||||
|
// Standard target options allows the person running `zig build` to choose
|
||||||
|
// what target to build for. Here we do not override the defaults, which
|
||||||
|
// means any target is allowed, and the default is native. Other options
|
||||||
|
// for restricting supported target set are available.
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
|
// Standard release options allow the person running `zig build` to select
|
||||||
|
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||||
|
const mode = b.standardReleaseOptions();
|
||||||
|
|
||||||
|
const exe = b.addExecutable("day10", "src/main.zig");
|
||||||
|
exe.setTarget(target);
|
||||||
|
exe.setBuildMode(mode);
|
||||||
|
exe.install();
|
||||||
|
|
||||||
|
const run_cmd = exe.run();
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
if (b.args) |args| {
|
||||||
|
run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
{{<{{{{([{[([[()<>]{<>{}}]<([]())(()<>)>)((({}())[()[]])<<[][]>[{}[]]>)]{{(<{}<>>{<><>}]([<>[]]<
|
||||||
|
[(<{{[{(<({{<<[]()><<>{}>>([<>[]]{<><>})}})>)}]}}>[{(<{({[{[[({}())((){})]({{}[]})]<<[<>{}]([][])>({<>()}
|
||||||
|
(({<{[{({(([[([]())({}())]]({[[]{}]([][]))<((){})<{}<>>>))[(([<>[]]<[]>)(([]{}){{}{}}))])})[({<[{
|
||||||
|
([{{[([<({<<<([]())[()[]]>{<()[]>[[]()]}>[{<[]{}><[]>>{<<>()>{[]()}}]>[[[[[]{}]([]<>)]<{<>{}}
|
||||||
|
[[((<({<(<{<<{{}()}{[][]}>[((){})]>}>{((<({}<>)<{}()>>[[<>()]])<<<[][]><<>[]>>{<{}[]>(<>())}>)<{[[{
|
||||||
|
[{<{{{{<([{[(<[]<>>(<>[])){({}<>)([]<>)}]{{([][])[<>{}]}{<[]<>>(<>{})}}}])<<{[<[<>{}]<(){}>>{<{}<>><<>
|
||||||
|
(({({([(<[[([[{}{}]([]<>}][(<>()){(){}}])]](({{{{}<>}<{}[]>}([{}[]][(){}])}[(<[]{}>({}()))<<<><>>>])<[{
|
||||||
|
[{<((<{(<{<<{[()()](()<>)}<({}[])([]<>)>>{(<<><>>[[]{}])[[[]()](<>[])]}>{[[({}<>)([]<>)][[{}[]
|
||||||
|
{<{<{{(<[[{[[({}[])[()[]]]([()<>][{}[]])]<<({}())[{}{}]><[<>[]](<><>)>>}(([([]{})((){})]((<>)([]{}))))]<{<<<
|
||||||
|
<{(<<(<[<{<[{[<>[]][{}{}]}{{()<>}{<><>}>]>[<(([]{})[[]])>]}<[<([{}{}][<><>]){([]{})}>]({<{<>()}>{
|
||||||
|
{[[<{{{<<<[<((()<>)({}{}))<{{}()}>>]<((([]{}){{}<>})[{{}<>}([]{})])({{()[]}[[]()]}[{{}()}({
|
||||||
|
<[[[{{([{[({[<{}[]>[{}()]]{<()>}}({<()()>}<<<>()>{[]}>))]((({({}[])>{[(){}]{<><>}})(({()[]}[()<>]
|
||||||
|
[([([([<[{{<[[{}[]]{<>{}}][<{}>(()[])]>[({<>()}(()[])){<[][]>{()[]}}]}}<{(({()}([]()))(([]())<()[]>))<((<>{}
|
||||||
|
<{[{(({([([[{((){})[[]]>{{{}[]}[<>()]}]])]{([([<[]{}>((){})]<[()<>]<()()>>)][<<{<>{}}{<><>
|
||||||
|
[[{{(([{(({[[{{}[]}]][<<<>()>({}{})>[[{}<>]{{}<>}]]}[(({{}}{[][]}){[{}{}][<>[]]})(<<<>{}><<><>>>)])<[
|
||||||
|
[[{([<<([[<(<{<>()}<[][]>>{[<>[]]{()[]}}){[<[][]><{}()>][([]())<<><>>]}>]((<<[(){}][(){}]><([])>>))
|
||||||
|
[{[<{(([(([([(<>[]}(<>{})][<{}[]>[()[]]])<{[{}<>]<[]<>>}{{[]<>}{{}{}}}>]<<{[<>{}](<>())}{{()[]}{<>{}}}>[
|
||||||
|
{({<[(((<{<<[[()<>]]<({}<>)>>>[<({[]<>}{()<>})[[()<>][<><>]]>({[{}[]]({}<>)}[<(){}>(<>())])]}><[{<[[<>
|
||||||
|
<(((({{(<({[<<[]<>>>([()()]{<>()})][<[{}{}]{<>()}>{{{}{}}[[][]]}]}{(<<<><>>(()<>)>(<<>()>[()[]]))
|
||||||
|
[<{{[{[[[<(({<()()>[(){}]}[([]())[(){}]]))>{[<[[[]]<[][]>]{[[][]](()())}>[(<<>()>{[]<>})(({}())<{}[]>)
|
||||||
|
(<[[((<<({[(([()[]]([]<>)){{(){}}})]{<(<<><>><[]{}>)<<{}<>]([]<>)>>}}){(<{<{[]{}}[{}<>]>}>{({(<><>)<()[]>}{((
|
||||||
|
{[{((<{<<<<([<[]{}>[[][]]]<[[]()][<>[]]>)[[<{}[]>{{}()}](<()<>>[<>[]])]>>[{([<()[]>{{}[]}](({}{}
|
||||||
|
(<([<((<{[<<(((){})<<><>>)<[{}()]<[]<>>}>[([[]{}](()[]))]>[<{({}()){{}()}}>[(([]<>)({}[])){
|
||||||
|
{((((<(({[(<{<()]([][])}>){[<[[][]]>]<{{{}<>}[[][]]}>}]}[<{([{[]{}}]{[(){}]<<>()>})[(<()<>>{()<>
|
||||||
|
<<{([{<[[[<{([[]<>]){[<>()][(){}]}}[{(()[])[()[]]}]>][{{[{{}[]}<()<>>]>[[{(){}}[<>[]]][[<>[]]({}()
|
||||||
|
<((<[<(([<[{({<><>}(()[]))}]<[<[{}()]<()[]>>(<()()>)][[(<>())<()())]<{<>}<{}>>]>>({{<<<>[]><<>(
|
||||||
|
[({{{{{{(([[<<()()><<>[]>>[{[]<>}]]{(<{}<>>(()[]))<<[][]>(()())>}]([<({}()><[][]>>]<{[[][]]<[]<>>}(
|
||||||
|
(<(<{{<[{{{[<[<>[]]<[]{}>>[{<>{}}{()()}]]{<<{}()>(<>())>[[{}[]]]}}}}][{([{[([]{})<()[]>][[<>{}]{()[]}]}(([()
|
||||||
|
{[<<(<<<{[<<<<[]<>><()[]>>[({}[])[[]<>]]><((<><>)[{}<>])[{{}{}}[[]()]]>>{{{[<><>]<<>()>}[<[]{}>([][])]
|
||||||
|
<(<{<(<({[[{((()[])[{}<>])([<>()]>}{[({}{})[(){}]]<[()<>]({}[])>}]{[<{[]{}}><{[]{}}[[][]]>][[<{}<>><()[]>]<[
|
||||||
|
{<({[<((<<<{{([]<>}{<><>}}<{<>{}}[[]<>]>}>{<[{{}}(()())]>}>(<<{[(){}]<()[]>}({(){}}[()<>])>[<<<>[]>{[]
|
||||||
|
{(({<{{{{{((<{[]<>>(<>{})>[[<>()]])<<(()())[<>]><[(){}][{}{}]>>)}({([[[]]]{<{}{}><()[]>})<{[(){}][[]()]}>
|
||||||
|
<<[<<[((({[[(<{}[]>({}())){[()()]}][{{<>{}}<<>()>}[<{}[]>[<>[]]]]]{<(([]())([]()))>{([()()]<<>[]>)[<
|
||||||
|
{([<<<({((<{{[<>[]][<>{}]}<<<>[]>[[][]]>}[{[()[]]<<>[]>}<[{}{}]<<><>>>]>({[<[]<>>]<<()()>([][])>}(((<
|
||||||
|
(<{<((<{[[<[(<[]{}>{<>{}})][<([][])[{}<>]>[<{}<>>]]><<[(<>[])[{}<>]]{<{}{}><{}[]>}>(<([]<>){()[]}>)>]]}{({[<(
|
||||||
|
[{{(({<<<<{{<({}()){{}{}}>[(()[])]}[([(){}]{<>[]})[(<>())[{}]]]}>[<<<{[]{}}{{}{}}>]{<[{}<>]>{(()())}}>[{(<[]<
|
||||||
|
{[<<{<[[({{<<{()[]}<<><>>>([[]<>>[{}[]])>}[[[([]<>)[<>{}]]]<<[<>()](<>{})>>]})(((({({}[])<<><>>}([<>])))((<
|
||||||
|
[{(({({<({(<{{[][]}({}<>)}[{()()}{[][]}]>(((<><>)(<>()))([{}()][{}()])))([{[[]()]<[]{}>}{(
|
||||||
|
{<{{<[<<[(<([({}())[{}()]]{{{}<>}<[]>}){[((){})<[][]>]<([]())({}[])>}>{<(((){})[()<>])(<()[]>[(){}]
|
||||||
|
{({({<{{(<([<[<><>]((){})>{{()[]}<<>{}>}]{[(<>())<{}[]>][{()<>}[[]()]>})>[[<{([])[()[]]}><<[(){}]({}())>>]{
|
||||||
|
(<{{(<<<{(<(({<><>}{()[]})<[{}[]]([]())>)([(()<>)[[]<>]]({[]()}{{}{}}))))[(<{{()[]}<()[]>}((<><>))>[[
|
||||||
|
<<[<([{<<[[({<[]<>><<>()>}{([]<>)[[]<>]}){[<{}{}><()[]>]<{<>()}{<>()}>}]{{<({}{})>})]>[<({<
|
||||||
|
(<<[[({[({(<{{[]{}}<[]{}}}>[<<()<>><{}<>>>(<()()>{{}<>})])}{<({({}[])<()>}<([]())<{}<>>>)<<[(
|
||||||
|
[<(<{(([(<([[<<>{}>(<>{})]](((()[])[[]()])[[{}<>]({}{})]))><<{<([]<>){[][]}>[{<>[]}<()<>>]}>(<((<>[]){()<>}
|
||||||
|
[<{[[{(([[{[{<[]<>>(<>[])}<<<>()>{{}{}}>][({[][]}<<>>){(<>[])[<><>]}]}(([([][])(<>[])]{(()())}))](<<{
|
||||||
|
((<{<<([<[(([{()()}((){})][<()[]><()[]>])<{({}<>){{}<>}}>)[{(<<><>>)<{{}[]}>}({(<>()){()}}{([
|
||||||
|
[({{{{((([({{(<>[])[[]<>]}([{}])}(({<><>}{<>()})[[{}[]]]))<{[[<>{}](()[])](<()<>>{[]()})}{{<()()
|
||||||
|
[<[<({[[({[[[<<>[]>]({[]}[<><>])]{[[()<>]([]())]<({}{})[[][]]>}]}<<(([()()]<()<>>)<{()()}[()[]]>
|
||||||
|
{<([[<[<<(([<(()[])(()<>)>{[<><>](<>[])]]{({{}})}){<((<><>)<{}<>>)((()[])[[]()])>})<<(<(())(
|
||||||
|
<[<((<{(<[[({{{}()}({}{})}}<[[()<>]]<[()()][<>]>>]<[([()()]({}<>))[<{}()>([]<>)]]>][{[[(()())[()]][[<>[]
|
||||||
|
[{(<(<[((<{(({(){}}[()[]])<{[][]}(<>{})>)[(<<><>>[()[]]]{[{}[]]{()<>}}]}><[<[[{}()](()[])][(<>()){<>()}]>[{
|
||||||
|
([({<({{{[[<[{{}<>}([][])]{[(){}]{()<>}}>][{[{[]<>}][<{}()>]}]]}{((<[{{}[]}(()()))[{<>[]}]>({(<>{})<[]<>>}
|
||||||
|
{[({[<[([(<{((<>{})<{}{}>)}(<[[]()]<{}{}>>({{}[]}{[]<>}))><[((()[])(())){([]<>)[()[]]}]<({()
|
||||||
|
[(<<<([{[[[<<<<>>{{}<>}>[{[]()}]>[([[]{}]{[]<>}){[<>()]}]]]]}]<<((<([{[][]}<{}<>>]<[[]{}][[]<>])){{[<>[]
|
||||||
|
{[{{[[{{[<[<<{{}<>}<[]{}>><<()[]>[<>[]]>>[([<>{}](()()))]]>{({([{}[]](<><>))<<(){}>(<>{})>}({([]<>)[{}[])}(<<
|
||||||
|
<{([[{<[<{{([(<>{})[<>()]]){{[()[]]([])}}}[{<((){})([]())>}(<{[][]}<<>{}>>[[[][]]<()()>])]}>[
|
||||||
|
{(<[({{(<<<{[(()())]<[<>[]][{}{}]>}[[<()[]>{[][]}]]>(<((<>())[()[]]){{()[]}{[][]}}>({{[]<>}<[][]>}(<[]{}
|
||||||
|
<{{[{((((<[{({[]{}}<(){}>)}[[{[][]}<<>{}>]<<[][]>{[]}>]]>{{([((){})<<>{}>]{{()()}})<[<<>()>](<<>>[()
|
||||||
|
<([({(<<<{[<{(()<>)(<>[])}([<>]{<>{}})>]<(<<<><>><{}()>>[([][]){[]<>}])>}{[([[[]<>]{(){}}]<[{}<>]{{}<>}
|
||||||
|
{<<<[{[(<[([([[]()]<()[]>)(([]())({}[]))]<[[()<>]]<[(){}]<[][]>>>)(<{<[][]>)<(()<>)<{}[]>>
|
||||||
|
{[[<[[<(<[[{(<()<>>)<{{}<>}[[][]]>}<<(()()){[]{}}>{<[]()>>>]]>)({<<<<[{}{}]{<>()}>{<<><>>([]{})}>>[([<()()>(
|
||||||
|
[[[{({{({[{[(({}())(<>[]))<<<>[]>[[]<>]>]<<<()()><<>>>[({}())(<>[])]>}[({<(){}>({}{})}[[{}()]]){[[[]<>
|
||||||
|
<(((<<[{[[<({({}<>)[{}()]}[{[]{}}([]())]){([[]<>]<[]<>>)[(()[])[{}[]]]}>(<<<{}[]><()[]>)>[[<{}(
|
||||||
|
[<<{[{{<<[[{<<()[]>(())><<{}()][<>()]>}({[{}{}][<>()]}<([]())([])>)]({{{[][]}[<>{}]}<[()]{{}()}>}(({
|
||||||
|
{([(<[[<(<<<(<<><>><{}<>>)({{}()}[<>()])>{([(){}][[][]]){[<><>]{<><>}}}>>(({(<<><>><()<>>){{()<>}{(){}}}}
|
||||||
|
[(<([[[([(({[[<>[]]]}))([{{[{}()]([]<>)}{{<>[]}[[][]]}}(<([]())>[([]{}){()<>}])][<{<()[]><()()>}>{<([
|
||||||
|
{([[<<[[<[[[<[{}[]]{[]<>}>[<{}()>{<>[]}]]]<[<{[][]}(<>[])>[[{}[]]<[][]>]][((()[])[<>{}]){{{}()}[(){}]}]>]>
|
||||||
|
{[[[<<{{[<<<([{}[]]<<>[]>)([()]<{}{}>)>({<<>{}>(()[])})>[(((<><>>{<>{}})<<<>[]>[[]()]>)({(()(
|
||||||
|
[[[{<<(({{[((<{}<>>[{}])({<>{}}<{}{}>))[(<{}()>(<>{}))(<<><>>{{}{}})]]({{<()>}}(<{(){}](<><>)
|
||||||
|
(({{[[[<[{<{[<{}()><<>{}>]}({[[]()]<{}[]>])>}[<{{(<><>)<{}()>}{{{}<>}{{}[]}}}(([<>[]]([][]))
|
||||||
|
<[<<{({[(<(<{({}<>)<[][]>}{(()[])({}[])}>{(<{}{}>>})>([<<<<>{}>((){})>[(()())[[]()]]><{[{}<>]<<>
|
||||||
|
[{<{[(<[[[{({({}<>)(()<>)}{<[][]>})}{[<[()[]]{[]<>]>{<{}()>(()())}]{[<()()>{<>[]}]<[<><>]>}}]
|
||||||
|
({{<{[[[([({{<<>()>(()<>)}(<{}()><()[]>)}<[[{}()]<{}[]>]{((){}){{}[]}}>)[([{<><>}<()<>>][(<><>)(()())]
|
||||||
|
(({<{{{[([{<<<{}{}>{[]{}}>([<>[]]{[]{}})>}{<<{[]{}}[[]{}]>{<<>{}>([]())}><(<(){}>({}[]))[(<>[])(()<>)]>
|
||||||
|
<[<(<{[[<([({[<>()][<>{}]}{{()()}[<><>]})]<[[<[]()>]<[{}<>]([])>]{<[<>[]]<<>()>]((<>())[<>{}])}>)([{<[[][]]
|
||||||
|
<<{{((({<<[[<{<>()}(()())>[(()[])[()<>]]]{({{}[]}[<><>])}]<{<<<><>>{{}[]}>}<[<[][]>[{}[]]](<()()>{[]{}})
|
||||||
|
[<<{<{([{(({[{()[]}{()}][({}{})(()[])]}{({<>()})({[]()}({}[]))}))}][[[([[{<>[]}[{}[]]][[<><>]<()[]>]]([
|
||||||
|
[([[{{<(<[{(<<()<>>><[[]()]{()()}>)<(({}()){[]<>})>}]>)>{<[<{{((()())({}<>)>{([]{}){{}<>}}}}<({
|
||||||
|
((<<{(<[(<[[<({})>[{[][]}[<>[]]]]]>)]>)}([(<[[([(([][]))[{{}()}([][])]][((<><>){[]()})])]]<<(
|
||||||
|
<<<<(<{[{[({<{(){}}[<>]>[<[]<>>{<>()}]}[<[<>()]>{[[]<>][{}[]}}])(<{<(){}>[{}{}]}<(()<>)<()[]>>>)][<{{<[]<
|
||||||
|
(([[<{[({{{[<<<><>>(()())>({[]<>}(<>()))]{<[<>()][{}{}]>([[]()]((){}))}}((<({}{})[<>]>([<>()]{(){}})))}[<{([<
|
||||||
|
{[([<<[([[<[(<[]()>{()[]})<{<>()}{(){}}>]><<{<[][]><{}()>}(<[]<>>([]<>])>>]{[[<<{}<>>({}[]
|
||||||
|
{{[<<(<({[<<{<[]<>>}{(<>())}>[{[<>]{(){}}}]>]}{{{<([()<>]{<>{}})(<()[]>[[]()])><[<<>[]>({}{})]((()())[{
|
||||||
|
[{{[<{<<{{<[<<()()>[{}]>([{}{}]({}{}))]{(<[][]>([][]))(([]{})<<>[]>)}>}({{<{<>[]}[<>()]>(({
|
||||||
|
[<{[(<<[<<(([[<>[]]][([]())({}<>}])){(({[]()}{()<>})[<[]{}>(<><>)])[<[{}[]][{}{}]><{(){}}<{}{}>>]}>({<<[[]()
|
||||||
|
[({[<<<({<({({{}<>}[[]{}])}({({}<>)<<>[]>}))([<{(){}}>])>}{<{[[{{}{}}(<>{})]]<[[()[]]<<><>>]{[<><>]<{}()>
|
||||||
|
[<{<<<<(([([[{{}()}[<>]][((){})[[]{}]]](({[]()}[[]()])[{[]()}(<>[])])){[{<<><>>{{}<>}}<{()[]}[[]
|
||||||
|
[{({<(((<({{({[]()}))[((()())<[][]>)<{<>{}}(<><>)>]}{[<[[][]](<><>)>][[{<>{}}[<>{}]](<<>[]>{[][]})]})>)))>}
|
||||||
|
[[{[[{({[([(<<<>[]>[<><>]>([{}()][<>()]))<<[<>{}]{{}<>}>[<<>{}>([]{}]]>])<(<(<[]()>)[(()[])
|
||||||
|
<([(<<[<<({{{([]{})}[{()<>}<[]()>]}}{(<{[]{}}([][])>)})[[[<[[][]]<<><>>><{{}{}}(<><>)>]<<(()())[(){}]>{
|
||||||
|
[(<{[{({[({<{<{}[]><<>()>}{<{}()>[[][]]}><<{{}()}{(){}}>>}[<{{<>{}}{()())}>]){[<[{()()}<[]()>]><[[{
|
||||||
|
<{<[{([([<<[<[<>()]{(){}}>][({{}[]}((){}))[<[][]><()<>>]]>>{{{<{<><>}{(){}}>({<><>}<()))}({<()><{}[]>}(<(
|
||||||
|
({((([[{([<[(([]{})){[()<>][<><>]}]>{[<<{}{}><()[]>>(<<>>)]({<<><>>[<>{}]}{<[]{}><<>{}>})}])[(<(([<><>][{}{
|
||||||
|
<[<(([(({([[<(()[])[[]{}]>{<<>{}>(<>{})}]]([([<>{}]{[]{}})][{<()>{()[]}}(({}[])(<>[]))]))})({{[(({(){}}[<>
|
|
@ -0,0 +1,424 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn main() anyerror!void {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = &arena.allocator;
|
||||||
|
|
||||||
|
// Read our input
|
||||||
|
var f = try std.fs.cwd().openFile("input", .{});
|
||||||
|
defer f.close();
|
||||||
|
var contents = try f.readToEndAlloc(alloc, std.math.maxInt(u32));
|
||||||
|
defer alloc.free(contents);
|
||||||
|
|
||||||
|
var lit = std.mem.tokenize(contents, "\n");
|
||||||
|
var corrupt_score: u32 = 0;
|
||||||
|
var completion_scores = std.ArrayList(u64).init(alloc);
|
||||||
|
defer completion_scores.deinit();
|
||||||
|
var line_id: usize = 0;
|
||||||
|
while (lit.next()) |line| {
|
||||||
|
//std.log.debug("{any}", .{nodes});
|
||||||
|
var tree = try line_to_tree(alloc, line, line_id);
|
||||||
|
corrupt_score += tree.corrupt;
|
||||||
|
if (tree.corrupt == 0) {
|
||||||
|
// Try completion
|
||||||
|
var score = try tree.autocomplete();
|
||||||
|
std.log.debug("Line {} autocompletion score {}", .{line_id, score});
|
||||||
|
try completion_scores.append(score); // score
|
||||||
|
}
|
||||||
|
line_id += 1;
|
||||||
|
}
|
||||||
|
std.log.info("[Part 1] Sum of corrupt line scores: {}", .{corrupt_score});
|
||||||
|
std.sort.sort(u64, completion_scores.items, {}, comptime std.sort.asc(u64));
|
||||||
|
|
||||||
|
std.log.info(
|
||||||
|
"[Part 2] Completion scores: {}",
|
||||||
|
.{completion_scores.items[completion_scores.items.len/2]}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_to_tree(alloc: *std.mem.Allocator, line: []const u8, id: usize) !Tree {
|
||||||
|
var tkzr = Tokenizer.init(line);
|
||||||
|
var tkns = std.ArrayList(Token).init(alloc);
|
||||||
|
var corrupt_score: u32 = 0;
|
||||||
|
while (true) {
|
||||||
|
var tkn = tkzr.next();
|
||||||
|
if (tkn.tag != .eos) {
|
||||||
|
try tkns.append(tkn);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//std.log.debug("{} tokens", .{tkns.items.len});
|
||||||
|
var nodes = std.ArrayList(Node).init(alloc);
|
||||||
|
try nodes.append(.{
|
||||||
|
.index = 0,
|
||||||
|
.parent = 0,
|
||||||
|
.tag = .root,
|
||||||
|
.start_index = 0,
|
||||||
|
});
|
||||||
|
var current_node: usize = 0;
|
||||||
|
for (tkns.items) |tkn, index| {
|
||||||
|
switch(tkn.tag) {
|
||||||
|
.r_paren,
|
||||||
|
.r_brace,
|
||||||
|
.r_bracket,
|
||||||
|
.r_angle_bracket,
|
||||||
|
=> {
|
||||||
|
if (current_node == 0) {
|
||||||
|
std.log.debug("Closing token before opening token: {}",
|
||||||
|
.{tkn});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//std.log.warn("Current node: {}", .{current_node});
|
||||||
|
nodes.items[current_node].end_index = index;
|
||||||
|
if (nodes.items[current_node].tag != token_tag_to_node_tag(tkns.items[index].tag)) {
|
||||||
|
std.log.warn(
|
||||||
|
"Line {}: mismatched tags: {} != {}",
|
||||||
|
.{id, tkns.items[nodes.items[current_node].start_index].tag,
|
||||||
|
tkns.items[index].tag}
|
||||||
|
);
|
||||||
|
corrupt_score += switch(tkns.items[index].tag) {
|
||||||
|
.r_paren => @as(u32, 3),
|
||||||
|
.r_bracket => @as(u32, 57),
|
||||||
|
.r_brace => @as(u32, 1197),
|
||||||
|
.r_angle_bracket => @as(u32, 25137),
|
||||||
|
else => @as(u32, 0),
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current_node = nodes.items[current_node].parent;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.eos,
|
||||||
|
.invalid,
|
||||||
|
=> unreachable,
|
||||||
|
else => {
|
||||||
|
// Opens a new node
|
||||||
|
var node = Node {
|
||||||
|
.index = nodes.items.len + 1,
|
||||||
|
.parent = current_node,
|
||||||
|
.start_index = index,
|
||||||
|
.tag = switch(tkn.tag) {
|
||||||
|
.l_paren => .paren,
|
||||||
|
.l_brace => .brace,
|
||||||
|
.l_bracket => .bracket,
|
||||||
|
.l_angle_bracket => .angle_bracket,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try nodes.append(node);
|
||||||
|
try nodes.items[current_node].children.append(alloc, nodes.items.len - 1);
|
||||||
|
current_node = nodes.items.len - 1;
|
||||||
|
//std.log.warn("Start new node from token index {} at {}: {any}",
|
||||||
|
// .{index, current_node, node});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Tree {
|
||||||
|
.nodes = nodes,
|
||||||
|
.tokens = tkns,
|
||||||
|
.corrupt = corrupt_score,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Tree = struct {
|
||||||
|
nodes: std.ArrayList(Node),
|
||||||
|
tokens: std.ArrayList(Token),
|
||||||
|
corrupt: u32 = 0,
|
||||||
|
|
||||||
|
pub fn autocomplete(self: *Tree) anyerror!u64 {
|
||||||
|
// I guess we want to traverse the tree, adding in tokens for end_index
|
||||||
|
// where necessary
|
||||||
|
var node = self.nodes.items[0];
|
||||||
|
var score: u64 = 0;
|
||||||
|
for (node.children.items) |n| {
|
||||||
|
score += try self.complete(&self.nodes.items[n], score);
|
||||||
|
}
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn complete(self: *Tree, node: *Node, score: u64) anyerror!u64 {
|
||||||
|
var s = score;
|
||||||
|
for (node.*.children.items) |n| {
|
||||||
|
s += try self.complete(&self.nodes.items[n], score);
|
||||||
|
}
|
||||||
|
if (node.*.end_index) |ei| {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try self.tokens.append(.{
|
||||||
|
.tag = switch(node.*.tag) {
|
||||||
|
.paren => .r_paren,
|
||||||
|
.brace => .r_brace,
|
||||||
|
.bracket => .r_bracket,
|
||||||
|
.angle_bracket => .r_angle_bracket,
|
||||||
|
else => .invalid,
|
||||||
|
},
|
||||||
|
.loc = .{.start = 0, .end = 0}, // fake
|
||||||
|
});
|
||||||
|
node.*.end_index = self.tokens.items.len - 1;
|
||||||
|
s *= 5;
|
||||||
|
s += switch(node.*.tag) {
|
||||||
|
.paren => @as(u64, 1),
|
||||||
|
.brace => @as(u64, 3),
|
||||||
|
.bracket => @as(u64, 2),
|
||||||
|
.angle_bracket => @as(u64, 4),
|
||||||
|
else => @as(u64, 0),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Node = struct {
|
||||||
|
index: usize,
|
||||||
|
parent: usize,
|
||||||
|
children: std.ArrayListUnmanaged(usize) = .{},
|
||||||
|
tag: Tag,
|
||||||
|
start_index: usize,
|
||||||
|
end_index: ?usize = null,
|
||||||
|
pub const Tag = enum {
|
||||||
|
root,
|
||||||
|
paren,
|
||||||
|
brace,
|
||||||
|
bracket,
|
||||||
|
angle_bracket,
|
||||||
|
invalid,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fn token_tag_to_node_tag(t: Token.Tag) Node.Tag {
|
||||||
|
switch(t) {
|
||||||
|
.l_paren,
|
||||||
|
.r_paren,
|
||||||
|
=> return .paren,
|
||||||
|
.l_brace,
|
||||||
|
.r_brace,
|
||||||
|
=> return .brace,
|
||||||
|
.l_bracket,
|
||||||
|
.r_bracket,
|
||||||
|
=> return .bracket,
|
||||||
|
.l_angle_bracket,
|
||||||
|
.r_angle_bracket,
|
||||||
|
=> return .angle_bracket,
|
||||||
|
else => return .invalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Token = struct {
|
||||||
|
tag: Tag,
|
||||||
|
loc: Loc,
|
||||||
|
|
||||||
|
pub const Loc = struct {
|
||||||
|
start: usize,
|
||||||
|
end: usize,
|
||||||
|
};
|
||||||
|
pub const Tag = enum {
|
||||||
|
l_paren,
|
||||||
|
r_paren,
|
||||||
|
l_brace,
|
||||||
|
r_brace,
|
||||||
|
l_bracket,
|
||||||
|
r_bracket,
|
||||||
|
l_angle_bracket,
|
||||||
|
r_angle_bracket,
|
||||||
|
eos,
|
||||||
|
invalid,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn lexeme(tag: Tag) ?[]const u8 {
|
||||||
|
return switch (tag) {
|
||||||
|
.l_paren => "(",
|
||||||
|
.r_paren => ")",
|
||||||
|
.l_brace => "{",
|
||||||
|
.r_brace => "}",
|
||||||
|
.l_bracket => "[",
|
||||||
|
.r_bracket => "]",
|
||||||
|
.l_angle_bracket => "<",
|
||||||
|
.r_angle_bracket => ">",
|
||||||
|
else => "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Tokenizer = struct {
|
||||||
|
index: usize,
|
||||||
|
buffer: []const u8,
|
||||||
|
|
||||||
|
pub fn init(buffer: []const u8) Tokenizer {
|
||||||
|
return Tokenizer{
|
||||||
|
.buffer = buffer,
|
||||||
|
.index = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(self: *Tokenizer) Token {
|
||||||
|
const start_index = self.index;
|
||||||
|
var result = Token {
|
||||||
|
.tag = .eos,
|
||||||
|
.loc = .{
|
||||||
|
.start = start_index,
|
||||||
|
.end = undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
while (self.index < self.buffer.len) : (self.index += 1) {
|
||||||
|
const c = self.buffer[self.index];
|
||||||
|
switch (c) {
|
||||||
|
'(' => {
|
||||||
|
result.tag = .l_paren;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
')' => {
|
||||||
|
result.tag = .r_paren;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
'{' => {
|
||||||
|
result.tag = .l_brace;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
'}' => {
|
||||||
|
result.tag = .r_brace;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
'[' => {
|
||||||
|
result.tag = .l_bracket;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
']' => {
|
||||||
|
result.tag = .r_bracket;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
'<' => {
|
||||||
|
result.tag = .l_angle_bracket;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
'>' => {
|
||||||
|
result.tag = .r_angle_bracket;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
result.tag = .invalid;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result.tag == .eos) {
|
||||||
|
result.loc.start = self.index;
|
||||||
|
}
|
||||||
|
result.loc.end = self.index;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test "tokenizer - all" {
|
||||||
|
try testTokenize("()[]{}<>", &.{
|
||||||
|
.l_paren, .r_paren, .l_bracket, .r_bracket, .l_brace, .r_brace,
|
||||||
|
.l_angle_bracket, .r_angle_bracket
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
test "tokenizer - early end" {
|
||||||
|
try testTokenize("({", &.{
|
||||||
|
.l_paren, .l_brace,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
test "tokenizer - invalid" {
|
||||||
|
try testTokenize("<d", &.{
|
||||||
|
.l_angle_bracket, .invalid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testTokenize(source: []const u8, expected_tokens: []const Token.Tag) !void {
|
||||||
|
var tokenizer = Tokenizer.init(source);
|
||||||
|
for (expected_tokens) |expected_token_id| {
|
||||||
|
const token = tokenizer.next();
|
||||||
|
if (token.tag != expected_token_id) {
|
||||||
|
std.debug.panic("expected {s}, found {s}\n", .{ @tagName(expected_token_id), @tagName(token.tag) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const last_token = tokenizer.next();
|
||||||
|
try std.testing.expect(last_token.tag == .eos);
|
||||||
|
try std.testing.expect(last_token.loc.start == source.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "ok" {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = &arena.allocator;
|
||||||
|
var tree = try line_to_tree(alloc, "[<>({}){}[([])<>]]", 1);
|
||||||
|
try std.testing.expectEqual(@as(u32, 0), tree.corrupt);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "a" {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = &arena.allocator;
|
||||||
|
var tree = try line_to_tree(alloc, "{([(<{}[<>[]}>{[]{[(<()>", 1);
|
||||||
|
try std.testing.expectEqual(@as(u32, 1197), tree.corrupt);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "b" {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = &arena.allocator;
|
||||||
|
var tree = try line_to_tree(alloc, "[[<[([]))<([[{}[[()]]]", 1);
|
||||||
|
try std.testing.expectEqual(@as(u32, 3), tree.corrupt);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "c" {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = &arena.allocator;
|
||||||
|
var tree = try line_to_tree(alloc, "[{[{({}]{}}([{[{{{}}([]", 1);
|
||||||
|
try std.testing.expectEqual(@as(u32, 57), tree.corrupt);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "d" {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = &arena.allocator;
|
||||||
|
var tree = try line_to_tree(alloc, "[<(<(<(<{}))><([]([]()", 1);
|
||||||
|
try std.testing.expectEqual(@as(u32, 3), tree.corrupt);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "e" {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = &arena.allocator;
|
||||||
|
var tree = try line_to_tree(alloc, "<{([([[(<>()){}]>(<<{{", 1);
|
||||||
|
try std.testing.expectEqual(@as(u32, 25137), tree.corrupt);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "autocomplete simple" {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = &arena.allocator;
|
||||||
|
var tree = try line_to_tree(alloc, "<", 1);
|
||||||
|
try std.testing.expectEqual(@as(u32, 0), tree.corrupt);
|
||||||
|
var score = try tree.autocomplete();
|
||||||
|
try std.testing.expectEqual(@as(u64, 4), score);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "autocomplete" {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const alloc = &arena.allocator;
|
||||||
|
var tree = try line_to_tree(alloc, "<{([{{}}[<[[[<>{}]]]>[]]", 1);
|
||||||
|
try std.testing.expectEqual(@as(u32, 0), tree.corrupt);
|
||||||
|
var score = try tree.autocomplete();
|
||||||
|
try std.testing.expectEqual(@as(u64, 294), score);
|
||||||
|
}
|
Reference in New Issue