day5
This commit is contained in:
parent
72d3d8da40
commit
1da0498792
5 changed files with 119 additions and 11 deletions
6
aoc.m
6
aoc.m
|
@ -25,7 +25,7 @@ main2(!IO) :-
|
||||||
) else
|
) else
|
||||||
die("expected day, part, filename")).
|
die("expected day, part, filename")).
|
||||||
|
|
||||||
:- type sol == (pred(part, list(string), univ)).
|
:- type sol == (pred(part, lines, univ)).
|
||||||
:- inst sol == (pred(in, in, out) is cc_multi).
|
:- inst sol == (pred(in, in, out) is cc_multi).
|
||||||
|
|
||||||
:- pred solution(int::in, sol::out(sol)) is semidet.
|
:- pred solution(int::in, sol::out(sol)) is semidet.
|
||||||
|
@ -37,8 +37,10 @@ solution(2, day2.run).
|
||||||
solution(3, day3.run).
|
solution(3, day3.run).
|
||||||
:- import_module day4.
|
:- import_module day4.
|
||||||
solution(4, day4.run).
|
solution(4, day4.run).
|
||||||
|
:- import_module day5.
|
||||||
|
solution(5, day5.run).
|
||||||
|
|
||||||
:- pred run_day(int, part, list(string), univ).
|
:- pred run_day(int, part, lines, univ).
|
||||||
:- mode run_day(in, in, in, out) is cc_multi.
|
:- mode run_day(in, in, in, out) is cc_multi.
|
||||||
run_day(Day, Part, Lines, Out) :-
|
run_day(Day, Part, Lines, Out) :-
|
||||||
if solution(Day, P) then
|
if solution(Day, P) then
|
||||||
|
|
4
basics.m
4
basics.m
|
@ -11,11 +11,13 @@
|
||||||
:- import_module list.
|
:- import_module list.
|
||||||
:- import_module string.
|
:- import_module string.
|
||||||
|
|
||||||
|
:- type lines == list(string).
|
||||||
|
|
||||||
:- pred die(string::in) is erroneous.
|
:- pred die(string::in) is erroneous.
|
||||||
:- pred die(string::in, list(poly_type)::in) is erroneous.
|
:- pred die(string::in, list(poly_type)::in) is erroneous.
|
||||||
|
|
||||||
:- pred need(io.res(T)::in, T::out) is det.
|
:- pred need(io.res(T)::in, T::out) is det.
|
||||||
:- pred read_lines_need(string::in, list(string)::out, io::di, io::uo) is det.
|
:- pred read_lines_need(string::in, lines::out, io::di, io::uo) is det.
|
||||||
|
|
||||||
|
|
||||||
:- pred wrap_main(pred(io, io), io, io).
|
:- pred wrap_main(pred(io, io), io, io).
|
||||||
|
|
6
day1.m
6
day1.m
|
@ -1,12 +1,12 @@
|
||||||
:- module day1.
|
:- module day1.
|
||||||
:- interface.
|
:- interface.
|
||||||
:- import_module basics.
|
:- import_module basics.
|
||||||
:- import_module list.
|
|
||||||
:- import_module univ.
|
:- import_module univ.
|
||||||
|
|
||||||
:- pred run(part::in, list(string)::in, univ::out) is cc_multi.
|
:- pred run(part::in, lines::in, univ::out) is cc_multi.
|
||||||
|
|
||||||
:- implementation.
|
:- implementation.
|
||||||
|
:- import_module list.
|
||||||
:- import_module std_util.
|
:- import_module std_util.
|
||||||
:- import_module maybe.
|
:- import_module maybe.
|
||||||
:- import_module string.
|
:- import_module string.
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
run(one, Lines, univ(det_head(go(Lines)))).
|
run(one, Lines, univ(det_head(go(Lines)))).
|
||||||
run(two, Lines, univ(sum(take_upto(3, go(Lines))))).
|
run(two, Lines, univ(sum(take_upto(3, go(Lines))))).
|
||||||
|
|
||||||
:- func go(list(string)) = list(int).
|
:- func go(lines) = list(int).
|
||||||
go(Lines) =
|
go(Lines) =
|
||||||
sort(converse(ordering), map(sum, gather(map(to_int_may, Lines)))).
|
sort(converse(ordering), map(sum, gather(map(to_int_may, Lines)))).
|
||||||
|
|
||||||
|
|
10
day4.m
10
day4.m
|
@ -1,19 +1,20 @@
|
||||||
:- module day4.
|
:- module day4.
|
||||||
:- interface.
|
:- interface.
|
||||||
:- import_module basics.
|
:- import_module basics.
|
||||||
:- import_module list.
|
|
||||||
:- import_module univ.
|
:- import_module univ.
|
||||||
|
|
||||||
:- pred run(part::in, list(string)::in, univ::out) is cc_multi.
|
:- pred run(part::in, lines::in, univ::out) is cc_multi.
|
||||||
|
|
||||||
|
:- pred number(int::out, chars::in, chars::out) is semidet.
|
||||||
|
|
||||||
:- implementation.
|
:- implementation.
|
||||||
:- import_module int.
|
:- import_module int.
|
||||||
:- import_module char.
|
:- import_module char.
|
||||||
:- import_module string.
|
:- import_module string.
|
||||||
|
:- import_module list.
|
||||||
|
|
||||||
:- type ranges ---> r(int, int, int, int).
|
:- type ranges ---> r(int, int, int, int).
|
||||||
|
|
||||||
:- pred number(int::out, chars::in, chars::out) is semidet.
|
|
||||||
number(N) --> digits(S), {to_int(from_char_list(S), N)}.
|
number(N) --> digits(S), {to_int(from_char_list(S), N)}.
|
||||||
|
|
||||||
:- pred digits(chars::out, chars::in, chars::out) is semidet.
|
:- pred digits(chars::out, chars::in, chars::out) is semidet.
|
||||||
|
@ -41,8 +42,7 @@ all_overlap(r(A, B, C, D)) :- C >= A, D =< B ; D >= B, C =< A.
|
||||||
any_overlap(r(A, B, C, D)) :- A =< C, B >= C ; C =< A, D >= A.
|
any_overlap(r(A, B, C, D)) :- A =< C, B >= C ; C =< A, D >= A.
|
||||||
|
|
||||||
|
|
||||||
:- pred go(pred(ranges)::(pred(in) is semidet),
|
:- pred go(pred(ranges)::(pred(in) is semidet), lines::in, int::out) is det.
|
||||||
list(string)::in, int::out) is det.
|
|
||||||
go(P, Lines, Out) :-
|
go(P, Lines, Out) :-
|
||||||
map(ranges, Lines, Ranges),
|
map(ranges, Lines, Ranges),
|
||||||
filter(P, Ranges, Overlaps),
|
filter(P, Ranges, Overlaps),
|
||||||
|
|
104
day5.m
Normal file
104
day5.m
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
:- module day5.
|
||||||
|
:- interface.
|
||||||
|
:- import_module basics.
|
||||||
|
:- import_module univ.
|
||||||
|
|
||||||
|
:- pred run(part::in, lines::in, univ::out) is cc_multi.
|
||||||
|
|
||||||
|
:- implementation.
|
||||||
|
:- import_module int.
|
||||||
|
:- import_module char.
|
||||||
|
:- import_module string.
|
||||||
|
:- import_module list.
|
||||||
|
:- import_module maybe.
|
||||||
|
|
||||||
|
|
||||||
|
:- type parser(T) == (pred(T, chars, chars)).
|
||||||
|
:- mode parser == (pred(out, in, out) is semidet).
|
||||||
|
|
||||||
|
:- pred many(parser(T)::parser, list(T)::out, chars::in, chars::out) is semidet.
|
||||||
|
many(P, Out) --> if P(X) then many(P, Xs), {Out = [X | Xs]} else {Out = []}.
|
||||||
|
|
||||||
|
:- pred spaces(chars::in, chars::out) is det.
|
||||||
|
spaces --> if [' '] then spaces else [].
|
||||||
|
|
||||||
|
:- pred word0(string::in, chars::in, chars::out) is semidet.
|
||||||
|
word0(Str, In, Out) :- append(to_char_list(Str), Out, In).
|
||||||
|
|
||||||
|
:- pred word(string::in, chars::in, chars::out) is semidet.
|
||||||
|
word(Str) --> word0(Str), spaces.
|
||||||
|
|
||||||
|
:- pred number(int::out, chars::in, chars::out) is semidet.
|
||||||
|
:- use_module day4.
|
||||||
|
number(N) --> day4.number(N), spaces.
|
||||||
|
|
||||||
|
:- type slot == maybe(char).
|
||||||
|
|
||||||
|
:- pred slot(slot::out, chars::in, chars::out) is semidet.
|
||||||
|
slot(Res) -->
|
||||||
|
(if ['[', C, ']'] then {Res = yes(C)}
|
||||||
|
else [' ', ' ', ' '], {Res = no}),
|
||||||
|
([' '] ; =([])).
|
||||||
|
|
||||||
|
|
||||||
|
:- type instr == {int, int, int}.
|
||||||
|
|
||||||
|
:- pred instr(instr::out, chars::in, chars::out) is semidet.
|
||||||
|
instr({Count, From, To}) -->
|
||||||
|
word("move"), number(Count),
|
||||||
|
word("from"), number(From),
|
||||||
|
word("to"), number(To).
|
||||||
|
|
||||||
|
|
||||||
|
:- func transpose(list(list(T))) = list(list(T)) is semidet.
|
||||||
|
transpose([]) = [].
|
||||||
|
transpose([Xs]) = map(func(Z) = [Z], Xs).
|
||||||
|
transpose([Xs1, Xs2 | Xss]) =
|
||||||
|
map_corresponding(cons, Xs1, transpose([Xs2 | Xss])).
|
||||||
|
|
||||||
|
|
||||||
|
:- type tower == list(char).
|
||||||
|
:- type towers == list(tower).
|
||||||
|
|
||||||
|
:- pred lines(parser(T), list(T), lines, lines).
|
||||||
|
:- mode lines(parser, out, in, out) is semidet.
|
||||||
|
lines(P, Out) -->
|
||||||
|
if [Line], {P(X, to_char_list(Line), [])}
|
||||||
|
then lines(P, Xs), {Out = [X | Xs]}
|
||||||
|
else {Out = []}.
|
||||||
|
|
||||||
|
:- pred input(towers, list(instr), lines, lines).
|
||||||
|
:- mode input(out, out, in, out) is semidet.
|
||||||
|
input(Towers, Insts) -->
|
||||||
|
lines(many(slot), Slots), [_, _], lines(instr, Insts),
|
||||||
|
{map(filter_map(maybe_is_yes), transpose(Slots), Towers)}.
|
||||||
|
|
||||||
|
|
||||||
|
:- pred take_n(int::in, int::in, tower::out, towers::in, towers::out) is det.
|
||||||
|
take_n(Which, Count, Res, [T0 | Ts0], [T1 | Ts1]) :-
|
||||||
|
if Which = 1 then
|
||||||
|
det_split_list(Count, T0, Res, T1), Ts0 = Ts1
|
||||||
|
else
|
||||||
|
take_n(Which - 1, Count, Res, Ts0, Ts1), T0 = T1.
|
||||||
|
take_n(_, _, _, [], _) :- die("take_n: not enough lists").
|
||||||
|
|
||||||
|
:- pred put_n(part::in, int::in, tower::in, towers::in, towers::out) is det.
|
||||||
|
put_n(Part, Which, New, [T0 | Ts0], [T1 | Ts1]) :-
|
||||||
|
if Which = 1 then
|
||||||
|
(if Part = one then Onto = reverse(New) else Onto = New),
|
||||||
|
T1 = Onto ++ T0, Ts0 = Ts1
|
||||||
|
else
|
||||||
|
put_n(Part, Which - 1, New, Ts0, Ts1), T0 = T1.
|
||||||
|
put_n(_, _, _, [], _) :- die("put_n: not enough lists").
|
||||||
|
|
||||||
|
:- pred interp(part::in, instr::in, towers::in, towers::out) is det.
|
||||||
|
interp(Part, {Count, From, To}) -->
|
||||||
|
take_n(From, Count, Res), put_n(Part, To, Res).
|
||||||
|
|
||||||
|
:- pragma no_determinism_warning(run/3).
|
||||||
|
run(Part, Lines, univ(Out)) :-
|
||||||
|
if input(Towers, Insts, Lines, []) then
|
||||||
|
foldl(interp(Part), Insts, Towers, Res),
|
||||||
|
from_char_list(map(det_head, Res), Out)
|
||||||
|
else
|
||||||
|
die("bad file").
|
Loading…
Reference in a new issue