import sys
from math import factorial
from itertools import combinations_with_replacement, permutations
# cards assumed to be of three types, a b c, with frequencies below
a_cards = 6
b_cards = 6
c_cards = 9
def unique_permutations(iterable, r=None):
previous = tuple()
for p in permutations(sorted(iterable), r):
if p > previous:
previous = p
yield p
def correct_guess_odds(cards_in_hand=5):
# the hands (multisets)
hands = [''.join(x) for x in combinations_with_replacement('abc', cards_in_hand)]
# remove any illegal hands (more cards of type than cards exist)
# this is safe to do because their permutation odds would be 0
legal_hands = []
for hand in hands:
if hand.count('a') <= a_cards - 1 and hand.count('b') <= b_cards - 1 and hand.count('c') <= c_cards - 1:
legal_hands.append(hand)
hands = legal_hands
number_of_cards = a_cards + b_cards + c_cards
# first calculate the odds of each specific permutation of card types
hand_perm_odds = {}
for hand in hands:
# -1 because correct cards removed
cards_left = {'a': a_cards - 1, 'b': b_cards - 1, 'c': c_cards - 1}
# odds are the chance of getting each hand *in order*
# so prod(cards_of_type_n_remaining) / prod(cards_remaining)
odds = 1 / (factorial(number_of_cards - 3) / factorial(number_of_cards - 3 - cards_in_hand))
for card in hand:
odds *= cards_left[card]
cards_left[card] -= 1
hand_perm_odds[hand] = odds
# now mult by number of permutations of each hand to get odds of hand
hand_odds = {}
for hand in hands:
perms = len(list(unique_permutations(hand, cards_in_hand)))
hand_odds[hand] = hand_perm_odds[hand] * perms
print(hand_odds)
# divide by odds of correct guess to get odds(hand * guess)
hand_guess_odds = {}
for hand in hands:
odds = 1 / ((a_cards - hand.count('a')) * (b_cards - hand.count('b')) * (c_cards - hand.count('c')))
hand_guess_odds[hand] = hand_odds[hand] * odds
print("result:", sum(hand_guess_odds.values()))
print(1/sum(hand_guess_odds.values()))
if __name__ == "__main__":
if len(sys.argv) > 1:
correct_guess_odds(int(sys.argv[1]))
else:
correct_guess_odds()