【Python】Magician“专属”神秘的“读心术”
貼吧里有這樣一個(gè)題目
下面樓主的補(bǔ)發(fā):
這種魔術(shù)看起來(lái)是有魔術(shù)師有“讀心術(shù)”?
實(shí)際上不然。
奧秘在于助手的出牌順序,這背后有一套算法,展示后魔術(shù)師經(jīng)過(guò)計(jì)算已經(jīng)知道了最后一張牌的值(每張牌有一個(gè)編號(hào)),對(duì)應(yīng)的可以找到隱藏的牌。
我的思路是這樣的(這是編程設(shè)計(jì)算法的思路,查閱過(guò)一些資料總結(jié)的):
首先只有4種花色,抽5張牌,根據(jù)鴿巢原理(鴿洞原理),必定有重花色的情況出現(xiàn)。
然后一種花色只有13張牌,圍成一個(gè)圈,最遠(yuǎn)的距離是6(雙向可達(dá))。
So,我們作如下規(guī)約:
- 藏匿的卡牌花色與第一張相同
- 藏匿卡牌的字面值與第一張相距在1~6之間(畢竟不能重復(fù),0是不存在的)
- 1~6 的距離由第2張~第4張展示的牌的大小順序呈現(xiàn)(按照編號(hào)而不是字面值)
- (小->中->大)= 1
- (小->大->中)= 2
- (中->小->大)= 3
- (中->大->小)= 4
- (大->小->中)= 5
- (大->中->小)= 6
- 編號(hào)順序花色從Club(梅花)->Diamond(方片)->Heart(紅心)->Spade(黑桃)
- 花色內(nèi)部編號(hào)從小到大A->2->3->…->K(與斗地主不同啊)
- 依據(jù)先補(bǔ)滿同字面值的花色再往后延伸字面值到K的順序來(lái)編號(hào)
規(guī)約就是這樣,然后就可以搞事情了嘿嘿嘿~~~
下面放出來(lái)Python描述的代碼實(shí)現(xiàn):
# 你可以讀心術(shù)——隨機(jī)抽取五張牌,其中一張隱藏起來(lái),按照特定的順序給四張牌,你就能知道第五張牌是什么!# deck是一個(gè)字符串列表,每個(gè)字符串是一張卡。名單上卡片的順序很重要!! deck = ['A_C', 'A_D', 'A_H', 'A_S', '2_C', '2_D', '2_H', '2_S','3_C', '3_D', '3_H', '3_S', '4_C', '4_D', '4_H', '4_S','5_C', '5_D', '5_H', '5_S', '6_C', '6_D', '6_H', '6_S','7_C', '7_D', '7_H', '7_S', '8_C', '8_D', '8_H', '8_S','9_C', '9_D', '9_H', '9_S', '10_C', '10_D', '10_H', '10_S','J_C', 'J_D', 'J_H', 'J_S', 'Q_C', 'Q_D', 'Q_H', 'Q_S','K_C', 'K_D', 'K_H', 'K_S']# 給5張牌,助手會(huì)藏一張合適的牌,TA仔細(xì)挑選了剩下的四張卡片,然后把它們讀出來(lái)! def AssistantOrderCards():print('Cards are character strings as shown below.')print('Ordering is:', deck)# 初始化cards, cind, cardsuits, cnumbers = [], [], [], []numsuits = [0, 0, 0, 0]# 將卡片作為用戶/觀眾的輸入# 填寫(xiě)各種數(shù)據(jù)結(jié)構(gòu)for i in range(5):print('Please give card', i + 1, end=' ')card = input('in above format: ')cards.append(card)n = deck.index(card)cind.append(n)cardsuits.append(n % 4)cnumbers.append(n // 4)numsuits[n % 4] += 1if numsuits[n % 4] > 1:pairsuit = n % 4# 從5個(gè)相同的套裝中找出兩張牌。保證存在cardH = []for i in range(5):if cardsuits[i] == pairsuit:cardH.append(i)# 找出需要隱藏的卡和要編碼的號(hào)碼hidden, other, encode = outputFirstCard(cnumbers, cardH, cards)remindices = []for i in range(5):if i != hidden and i != other:remindices.append(cind[i])# 按升序排列這三張牌sortList(remindices)# 給定需要編碼的號(hào)碼,對(duì)卡片進(jìn)行適當(dāng)?shù)呐判?/span>outputNext3Cards(encode, remindices)return# 這個(gè)程序可以根據(jù)距離隱藏哪張卡。兩張牌之間有相同的套裝。它返回隱藏卡、第一張暴露卡和距離。 def outputFirstCard(ns, oneTwo, cards):encode = (ns[oneTwo[0]] - ns[oneTwo[1]]) % 13if 0 < encode <= 6:hidden = oneTwo[0]other = oneTwo[1]else:hidden = oneTwo[1]other = oneTwo[0]encode = (ns[oneTwo[1]] - ns[oneTwo[0]]) % 13print('First card is: ', cards[other])return hidden, other, encode# 這個(gè)程序根據(jù)“編碼”命令三張卡。需要進(jìn)行編碼。 def outputNext3Cards(code, ind):if code == 1:s, t, f = ind[0], ind[1], ind[2]elif code == 2:s, t, f = ind[0], ind[2], ind[1]elif code == 3:s, t, f = ind[1], ind[0], ind[2]elif code == 4:s, t, f = ind[1], ind[2], ind[0]elif code == 5:s, t, f = ind[2], ind[0], ind[1]else:s, t, f = ind[2], ind[1], ind[0]print('Second card is:', deck[s])print('Third card is:', deck[t])print('Fourth card is:', deck[f])# 升序排列tList的元素 def sortList(tList):for ind in range(0, len(tList)-1):iSm = indfor i in range(ind, len(tList)):if tList[iSm] > tList[i]:iSm = itList[ind], tList[iSm] = tList[iSm], tList[ind]# 這個(gè)過(guò)程需要正確地編碼四張卡并確定隱藏的卡 def MagicianGuessesCard():print('Cards are character strings are shown as below')print('Ordering is:', deck)cards, cind = [], []for i in range(4):print('Please give card', i+1, end=' ')card = input('in above format:')cards.append(card)n = deck.index(card)cind.append(n)if i == 0:suit = n % 4number = n // 4# 使用最后3張卡的順序來(lái)確定與第一張卡的距離if cind[1] < cind[2] and cind[1] < cind[3]:if cind[2] < cind[3]:encode = 1else:encode = 2elif (cind[3] < cind[1] < cind[2]) or (cind[2] < cind[1] < cind[3]):if cind[2] < cind[3]:encode = 3else:encode = 4elif cind[1] > cind[2] and cind[1] > cind[3]:if cind[2] < cind[3]:encode = 5else:encode = 6# 知道號(hào)碼和套裝給出卡片索引然后字符串hiddenNumber = (number + encode) % 13index = hiddenNumber * 4 + suitprint('Hidden card is:', deck[index])# 類似于AssistantOrderCards(), 接收大量的卡,然后“隨機(jī)”生成五張卡。 def ComputerAssistant():print('Cards are character strings as shown below.')print('Ordering is:', deck)cards, cind, cardsuits, cnumbers = [], [], [], []numsuits = [0, 0, 0, 0]number = 0while number < 99999:number = int(input('Please give random number' +' of at least 6 digits:'))for i in range(5):number = number * (i + 1) // (i + 2)n = number % 52cards.append(deck[n])cind.append(n)cardsuits.append(n % 4)cnumbers.append(n // 4)numsuits[n % 4] += 1if numsuits[n % 4] > 1:pairsuit = n % 4cardH = []for i in range(5):if cardsuits[i] == pairsuit:cardH.append(i)hidden, other, encode = outputFirstCard(cnumbers, cardH, cards)remindices = []for i in range(5):if i != hidden and i != other:remindices.append(cind[i])sortList(remindices)outputNext3Cards(encode, remindices)guess = input('What is the hidden card?')if guess == cards[hidden]:print('You are a Mind Reader Extraordinaire!')else:print('Sorry, not impressed!')returnAssistantOrderCards() MagicianGuessesCard() ComputerAssistant()有三種模式:
AssistantOrderCards()是助手的算法,——助手抽4張牌,可以經(jīng)過(guò)此算法知道何種順序展示哪四張牌(當(dāng)然了,展示的順序很多種,這是助手跟魔術(shù)師約定的“秘鑰”,我們這里只按我們的思路來(lái))。
MagicianGuessesCard()是魔術(shù)師的算法——魔術(shù)師按照助手展示的順序“讀出”牌的值以及展示順序背后的秘密,算出最后隱藏而他“不知道”的牌。
ComputerAssistant()是沒(méi)有助手的魔術(shù)師“自行訓(xùn)練”所用,隨機(jī)抽多張卡(輸入大于100000停止),然后猜,看猜得對(duì)不對(duì)用來(lái)檢驗(yàn)技術(shù)達(dá)不達(dá)標(biāo)。
OK,終于解決,下面升華一下主題,咳咳~~
這個(gè)“讀心術(shù)”涉及到了一個(gè) 信息編碼 的問(wèn)題:
這個(gè)玩法里有 3! = 6 種排列方式,而一般對(duì)于 n! 來(lái)說(shuō),我們可以通過(guò)一個(gè)具體排列方式對(duì)傳遞的消息進(jìn)行簡(jiǎn)單編碼,普通的監(jiān)聽(tīng)者知道有秘密但是他并不能輕易的破解(除非他知道秘鑰,對(duì)吧…),而傳遞信息的雙方則可以根據(jù)加密解密來(lái)傳遞信息,蠻有趣的呢~~
總結(jié)
以上是生活随笔為你收集整理的【Python】Magician“专属”神秘的“读心术”的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【C语言】C语言中一些零碎的基础知识
- 下一篇: 【Python】Matplotlib绘制