From e93670512c9bfffc5d023da2f2eeb648f8f4e414 Mon Sep 17 00:00:00 2001 From: rhiannon morris Date: Tue, 13 Dec 2022 08:27:18 +0100 Subject: [PATCH] arrays --- day11.m | 77 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/day11.m b/day11.m index b2ac9bf..87f922e 100644 --- a/day11.m +++ b/day11.m @@ -8,6 +8,7 @@ :- import_module int. :- import_module string. :- import_module list. +:- import_module array. :- type item == int. @@ -21,7 +22,10 @@ inspected :: int). :- func inspected(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). @@ -31,7 +35,7 @@ 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. +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. @@ -55,7 +59,7 @@ plus(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). :- 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). -:- 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 give(item::in, int::in, monkeys::m_in, monkeys::m_out) is det. +give(I, N, !Ms) :- + lookup(!.Ms, N, M0), + M = M0^items := [I | M0^items], + set(N, M, !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 get(int::in, monkey::out, monkeys::m_in, monkeys::m_out) is det. +get(N, M0, !Ms) :- + lookup(!.Ms, N, M0), + Len = length(M0^items), Insp = M0^inspected, + M = (M0^inspected := Insp + Len)^items := [], + set(N, M, !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) :- I2 = op(M^op, DM, I), (if test(M^test, I2) then @@ -109,33 +112,39 @@ step(DM, M, I, !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 steps(divmod::in, monkey::in, list(item)::in, + monkeys::m_in, monkeys::m_out) is det. +steps(_, _, [], !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. -round(DM, I, !Ms) :- - if turn(DM, I, !Ms) then round(DM, I + 1, !Ms) else true. +:- pred turn(divmod::in, int::in, monkeys::m_in, monkeys::m_out) is det. +turn(DM, N, !Ms) :- get(N, M, !Ms), steps(DM, M, M^items, !Ms). -:- 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). -:- 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) :- - if N = 0 then true else - round(DM, !Ms), - rounds(DM, N - 1, !Ms). + if N > 0 then round(DM, !Ms), rounds(DM, N - 1, !Ms) else true. -:- 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) :- - 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). + +% i broke part 1 at some point and i can't see where + run(Part, Lines, Out) :- - parse(join_list("\n", Lines), one_or_more(monkey), Res), - (if Res = ok(Monkeys) then - rounds(Part, Monkeys, Final), + parse(join_list("\n", Lines), monkeys, Res), + (if Res = ok(MList) then + from_list(MList, Arr0), + rounds(Part, Arr0, Arr1), + to_list(Arr1, Final), Out = int(prod(take_upto(2, rev_sort(map(inspected, Final))))) else Out = 'new other'(Res)).