ソリティア(*)が、どのくらいの回数やれば成功するか、Pythonでシミュレーションしてみた
(*)一般的なソリティアではない点注意。ルールはコメント参照。
solitaire.py
# 当該カードをひっくり返す
def updown(card):
if card[2] == "D":
card[2] = "U"
else:
card[2] = "D"
return card
# 同一スーツ、1つ下の数値のカードを見つけて、下に連結する
def find(lane,lanes):
b = False
for ls in lanes:
if ls != lane:
for l in ls:
if not len(lane)==0:
if(lane[len(lane)-1][0]==l[0] and \
lane[len(lane)-1][1]-1==l[1] and \
l[2]=='U'):
b = True
ix = ls.index(l)
for c in range(ix,len(ls)):
lane.append(ls.pop(ix))
return b
# 空のレーンに、キング(に連なるカードたち)を移す
def king_move(lanes):
b = False
for ls in lanes:
if len(ls)==0:
for ls_ot in lanes:
if len(ls_ot)>0 and len(ls)==0:
for l in ls_ot:
if l[1] == 13 and len(ls)==0:
ix = ls_ot.index(l)
if ix >0 and len(ls)==0:
b = True
for c in range(ix,len(ls_ot)):
ls.append(ls_ot.pop(ix))
break
return b
# トップに来た裏カードを、表にする
def top_faceup(lanes):
b = False
for ls in lanes:
if not len(ls)==0:
if(ls[len(ls)-1][2] =='D'):
b = True
updown(ls[len(ls)-1])
return b
# エース(以降最小の)のカードがトップに来たら、外に出す
def out_put(lanes):
b = False
for ls in lanes:
if not len(ls)==0:
for s in range(0,4):
if(out_place[s][len(out_place[s])-1][0] == ls[len(ls)-1][0] and \
out_place[s][len(out_place[s])-1][1] == ls[len(ls)-1][1]-1 ):
out_place[s].append(ls.pop())
b = True
break
return b
# メインループの始まり
import random
cn1=0 #試行回数
cn2=0 #成功数
# メイン
for k in range(0,10000):
if k % 100 == 0:
print(k)
# 準備 ht:ハート、sp:スペード、di:ダイヤ、cb:クラブ
out_place = [[['ht',0,'U']],[['sp',0,'U']],[['di',0,'U']],[['cb',0,'U']]]
nums = [1,2,3,4,5,6,7,8,9,10,11,12,13]
suits = ["ht","sp","di","cb"]
cards = list()
# 52枚の準備
for s in suits:
for n in nums:
cards.append([s,n,"D"])
random.shuffle(cards)
# 7つのレーン
lane = [list(),list(),list(),list(),list(),list(),list()]
# カードの初期配置 ここから↓
# 1枚表 6枚裏
lane[0].append(updown(cards.pop()))
for i in range(1,7):
lane[i].append(cards.pop())
# 1枚表 ●枚裏
for j in range(1,7):
lane[j].append(updown(cards.pop()))
for i in range(j+1,7):
lane[i].append(cards.pop())
# 4枚ずつ表
for j in range(1,5):
for i in range(1,7):
lane[i].append(updown(cards.pop()))
# カードの初期配置 ここまで↑
#なにか動く限り、ループ
b1 = True
while b1:
b1 = False
b1 = b1 or top_faceup(lane)
b1 = b1 or out_put(lane)
b1 = b1 or king_move(lane)
for i in range(0,7):
b1 = b1 or find(lane[i],lane)
if sum(len(op) for op in out_place)-4 == 13*4:
cn2=cn2+1
cn1=cn1+1
print("全試行数:",cn1, " 成功数:",cn2, " 成功率:", "{0:.2f}%".format(cn2/cn1*100))
結果↓
10000回実施して、182回。 約2%弱。
全試行数: 100000 成功数: 4143 成功率: 4.14%
成功率4%ほど。 ※注:処理を一部修正後(ソース内"#なにか動く限り、ループ")