diff --git a/07/part1.pl b/07/part1.pl index f6ee17e..d44eb77 100644 --- a/07/part1.pl +++ b/07/part1.pl @@ -7,16 +7,19 @@ answer(Answer) :- 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], Type), Score is E + 15*D + (15**2)*C + (15**3)*B + (15**4)*A + (15**5)*Type. +% type(Hand, Type) get the type rank for one hand, ordered. type(Hand, Type) :- sort(0, @=<, Hand, Sorted), sorted_type(Sorted, Type). sorted_type([X, X, X, X, X], 7) :- !. sorted_type([X, X, X, X, _], 6) :- !. @@ -35,6 +38,7 @@ sorted_type([_, _, X, X, _], 2) :- !. sorted_type([_, _, _, X, X], 2) :- !. sorted_type([_, _, _, _, _], 1). +% convert_input(InputList, Cards, Bets) convert_input([], [], []). convert_input([[Cards, Bet] | Cdr], [[C1, C2, C3, C4, C5] | HandCdr], @@ -43,6 +47,7 @@ convert_input([[Cards, Bet] | Cdr], card(A1, C1), card(A2, C2), card(A3, C3), card(A4, C4), card(A5, C5), convert_input(Cdr, HandCdr, BetCdr). +% card(Ascii, Value) converts between card ascii value and internal values card(84, 10). card(74, 11). card(81, 12). @@ -50,5 +55,6 @@ card(75, 13). card(65, 14). card(Char, Card) :- Char >= 48, Char =< 57, Card is Char - 48. +% zip 2 lists into a map zip([], [], []). zip([A | ACdr], [B | BCdr], [A-B | ABCdr]) :- zip(ACdr, BCdr, ABCdr). diff --git a/07/part2.pl b/07/part2.pl new file mode 100644 index 0000000..19eee8d --- /dev/null +++ b/07/part2.pl @@ -0,0 +1,88 @@ +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) :- + max_type([A, B, C, D, E], Type), + tiebreaker([A, B, C, D, E], Tiebreaker), + Score is Tiebreaker + (100**5)*Type. + +tiebreaker([A, B, C, D, E], Score) :- + Score is E + 100*D + (100**2)*C + (100**3)*B + (100**4)*A. + +% max_type gets the max possible type from a hand including wildcards +max_type([A, B, C, D, E], Type) :- + ( + 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 + ). + +% type(Hand, Type) get the type rank for one hand, ordered. +type([A, B, C, D, E], Type) :- + wild(A, [A, B, C, D, E], Ax), + wild(B, [A, B, C, D, E], Bx), + wild(C, [A, B, C, D, E], Cx), + wild(D, [A, B, C, D, E], Dx), + wild(E, [A, B, C, D, E], 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. + +% 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). + +wild(X, _, Y) :- X =\= 1, Y is X. +wild(X, [A, B, C, D, E], Y) :- + X =:= 1, + (Y is A; Y is B; Y is C; Y is D; Y is E). + +% 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. + +% zip 2 lists into a map +zip([], [], []). +zip([A | ACdr], [B | BCdr], [A-B | ABCdr]) :- zip(ACdr, BCdr, ABCdr).