arrays
This commit is contained in:
parent
506f945d80
commit
e93670512c
1 changed files with 43 additions and 34 deletions
77
day11.m
77
day11.m
|
@ -8,6 +8,7 @@
|
||||||
:- import_module int.
|
:- import_module int.
|
||||||
:- import_module string.
|
:- import_module string.
|
||||||
:- import_module list.
|
:- import_module list.
|
||||||
|
:- import_module array.
|
||||||
|
|
||||||
:- type item == int.
|
:- type item == int.
|
||||||
|
|
||||||
|
@ -21,7 +22,10 @@
|
||||||
inspected :: int).
|
inspected :: int).
|
||||||
:- func inspected(monkey) = int.
|
:- func inspected(monkey) = int.
|
||||||
:- func test(monkey) = int.
|
:- func test(monkey) = int.
|
||||||
:- type monkeys == list(monkey).
|
|
||||||
|
:- type monkeys == array(monkey).
|
||||||
|
:- mode m_in == array_di.
|
||||||
|
:- mode m_out == array_uo.
|
||||||
|
|
||||||
:- type divmod ---> dm(d :: int, m :: int).
|
:- type divmod ---> dm(d :: int, m :: int).
|
||||||
|
|
||||||
|
@ -31,7 +35,7 @@ op(mul(M), N) = M * N.
|
||||||
op(square, N) = N * N.
|
op(square, N) = N * N.
|
||||||
|
|
||||||
:- func op(op, divmod, item) = item.
|
:- func op(op, divmod, item) = item.
|
||||||
op(O, dm(D, M), N) = op(O, N) `div` D `mod` M.
|
op(O, dm(D, M), N) = (op(O, N) div D) mod M.
|
||||||
|
|
||||||
:- pred test(test::in, item::in) is semidet.
|
:- pred test(test::in, item::in) is semidet.
|
||||||
test(M, N) :- N mod M = 0.
|
test(M, N) :- N mod M = 0.
|
||||||
|
@ -55,7 +59,7 @@ plus(Src) --> punct("+", Src, _).
|
||||||
star(Src) --> punct("*", Src, _).
|
star(Src) --> punct("*", Src, _).
|
||||||
|
|
||||||
|
|
||||||
:- pred monkeys(src::in, monkeys::out, ps::in, ps::out) is semidet.
|
:- pred monkeys(src::in, list(monkey)::out, ps::in, ps::out) is semidet.
|
||||||
monkeys(Src, Ms) --> one_or_more(monkey, Src, Ms), eof(Src).
|
monkeys(Src, Ms) --> one_or_more(monkey, Src, Ms), eof(Src).
|
||||||
|
|
||||||
:- pred monkey(src::in, monkey::out, ps::in, ps::out) is semidet.
|
:- pred monkey(src::in, monkey::out, ps::in, ps::out) is semidet.
|
||||||
|
@ -86,22 +90,21 @@ test(Src, N) --> kws(Src, ["divisible", "by"]), int_literal(Src, N).
|
||||||
act(Src, N) --> kws(Src, ["throw", "to", "monkey"]), int_literal(Src, N).
|
act(Src, N) --> kws(Src, ["throw", "to", "monkey"]), int_literal(Src, N).
|
||||||
|
|
||||||
|
|
||||||
:- pred give(item::in, int::in, monkeys::in, monkeys::out) is det.
|
:- pred give(item::in, int::in, monkeys::m_in, monkeys::m_out) is det.
|
||||||
give(_, _, [], _) :- die("list too short").
|
give(I, N, !Ms) :-
|
||||||
give(I, N, [!.M | !.Ms], [!:M | !:Ms]) :-
|
lookup(!.Ms, N, M0),
|
||||||
if N = 0 then !M^items := [I | !.M^items]
|
M = M0^items := [I | M0^items],
|
||||||
else give(I, N - 1, !Ms).
|
set(N, M, !Ms).
|
||||||
|
|
||||||
:- pred get(int::in, monkey::out, monkeys::in, monkeys::out) is semidet.
|
:- pred get(int::in, monkey::out, monkeys::m_in, monkeys::m_out) is det.
|
||||||
get(N, X, [!.M | !.Ms], [!:M | !:Ms]) :-
|
get(N, M0, !Ms) :-
|
||||||
if N = 0 then
|
lookup(!.Ms, N, M0),
|
||||||
X = !.M,
|
Len = length(M0^items), Insp = M0^inspected,
|
||||||
!M^inspected := !.M^inspected + length(!.M^items),
|
M = (M0^inspected := Insp + Len)^items := [],
|
||||||
!M^items := []
|
set(N, M, !Ms).
|
||||||
else
|
|
||||||
get(N - 1, X, !Ms).
|
|
||||||
|
|
||||||
:- pred step(divmod::in, monkey::in, int::in, monkeys::in, monkeys::out) is det.
|
:- pred step(divmod::in, monkey::in, item::in,
|
||||||
|
monkeys::m_in, monkeys::m_out) is det.
|
||||||
step(DM, M, I, !Ms) :-
|
step(DM, M, I, !Ms) :-
|
||||||
I2 = op(M^op, DM, I),
|
I2 = op(M^op, DM, I),
|
||||||
(if test(M^test, I2) then
|
(if test(M^test, I2) then
|
||||||
|
@ -109,33 +112,39 @@ step(DM, M, I, !Ms) :-
|
||||||
else
|
else
|
||||||
give(I2, M^if_false, !Ms)).
|
give(I2, M^if_false, !Ms)).
|
||||||
|
|
||||||
:- pred turn(divmod::in, int::in, monkeys::in, monkeys::out) is semidet.
|
:- pred steps(divmod::in, monkey::in, list(item)::in,
|
||||||
turn(DM, I, !Ms) :-
|
monkeys::m_in, monkeys::m_out) is det.
|
||||||
get(I, M, !Ms),
|
steps(_, _, [], !Ms).
|
||||||
foldr(step(DM, M), M^items, !Ms).
|
steps(DM, M, [I | Is], !Ms) :- steps(DM, M, Is, !Ms), step(DM, M, I, !Ms).
|
||||||
|
|
||||||
:- pred round(divmod::in, int::in, monkeys::in, monkeys::out) is det.
|
:- pred turn(divmod::in, int::in, monkeys::m_in, monkeys::m_out) is det.
|
||||||
round(DM, I, !Ms) :-
|
turn(DM, N, !Ms) :- get(N, M, !Ms), steps(DM, M, M^items, !Ms).
|
||||||
if turn(DM, I, !Ms) then round(DM, I + 1, !Ms) else true.
|
|
||||||
|
|
||||||
:- pred round(divmod::in, monkeys::in, monkeys::out) is det.
|
:- pred round(divmod::in, int::in, monkeys::m_in, monkeys::m_out) is det.
|
||||||
|
round(DM, N, !Ms) :-
|
||||||
|
if N < size(!.Ms) then turn(DM, N, !Ms), round(DM, N + 1, !Ms) else true.
|
||||||
|
|
||||||
|
:- pred round(divmod::in, monkeys::m_in, monkeys::m_out) is det.
|
||||||
round(DM, !Ms) :- round(DM, 0, !Ms).
|
round(DM, !Ms) :- round(DM, 0, !Ms).
|
||||||
|
|
||||||
:- pred rounds(divmod::in, int::in, monkeys::in, monkeys::out) is det.
|
:- pred rounds(divmod::in, int::in, monkeys::m_in, monkeys::m_out) is det.
|
||||||
rounds(DM, N, !Ms) :-
|
rounds(DM, N, !Ms) :-
|
||||||
if N = 0 then true else
|
if N > 0 then round(DM, !Ms), rounds(DM, N - 1, !Ms) else true.
|
||||||
round(DM, !Ms),
|
|
||||||
rounds(DM, N - 1, !Ms).
|
|
||||||
|
|
||||||
:- pred rounds(part::in, monkeys::in, monkeys::out) is det.
|
:- pred rounds(part::in, monkeys::m_in, monkeys::m_out) is det.
|
||||||
rounds(Part, !Ms) :-
|
rounds(Part, !Ms) :-
|
||||||
DM = dm(part(Part, 3, 1), prod(map(test, !.Ms))),
|
DM = dm(part(Part, 3, 1), foldl(func(X, A) = test(X) * A, !.Ms, 1)),
|
||||||
rounds(DM, part(Part, 20, 10_000), !Ms).
|
rounds(DM, part(Part, 20, 10_000), !Ms).
|
||||||
|
|
||||||
|
|
||||||
|
% i broke part 1 at some point and i can't see where
|
||||||
|
|
||||||
run(Part, Lines, Out) :-
|
run(Part, Lines, Out) :-
|
||||||
parse(join_list("\n", Lines), one_or_more(monkey), Res),
|
parse(join_list("\n", Lines), monkeys, Res),
|
||||||
(if Res = ok(Monkeys) then
|
(if Res = ok(MList) then
|
||||||
rounds(Part, Monkeys, Final),
|
from_list(MList, Arr0),
|
||||||
|
rounds(Part, Arr0, Arr1),
|
||||||
|
to_list(Arr1, Final),
|
||||||
Out = int(prod(take_upto(2, rev_sort(map(inspected, Final)))))
|
Out = int(prod(take_upto(2, rev_sort(map(inspected, Final)))))
|
||||||
else
|
else
|
||||||
Out = 'new other'(Res)).
|
Out = 'new other'(Res)).
|
||||||
|
|
Loading…
Reference in a new issue