answer(Answer) :- input(Input), convert_input(Input, Hands, Bets), convlist(score, Hands, Scores), zip(Scores, Bets, ScoresBets), sort(ScoresBets, SortedScoreBetsInv), reverse(SortedScoreBetsInv, SortedScoreBets), payout(SortedScoreBets, _, Answer). % payout([Hand-Bet], _, Payout) computes total payout from [Hand-Bet] map. payout([], 0, 0). payout([_-Bet | Cdr], Rank, Payout) :- payout(Cdr, LastRank, LastPayout), Rank is LastRank + 1, Payout is LastPayout + Rank*Bet. % score(Hand, Score) gets the score for one hand, that can be directly compared. score([A, B, C, D, E], Score) :- ( type([A, B, C, D, E], 7) -> Type is 7; type([A, B, C, D, E], 6) -> Type is 6; type([A, B, C, D, E], 5) -> Type is 5; type([A, B, C, D, E], 4) -> Type is 4; type([A, B, C, D, E], 3) -> Type is 3; type([A, B, C, D, E], 2) -> Type is 2; type([A, B, C, D, E], 1) -> Type is 1 ), Score is E + 100*D + (100**2)*C + (100**3)*B + (100**4)*A + (100**5)*Type. % type(Hand, Type) get the type rank for one hand, ordered. type([A, B, C, D, E], Type) :- wild([A, B, C, D, E], [Ax, Bx, Cx, Dx, Ex]), sort(0, @=<, [Ax, Bx, Cx, Dx, Ex], Sorted), sorted_type(Sorted, Type). sorted_type([X, X, X, X, X], 7). sorted_type([X, X, X, X, A], 6) :- X =\= A. sorted_type([A, X, X, X, X], 6) :- X =\= A. sorted_type([Y, Y, X, X, X], 5) :- X =\= Y. sorted_type([X, X, X, Y, Y], 5) :- X =\= Y. sorted_type([X, X, X, A, B], 4) :- X =\= A, A =\= B. sorted_type([A, X, X, X, B], 4) :- A =\= X, X =\= B. sorted_type([A, B, X, X, X], 4) :- A =\= B, B =\= X. sorted_type([X, X, Y, Y, A], 3) :- X =\= Y, Y =\= A. sorted_type([X, X, A, Y, Y], 3) :- X =\= A, A =\= Y. sorted_type([A, X, X, Y, Y], 3) :- A =\= X, X =\= Y. sorted_type([X, X, A, B, C], 2) :- X =\= A, A =\= B, B =\= C. sorted_type([A, X, X, B, C], 2) :- A =\= X, X =\= B, B =\= C. sorted_type([A, B, X, X, C], 2) :- A =\= B, B =\= X, X =\= C. sorted_type([A, B, C, X, X], 2) :- A =\= B, B =\= C, C =\= X. sorted_type([A, B, C, D, E], 1) :- A =\= B, B =\= C, C =\= D, D =\= E. % wild replaces a wildcard with any possible other card wild(_, X, Y) :- card(X), X =\= 1, Y is X. wild([A, B, C, D, E], X, Y) :- card(X), X =:= 1, (Y is A; Y is B; Y is C; Y is D; Y is E), Y =\= 1. wild([1, 1, 1, 1, 1], [2, 2, 2, 2, 2]). wild(Hand, WildHand) :- maplist(wild(Hand), Hand, WildHand). % card(Ascii, Value) converts between card ascii value and internal values card(84, 10). % T card(74, 1). % J card(81, 12). % Q card(75, 13). % K card(65, 14). % A card(Char, Card) :- Char >= 48, Char =< 57, Card is Char - 48. card(1). card(2). card(3). card(4). card(5). card(6). card(7). card(8). card(9). card(10). card(12). card(13). card(14). % zip 2 lists into a map zip([], [], []). zip([A | ACdr], [B | BCdr], [A-B | ABCdr]) :- zip(ACdr, BCdr, ABCdr). % convert_input(InputList, Cards, Bets) convert_input([], [], []). convert_input([[Cards, Bet] | Cdr], [[C1, C2, C3, C4, C5] | HandCdr], [Bet | BetCdr]) :- string_to_list(Cards, [A1, A2, A3, A4, A5]), card(A1, C1), card(A2, C2), card(A3, C3), card(A4, C4), card(A5, C5), convert_input(Cdr, HandCdr, BetCdr).