ranks = '123456789TJQKA'
values = [0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
1, 2, 3, 4]
suits = 'cdhs'
hcp = dict((rank + suit, value)
for suit in suits
for rank, value in zip(ranks, values))
cards = sorted(hcp.keys())
def count_points(hand):
return sum(hcp[card] for card in hand)
def bad():
scores = {}
for c0 in range(len(cards)):
for c1 in range(c0):
for c2 in range(c1):
for c3 in range(c2):
for c4 in range(c3):
hand = map(cards.__getitem__,
[c4, c3, c2, c1, c0])
score = count_points(hand)
scores[score] = scores.get(score, 0) + 1
return scores
%time bad()
CPU times: user 10.3 s, sys: 24 ms, total: 10.3 s Wall time: 10.3 s
{0: 658008, 1: 365560, 2: 424840, 3: 526760, 4: 601680, 5: 354240, 6: 291204, 7: 250588, 8: 155892, 9: 84156, 10: 52256, 11: 31524, 12: 13044, 13: 5884, 14: 2724, 15: 1056, 16: 276, 17: 92, 18: 28, 19: 4}
def tricky():
scores = {}
c = [None] * 5
for c[4] in range(len(cards)):
for c[3] in range(c[4]):
for c[2] in range(c[3]):
for c[1] in range(c[2]):
for c[0] in range(c[1]):
hand = map(cards.__getitem__, c)
score = count_points(hand)
scores[score] = scores.get(score, 0) + 1
return scores
%time tricky()
CPU times: user 9.36 s, sys: 0 ns, total: 9.36 s Wall time: 9.35 s
{0: 658008, 1: 365560, 2: 424840, 3: 526760, 4: 601680, 5: 354240, 6: 291204, 7: 250588, 8: 155892, 9: 84156, 10: 52256, 11: 31524, 12: 13044, 13: 5884, 14: 2724, 15: 1056, 16: 276, 17: 92, 18: 28, 19: 4}
def better():
scores = {}
for indices in subset_generator(len(cards), 5):
hand = map(cards.__getitem__, indices)
score = count_points(hand)
scores[score] = scores.get(score, 0) + 1
return scores
def subset_generator(set_size, subset_size, accumulator=()):
if subset_size == 0:
yield accumulator
else:
for index in range(set_size):
for indices in subset_generator(
set_size=index,
subset_size=subset_size - 1,
accumulator=(index,) + accumulator,
):
yield indices
list(subset_generator(5, 3))
[(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3), (0, 1, 4), (0, 2, 4), (1, 2, 4), (0, 3, 4), (1, 3, 4), (2, 3, 4)]
%time better()
CPU times: user 14.9 s, sys: 4 ms, total: 14.9 s Wall time: 14.9 s
{0: 658008, 1: 365560, 2: 424840, 3: 526760, 4: 601680, 5: 354240, 6: 291204, 7: 250588, 8: 155892, 9: 84156, 10: 52256, 11: 31524, 12: 13044, 13: 5884, 14: 2724, 15: 1056, 16: 276, 17: 92, 18: 28, 19: 4}
def new_subset_generator(set_size, subset_size, accumulator=()):
if subset_size == 0:
yield accumulator
else:
for index in range(set_size):
yield from new_subset_generator(
set_size=index,
subset_size=subset_size - 1,
accumulator=(index,) + accumulator,
)
def even_better():
scores = {}
for indices in new_subset_generator(len(cards), 5):
hand = map(cards.__getitem__, indices)
score = count_points(hand)
scores[score] = scores.get(score, 0) + 1
return scores
%time even_better()
CPU times: user 14.4 s, sys: 0 ns, total: 14.4 s Wall time: 14.4 s
{0: 658008, 1: 365560, 2: 424840, 3: 526760, 4: 601680, 5: 354240, 6: 291204, 7: 250588, 8: 155892, 9: 84156, 10: 52256, 11: 31524, 12: 13044, 13: 5884, 14: 2724, 15: 1056, 16: 276, 17: 92, 18: 28, 19: 4}
from itertools import combinations
from collections import Counter
def best():
hands = combinations(cards, 5)
scores = Counter(map(count_points, hands))
return dict(scores)
%time best()
CPU times: user 7.81 s, sys: 0 ns, total: 7.81 s Wall time: 7.82 s
{0: 658008, 1: 365560, 2: 424840, 3: 526760, 4: 601680, 5: 354240, 6: 291204, 7: 250588, 8: 155892, 9: 84156, 10: 52256, 11: 31524, 12: 13044, 13: 5884, 14: 2724, 15: 1056, 16: 276, 17: 92, 18: 28, 19: 4}
from itertools import permutations
from collections import Counter
def queens_filter(n):
tally = Counter(
solution[0]
for solution in permutations(range(n))
if is_valid(solution))
return dict(tally)
def is_valid(solution):
rows = set(solution)
diagonals = set(i-j for i, j in enumerate(solution))
antidiags = set(i+j for i, j in enumerate(solution))
return len(solution) == len(rows) == len(diagonals) == len(antidiags)
queens_filter(4)
{1: 1, 2: 1}
%time queens_filter(9)
CPU times: user 2.83 s, sys: 32 ms, total: 2.86 s Wall time: 2.87 s
{0: 28, 1: 30, 2: 47, 3: 44, 4: 54, 5: 44, 6: 47, 7: 30, 8: 28}
def queens_prune(n):
tally = Counter(s[0] for s in solution_generator(n))
return dict(tally)
def solution_generator(n, accumulator=()):
if not is_valid(accumulator):
return
elif len(accumulator) == n:
yield accumulator
else:
for new_queen in range(n):
yield from solution_generator(n, accumulator + (new_queen,))
list(solution_generator(4))
[(1, 3, 0, 2), (2, 0, 3, 1)]
%time queens_prune(9)
CPU times: user 544 ms, sys: 12 ms, total: 556 ms Wall time: 558 ms
{0: 28, 1: 30, 2: 47, 3: 44, 4: 54, 5: 44, 6: 47, 7: 30, 8: 28}