我想知道有哪些牌型能和好几张牌,所以编了程序来算。做法是: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