清一色胡哪几张

我想知道有哪些牌型能和好几张牌,所以编了程序来算。做法是:123456789 + 类C(9, 4),检查是否能能和。下面的代码生成类C(9, 4):

cnt = 0; combo = set()
for a in range(1, 10):
    for b in range(1, 10):
        for c in range(1, 10):
            for d in range(1, 10):
                cnt += 1
                combo.add(reduce(lambda x,y:str(x)+str(y), sorted([a, b, c, d])))
print(cnt, len(combo))

考虑2张牌,C(2,2)只有12一种,我们多了11和22。3张牌起码多111和112。9^4=6561, C(9,4)=126, 我们这个是495.

By the way, reduce(function, sequence[, initial]),initial是可选的。今天之前我一直传个''当initial, 土了。Anyway,完整程序和结果:

图片及代码:https://files.cnblogs.com/files/blogs/714801/mahjong.zip 

# -*- coding: gbk -*-
# vim:ts=2:sw=2
# 张=Tile 组=Meld 顺子=Sequence 刻子=Triplet 杠子=Kong
# 将牌/雀头/对子=Eyes/Pair 和/胡=Win
# tiles.sort()后对子和刻子判断很方便
from functools import reduce
def is_pair(t): return len(t) >= 2 and t[0] == t[1]
def is_tri(t): return len(t) >= 3 and t[0] == t[1] and t[1] == t[2]
# 顺子的判断不太方便,例如1 1 1 2 2 3
def has_seq(tiles): 
  try:
    t = tiles; i = t.pop(0); j = i + 1; k = j + 1
    t.index(j); t.remove(j); t.index(k); t.remove(k)
    return 1, [i, j, k], t
  except:
    return 0, [], []
def check_and_print(r):
  if len(r) == 7: return 1 # 七小对
  p = m = 0 # count of pair and melds
  for t in r:
    if len(t) == 2: p = p + 1
    else: m = m + 1
  return p == 1 and m == 4
def check_winning(tiles, r):
  if len(tiles) == 0: return check_and_print(r)
  if is_pair(tiles) and check_winning(tiles[2:], r + [tiles[:2]]):
    return 1
  if is_tri(tiles) and check_winning(tiles[3:], r + [tiles[:3]]):
    return 1
  ok, s, t = has_seq(tiles)
  return ok and check_winning(t, r + [s])
def can_win(tiles):
  if len(tiles) != 14: return 0
  tiles.sort()
  return check_winning(tiles, [])

cnt = 0; combo = set()
for a in range(1, 10):
    for b in range(1, 10):
        for c in range(1, 10):
            for d in range(1, 10):
                cnt += 1
                combo.add(reduce(lambda x,y:str(x)+str(y), sorted([a, b, c, d])))
print(cnt, len(combo))

g = {}
for s2 in combo:
    s = '123456789' + s2
    tiles = list(map(int, list(s))); cnt = 0
    for i in range(1, 10):
        if can_win(tiles + [i]): cnt += 1
        if cnt > 3: g[cnt] = g.get(cnt, []) + [s]
seen = set()

for i in range(9, 3, -1):
    lst = g.get(i, None)
    if not lst: continue
    for x in lst:
        if x in seen: continue
        seen.add(x); print(x, i)

6561 495
1234567891199 9
1234567891122 7
1234567891166 7
1234567894499 7
1234567898899 7
1234567893777 6
1234567891178 6
1234567892223 6
1234567892399 6
1234567897888 6
1234567893337 6
1234567891155 6
1234567895599 6
1234567895566 5
1234567894555 5
1234567896777 5
1234567894456 5
1234567897899 5
1234567892355 5
1234567894455 5
1234567891233 5
1234567897789 5
1234567894478 5
1234567895578 5
1234567896799 5
1234567894566 5
1234567893599 5
1234567895556 5
1234567891133 5
1234567891123 5
1234567892299 5
1234567897799 5
1234567894466 5
1234567895557 5
1234567893555 5
1234567896667 5
1234567891188 5
1234567891134 5
1234567893334 5
1234567891157 5
1234567892366 5
1234567893444 5
1234567891145 4
1234567893667 4
1234567892278 4
1234567892266 4
1234567891146 4
1234567894666 4
1234567891333 4
1234567892388 4
1234567897999 4
1234567894446 4
1234567891169 4
1234567891222 4
1234567895699 4
1234567893889 4
1234567891167 4
1234567894488 4
1234567891127 4
1234567892333 4
1234567898889 4
1234567894699 4
1234567891499 4
1234567894599 4
1234567897778 4
1234567892224 4
1234567893799 4
1234567893899 4
1234567894467 4
1234567894457 4
1234567893447 4
1234567897779 4
1234567893466 4
1234567893888 4
1234567893566 4
1234567891137 4
1234567893499 4
1234567891113 4
1234567896888 4
1234567891227 4
1234567891156 4
1234567892227 4

你可能感兴趣的:(清一色胡哪几张)