:- table match/3. :- table sum/5. % match1(WinningNums, CardNums, NMatches) match1(_, [], 0). match1(Wins, [X|Nums], N) :- member(X, Wins), match1(Wins, Nums, N1), N is N1 + 1. match1(Wins, [X|Nums], N) :- \+ member(X, Wins), match1(Wins, Nums, N). match(Input, Nth, NMatches) :- nth1(Nth, Input, [Wins|CardNums]), match1(Wins, CardNums, NMatches). % sum(Cards, X, StuffToSum, Indices, Sum). sum(_, _, [], [0], 0). sum(Cards, X, [Element|Rest], [I,INext|IRest], Sum) :- sum(Cards, X, Rest, [INext|IRest], SumOfRest), Sum is Element + SumOfRest, I is INext + 1, match(Cards, I, NMatches_i), NMatches_i >= X - I. sum(Cards, X, [_|Rest], [I,INext|IRest], SumOfRest) :- sum(Cards, X, Rest, [INext|IRest], SumOfRest), I is INext + 1, match(Cards, I, NMatches_i), NMatches_i < X - I. % Number of card X = Nx = 1 + sum(Ni*(matches(i) >= x-i), i=1->x-1) ncards([], []). ncards([_|RestOfCards], [Nx|NRest]) :- length(RestOfCards, X_minus_1), X is X_minus_1 + 1, ncards(RestOfCards, NRest), reverse(RestOfCards, ReversedRestOfCards), sum(ReversedRestOfCards, X, NRest, _, Nx_minus_1), Nx is Nx_minus_1 + 1. % this is a more normal sum of a list sum([], 0). sum([Element|Rest], Sum) :- sum(Rest, RestOfSum), Sum is Element + RestOfSum. all_scores(Input, Score) :- reverse(Input, ReversedInput), ncards(ReversedInput, CardCounts), sum(CardCounts, Score).