day11
This commit is contained in:
parent
d7b45f85d2
commit
506f945d80
5 changed files with 161 additions and 11 deletions
4
Makefile
4
Makefile
|
@ -1,5 +1,7 @@
|
|||
MMCFLAGS := \
|
||||
--infer-all --warn-unused-imports
|
||||
# this seems to break day7 for some absolutely bizarre reason
|
||||
MMCFLAGS := # -s asm_fast.par.gc.stseg
|
||||
# -s asm_fast.par.gc.stseg
|
||||
|
||||
all: aoc
|
||||
|
||||
|
|
4
aoc.m
4
aoc.m
|
@ -8,8 +8,6 @@
|
|||
:- import_module basics.
|
||||
:- import_module string.
|
||||
:- import_module list.
|
||||
:- import_module exception.
|
||||
:- import_module univ.
|
||||
|
||||
main(!IO) :- wrap_main(main2, !IO).
|
||||
|
||||
|
@ -48,6 +46,7 @@ run_day(Day, Part, Lines, Out) :-
|
|||
:- import_module day8.
|
||||
:- import_module day9.
|
||||
:- import_module day10.
|
||||
:- import_module day11.
|
||||
|
||||
:- pred solution(int::in, sol::out(sol)) is semidet.
|
||||
solution(1, day1.run).
|
||||
|
@ -60,3 +59,4 @@ solution(7, day7.run).
|
|||
solution(8, day8.run).
|
||||
solution(9, day9.run).
|
||||
solution(10, day10.run).
|
||||
solution(11, day11.run).
|
||||
|
|
16
basics.m
16
basics.m
|
@ -9,7 +9,9 @@
|
|||
|
||||
:- func part(part, T, T) = T.
|
||||
|
||||
:- type answer ---> int(int); string(string); lines(list(string)).
|
||||
:- type answer --->
|
||||
int(int); string(string); lines(list(string));
|
||||
some [T] other(T).
|
||||
:- pred output(answer::in, io::di, io::uo) is det.
|
||||
|
||||
|
||||
|
@ -39,10 +41,10 @@
|
|||
:- type chars == list(char).
|
||||
|
||||
|
||||
:- import_module int.
|
||||
|
||||
:- func sum(list(int)) = int.
|
||||
:- func prod(list(int)) = int.
|
||||
:- func replicate(int, T) = list(T).
|
||||
:- func rev_sort(list(T)) = list(T).
|
||||
|
||||
:- func map_index(func(int, T) = U, list(T)) = list(U).
|
||||
|
||||
|
@ -64,6 +66,7 @@ part(two, _, Y) = Y.
|
|||
output(int(I), !IO) :- write_int(I, !IO), nl(!IO).
|
||||
output(string(S), !IO) :- write_string(S, !IO), nl(!IO).
|
||||
output(lines(Ss), !IO) :- write_list(Ss, "\n", write_string, !IO), nl(!IO).
|
||||
output(other(X), !IO) :- write(X, !IO), nl(!IO).
|
||||
|
||||
|
||||
ite(P, T, E) = X :- if P then X = T else X = E.
|
||||
|
@ -92,11 +95,18 @@ read_lines_need(File, Lines, !IO) :-
|
|||
need(Res, Lines).
|
||||
|
||||
|
||||
:- import_module int.
|
||||
|
||||
sum(Xs) = foldl(plus, Xs, 0).
|
||||
prod(Xs) = foldl(times, Xs, 1).
|
||||
|
||||
replicate(N, X) = Out :-
|
||||
if N = 0 then Out = [] else Out = [X | replicate(N - 1, X)].
|
||||
|
||||
:- import_module std_util.
|
||||
|
||||
rev_sort(Xs) = sort(converse(ordering), Xs).
|
||||
|
||||
:- func map_index(int, func(int, T) = U, list(T)) = list(U).
|
||||
map_index(_, _, []) = [].
|
||||
map_index(I, F, [X | Xs]) = [F(I, X) | map_index(I+1, F, Xs)].
|
||||
|
|
5
day1.m
5
day1.m
|
@ -6,10 +6,7 @@
|
|||
|
||||
:- implementation.
|
||||
:- import_module list.
|
||||
:- import_module std_util.
|
||||
:- import_module maybe.
|
||||
:- import_module string.
|
||||
:- import_module int.
|
||||
|
||||
:- pragma no_determinism_warning(run/3).
|
||||
run(one, Lines, int(det_head(go(Lines)))).
|
||||
|
@ -17,7 +14,7 @@ run(two, Lines, int(sum(take_upto(3, go(Lines))))).
|
|||
|
||||
:- func go(lines) = list(int).
|
||||
go(Lines) =
|
||||
sort(converse(ordering), map(sum, gather(map(to_int_may, Lines)))).
|
||||
rev_sort(map(sum, gather(map(to_int_may, Lines)))).
|
||||
|
||||
:- func gather(list(maybe(T))) = list(list(T)).
|
||||
gather(Xs) = Ys :- gather(Xs, Ys).
|
||||
|
|
141
day11.m
Normal file
141
day11.m
Normal file
|
@ -0,0 +1,141 @@
|
|||
:- module day11.
|
||||
:- 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 item == int.
|
||||
|
||||
:- type op ---> add(int); mul(int); square.
|
||||
:- type test == int.
|
||||
|
||||
:- type monkey --->
|
||||
m(items :: list(item),
|
||||
op :: op, test :: test,
|
||||
if_true :: int, if_false :: int,
|
||||
inspected :: int).
|
||||
:- func inspected(monkey) = int.
|
||||
:- func test(monkey) = int.
|
||||
:- type monkeys == list(monkey).
|
||||
|
||||
:- type divmod ---> dm(d :: int, m :: int).
|
||||
|
||||
:- func op(op, item) = item.
|
||||
op(add(M), N) = M + N.
|
||||
op(mul(M), N) = M * N.
|
||||
op(square, N) = N * N.
|
||||
|
||||
:- func op(op, divmod, item) = item.
|
||||
op(O, dm(D, M), N) = op(O, N) `div` D `mod` M.
|
||||
|
||||
:- pred test(test::in, item::in) is semidet.
|
||||
test(M, N) :- N mod M = 0.
|
||||
|
||||
|
||||
:- import_module parsing_utils.
|
||||
|
||||
eof(Src) --> not next_char(Src, _).
|
||||
|
||||
:- pred kw(src::in, string::in, ps::in, ps::out) is semidet.
|
||||
kw(Src, Kw) --> ikeyword("abcdefghijklmnopqrstuvwxyz", Kw, Src, _).
|
||||
|
||||
:- pred kws(src::in, list(string)::in, ps::in, ps::out) is semidet.
|
||||
kws(_, []) --> [].
|
||||
kws(Src, [Kw | Kws]) --> kw(Src, Kw), kws(Src, Kws).
|
||||
|
||||
colon(Src) --> punct(":", Src, _).
|
||||
comma(Src) --> punct(",", Src, _).
|
||||
equal(Src) --> punct("=", Src, _).
|
||||
plus(Src) --> punct("+", Src, _).
|
||||
star(Src) --> punct("*", Src, _).
|
||||
|
||||
|
||||
:- pred monkeys(src::in, monkeys::out, ps::in, ps::out) is semidet.
|
||||
monkeys(Src, Ms) --> one_or_more(monkey, Src, Ms), eof(Src).
|
||||
|
||||
:- pred monkey(src::in, monkey::out, ps::in, ps::out) is semidet.
|
||||
monkey(Src, m(reverse(I), O, P, T, F, 0)) -->
|
||||
kw(Src, "monkey"), int_literal_as_string(Src, _), colon(Src),
|
||||
kws(Src, ["starting", "items"]), colon(Src), items(Src, I),
|
||||
kw(Src, "operation"), colon(Src),
|
||||
kw(Src, "new"), equal(Src), op(Src, O),
|
||||
kw(Src, "test"), colon(Src), test(Src, P),
|
||||
kws(Src, ["if", "true"]), colon(Src), act(Src, T),
|
||||
kws(Src, ["if", "false"]), colon(Src), act(Src, F).
|
||||
|
||||
:- pred items(src::in, list(item)::out, ps::in, ps::out) is semidet.
|
||||
items(Src, Is) --> comma_separated_list(int_literal, Src, Is).
|
||||
|
||||
:- pred op(src::in, op::out, ps::in, ps::out) is semidet.
|
||||
op(Src, Op) -->
|
||||
kw(Src, "old"),
|
||||
(if star(Src) then
|
||||
(if int_literal(Src, N) then {Op = mul(N)}
|
||||
else kw(Src, "old"), {Op = square})
|
||||
else plus(Src), int_literal(Src, N), {Op = add(N)}).
|
||||
|
||||
:- pred test(src::in, test::out, ps::in, ps::out) is semidet.
|
||||
test(Src, N) --> kws(Src, ["divisible", "by"]), int_literal(Src, N).
|
||||
|
||||
:- pred act(src::in, int::out, ps::in, ps::out) is semidet.
|
||||
act(Src, N) --> kws(Src, ["throw", "to", "monkey"]), int_literal(Src, N).
|
||||
|
||||
|
||||
:- pred give(item::in, int::in, monkeys::in, monkeys::out) is det.
|
||||
give(_, _, [], _) :- die("list too short").
|
||||
give(I, N, [!.M | !.Ms], [!:M | !:Ms]) :-
|
||||
if N = 0 then !M^items := [I | !.M^items]
|
||||
else give(I, N - 1, !Ms).
|
||||
|
||||
:- pred get(int::in, monkey::out, monkeys::in, monkeys::out) is semidet.
|
||||
get(N, X, [!.M | !.Ms], [!:M | !:Ms]) :-
|
||||
if N = 0 then
|
||||
X = !.M,
|
||||
!M^inspected := !.M^inspected + length(!.M^items),
|
||||
!M^items := []
|
||||
else
|
||||
get(N - 1, X, !Ms).
|
||||
|
||||
:- pred step(divmod::in, monkey::in, int::in, monkeys::in, monkeys::out) is det.
|
||||
step(DM, M, I, !Ms) :-
|
||||
I2 = op(M^op, DM, I),
|
||||
(if test(M^test, I2) then
|
||||
give(I2, M^if_true, !Ms)
|
||||
else
|
||||
give(I2, M^if_false, !Ms)).
|
||||
|
||||
:- pred turn(divmod::in, int::in, monkeys::in, monkeys::out) is semidet.
|
||||
turn(DM, I, !Ms) :-
|
||||
get(I, M, !Ms),
|
||||
foldr(step(DM, M), M^items, !Ms).
|
||||
|
||||
:- pred round(divmod::in, int::in, monkeys::in, monkeys::out) is det.
|
||||
round(DM, I, !Ms) :-
|
||||
if turn(DM, I, !Ms) then round(DM, I + 1, !Ms) else true.
|
||||
|
||||
:- pred round(divmod::in, monkeys::in, monkeys::out) is det.
|
||||
round(DM, !Ms) :- round(DM, 0, !Ms).
|
||||
|
||||
:- pred rounds(divmod::in, int::in, monkeys::in, monkeys::out) is det.
|
||||
rounds(DM, N, !Ms) :-
|
||||
if N = 0 then true else
|
||||
round(DM, !Ms),
|
||||
rounds(DM, N - 1, !Ms).
|
||||
|
||||
:- pred rounds(part::in, monkeys::in, monkeys::out) is det.
|
||||
rounds(Part, !Ms) :-
|
||||
DM = dm(part(Part, 3, 1), prod(map(test, !.Ms))),
|
||||
rounds(DM, part(Part, 20, 10_000), !Ms).
|
||||
|
||||
run(Part, Lines, Out) :-
|
||||
parse(join_list("\n", Lines), one_or_more(monkey), Res),
|
||||
(if Res = ok(Monkeys) then
|
||||
rounds(Part, Monkeys, Final),
|
||||
Out = int(prod(take_upto(2, rev_sort(map(inspected, Final)))))
|
||||
else
|
||||
Out = 'new other'(Res)).
|
Loading…
Reference in a new issue