This commit is contained in:
rhiannon morris 2022-12-13 08:28:17 +01:00
parent e93670512c
commit 20631cf4cd
3 changed files with 92 additions and 4 deletions

View file

@ -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

4
aoc.m
View file

@ -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).

86
day13.m Normal file
View file

@ -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").