From 20631cf4cd6e748f4e138655d79f7be50be67549 Mon Sep 17 00:00:00 2001 From: rhiannon morris Date: Tue, 13 Dec 2022 08:28:17 +0100 Subject: [PATCH] day13 --- Makefile | 6 ++-- aoc.m | 4 +++ day13.m | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 day13.m diff --git a/Makefile b/Makefile index d06d253..447cf1c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,5 @@ -MMCFLAGS := \ - --infer-all --warn-unused-imports - # this seems to break day7 for some absolutely bizarre reason - # -s asm_fast.par.gc.stseg +MMCFLAGS := --infer-all --no-inform-inferred --warn-unused-imports \ + -s asm_fast.par.gc.stseg all: aoc diff --git a/aoc.m b/aoc.m index 564d2d6..f4f5be9 100644 --- a/aoc.m +++ b/aoc.m @@ -47,6 +47,8 @@ run_day(Day, Part, Lines, Out) :- :- import_module day9. :- import_module day10. :- import_module day11. +% :- import_module day12. +:- import_module day13. :- pred solution(int::in, sol::out(sol)) is semidet. solution(1, day1.run). @@ -60,3 +62,5 @@ solution(8, day8.run). solution(9, day9.run). solution(10, day10.run). solution(11, day11.run). +% solution(12, day12.run). +solution(13, day13.run). diff --git a/day13.m b/day13.m new file mode 100644 index 0000000..31d6ddc --- /dev/null +++ b/day13.m @@ -0,0 +1,86 @@ +:- module day13. +:- interface. +:- import_module basics. + +:- pred run(part::in, lines::in, answer::out) is cc_multi. + +:- implementation. +:- import_module int. +:- import_module string. +:- import_module list. + +:- type packet ---> i(int); l(list(packet)). +:- type packets == {packet, packet}. + + +:- pred packets(list(packets)::out, lines::in) is nondet. +packets(Ps, Lines) :- packets(Ps, to_char_list(join_list("", Lines)), []). + +:- pred packets(list(packets)::out, chars::in, chars::out) is multi. +packets([{P, Q} | Rest]) --> packet(P), packet(Q), packets(Rest). +packets([]) --> []. + +:- pred packet(packet::out, chars::in, chars::out) is nondet. +:- import_module day4. +packet(i(I)) --> day4.number(I). +packet(l(Ps)) --> ['['], inner(Ps), [']']. + +:- pred inner(list(packet)::out, chars::in, chars::out) is multi. +inner(Ps) --> inner1(Ps). +inner([]) --> []. + +:- pred inner1(list(packet)::out, chars::in, chars::out) is nondet. +inner1([P | Ps]) --> packet(P), (if [','] then inner1(Ps) else {Ps = []}). + + +:- pred cmps(list(packet)::in, list(packet)::in, comparison_result::out) is det. +cmps([], [], =). +cmps([], [_|_], <). +cmps([_|_], [], >). +cmps([P|Ps], [Q|Qs], C) :- + cmp(P, Q, C1), (if C1 = (=) then cmps(Ps, Qs, C) else C = C1). + +:- pred cmp(packet::in, packet::in, comparison_result::out) is det. +cmp(i(I), i(J), C) :- compare(C, I, J). +cmp(l(Ps), l(Qs), C) :- cmps(Ps, Qs, C). +cmp(i(I), l(Qs), C) :- cmps([i(I)], Qs, C). +cmp(l(Ps), i(J), C) :- cmps(Ps, [i(J)], C). + +:- func cmp(packet, packet) = comparison_result. +cmp(P, Q) = C :- cmp(P, Q, C). + +:- pred ok(packets::in) is semidet. +ok({P, Q}) :- not cmp(P, Q, >). + +div1 = l([l([i(2)])]). +div2 = l([l([i(6)])]). + +:- pred divider(packet::in) is semidet. +divider(div1). divider(div2). + +:- mode unary == (pred(in) is semidet). + +:- pred indices(pred(T)::unary, int::in, list(T)::in, list(int)::out) is det. +indices(_, _, [], []). +indices(P, I, [X|Xs], Is) :- + indices(P, I + 1, Xs, Is0), + (if P(X) then Is = [I|Is0] else Is = Is0). + +:- pred indices(pred(T)::unary, list(T)::in, list(int)::out) is det. +indices(P, Xs, Is) :- indices(P, 1, Xs, Is). + + +:- func merge(list(packets)) = list(packet). +merge(Ps) = foldl(func({X, Y}, Zs) = [X,Y|Zs], Ps, []). + +:- pragma no_determinism_warning(run/3). +run(one, Lines, int(sum(Is))) :- + if packets(Ps, Lines) then + indices(ok, Ps, Is) + else + die("bad input"). +run(two, Lines, int(prod(Is))) :- + if packets(Pairs, Lines) then + indices(divider, sort(cmp, [div1, div2 | merge(Pairs)]), Is) + else + die("bad input").