From ccda7b498f089e8b4910442c1be95b81f0215e04 Mon Sep 17 00:00:00 2001 From: Shanti Chellaram Date: Sun, 11 Dec 2022 23:42:00 +0900 Subject: [PATCH] Day 11-1 --- day11.erl | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 day11.erl diff --git a/day11.erl b/day11.erl new file mode 100644 index 0000000..83dd12e --- /dev/null +++ b/day11.erl @@ -0,0 +1,87 @@ +-module(day11). + +-export([solve/1]). + +solve(Input) -> + Monkeys = parse_monkeys(Input), + {score(run(20, Monkeys)), none}. + +score(Monkeys0) -> + Monkeys1 = maps:values(Monkeys0), + Monkeys2 = lists:map(fun(#{interact:=Interact}) -> Interact end, Monkeys1), + [M1, M2|_Rest] = lists:sort(fun erlang:'>'/2, Monkeys2), + M1*M2. + +run(0, Monkeys) -> Monkeys; +run(N, Monkeys) -> run(N-1, run_round(Monkeys)). + +run_round(Monkeys) -> + lists:foldl( + fun (Id, State) -> run_turn(Id, State) end, + Monkeys, + maps:keys(Monkeys) + ). + +run_turn(Id, Monkeys) -> + #{Id := CurrentMonkey} = Monkeys, + #{operation := Operation, test := Test, queue := Queue} = CurrentMonkey, + case Queue of + [] -> Monkeys; + [Item|_Rest] -> + NewLevel = Operation(Item), + Target = Test(NewLevel), + run_turn(Id, throw_item(Monkeys, Id, Target)) + end. + +increment_interacts(Monkey) -> + maps:update_with(interact, fun(X)->X+1 end, 1, Monkey). + +throw_item(Monkeys, From, To) -> + #{From := #{operation := Op, queue:= [Item|FromQueue]} = FromMonkey, To := #{queue := ToQueue} = ToMonkey} = Monkeys, + Monkeys#{From := increment_interacts(FromMonkey#{queue:=FromQueue}), To := ToMonkey#{queue := ToQueue ++ [Op(Item) div 3]}}. + +parse_monkeys(Input) -> parse_monkeys(Input, #{}). + +parse_monkeys(<<>>, Acc) -> Acc; +parse_monkeys(<<$\n, Rest/binary>>, Acc) -> parse_monkeys(Rest, Acc); +parse_monkeys(Input, Storage) -> + <<"Monkey ", MonkeyDigit, $:, $\n, Rest1/binary>> = Input, + MonkeyNumber = MonkeyDigit - $0, + <<" Starting items:", Rest2/binary>> = Rest1, + {Items, Rest3} = parse_items(Rest2, []), + <<" Operation: new = ", Rest4/binary>> = Rest3, + {Operation, Rest5} = parse_operation(Rest4, []), + <<" Test: divisible by ", Rest6/binary>> = Rest5, + {TestDivisor, <<$\n, Rest7/binary>>} = parse_int(Rest6), + <<" If true: throw to monkey ", TrueDigit, $\n, Rest8/binary>> = Rest7, + True = TrueDigit - $0, + <<" If false: throw to monkey ", FalseDigit, $\n, Rest9/binary>> = Rest8, + False = FalseDigit - $0, + Test = fun (Var) -> case (Var div 3) rem TestDivisor of 0 -> True; _ -> False end end, + parse_monkeys(Rest9, Storage#{MonkeyNumber => #{queue => Items, operation => Operation, test => Test}}). + +parse_operation(<<$\n, Rest/binary>>, [Rhs, Op, Lhs]) -> {fun(Old) -> Op(Rhs(Old), Lhs(Old)) end, Rest}; +parse_operation(<<$\s, Rest/binary>>, Acc) -> parse_operation(Rest, Acc); +parse_operation(<<$+, Rest/binary>>, Acc) -> parse_operation(Rest, [fun erlang:'+'/2|Acc]); +parse_operation(<<$*, Rest/binary>>, Acc) -> parse_operation(Rest, [fun erlang:'*'/2|Acc]); +parse_operation(<<"old", Rest/binary>>, Acc) -> parse_operation(Rest, [fun(Old) -> Old end | Acc]); +parse_operation(<>, Acc) -> + {Literal, Rest} = parse_int(String), + parse_operation(Rest, [fun(_Old) -> Literal end | Acc]). + +parse_items(<<$\n, Rest/binary>>, Items) -> {lists:reverse(Items), Rest}; +parse_items(<<$,, Rest/binary>>, Items) -> parse_items(Rest, Items); +parse_items(<<$\s, Rest/binary>>, Items) -> parse_items(Rest, Items); +parse_items(<>, Items) -> + {Item, RestOut} = parse_int(RestIn), + parse_items(RestOut, [Item|Items]). + +parse_int(<<$-, Rest/binary>>) -> + {AbsoluteValue, Binary} = parse_int0(Rest, 0), + {-1 * AbsoluteValue, Binary}; +parse_int(Binary) -> + parse_int0(Binary, 0). + +parse_int0(<>, Acc) when Digit >= $0 andalso Digit =< $9 -> + parse_int0(Rest, Acc*10 + Digit - $0); +parse_int0(Binary, Acc) when is_binary(Binary) -> {Acc, Binary}.