-module(day13). -export([solve/1]). solve(Input) -> PacketPairs = binary:split(Input, <<"\n\n">>, [global, trim_all]), Part1 = part1(PacketPairs), {Part1, part2(Input)}. part1(PacketPairs) -> part1(PacketPairs, {1, 0}). part1([], {_Index, Score}) -> Score; part1([PacketPair|Rest], {Index, Score}) -> [LeftStr, RightStr] = binary:split(PacketPair, <<$\n>>, [trim_all]), Left = parse_packet(LeftStr), Right = parse_packet(RightStr), NewScore = case compare(Left, Right) of true -> Score + Index; false -> Score end, part1(Rest, {Index+1, NewScore}). part2(Input) -> Packets0 = binary:split(Input, <<"\n">>, [global, trim_all]), Packets1 = lists:filter(fun(X) -> byte_size(X) > 0 end, Packets0), Packets2 = lists:map(fun parse_packet/1, Packets1), Packets3 = [[[2]], [[6]] | Packets2], % add signal packets Packets = lists:sort(fun compare/2, Packets3), find([[2]], Packets) * find([[6]], Packets). find(Item, List) -> find(Item, List, 1). find(_Item, [], _Index) -> 0; find(Item, [Item | _Rest], Index) -> Index; find(Item, [_Head | Rest], Index) -> find(Item, Rest, Index+1). compare([], []) -> undecided; compare([], [_|_Rest]) -> true; compare([_|_Rest], []) -> false; compare([Left | LeftRest], [Right | RightRest]) when is_list(Left) and is_list(Right) -> case compare(Left, Right) of undecided -> compare(LeftRest, RightRest); Result -> Result end; compare([Left | _] = Lefts, [Right | RightRest]) when is_list(Left) and is_integer(Right) -> compare(Lefts, [[Right] | RightRest]); compare([Left | LeftRest], [Right | _] = Rights) when is_integer(Left) and is_list(Right) -> compare([[Left] | LeftRest], Rights); compare([Value | Left], [Value | Right]) when is_integer(Value) -> compare(Left, Right); compare([Left|_], [Right|_]) when is_integer(Left) and is_integer(Right) -> Left < Right; compare(Left, Right) when is_integer(Left) and is_integer(Right) -> Left < Right. parse_packet(Packet) -> {ok, Tokens, _EndLine} = erl_scan:string(unicode:characters_to_list([Packet,$.])), {ok, Parsed} = erl_parse:parse_term(Tokens), Parsed.