WOO logo

將七張牌的位置轉換為數字

這篇通訊發佈時,距離日全食還有四天。我希望你們都興奮不已,也希望所有體力和經濟條件允許、能夠在全食帶上觀賞日全食的人都能興奮不已。可惜的是,我打算去德州觀看日全食,天氣預報顯示當天會有雷暴。不過,我仍然希望天空晴朗。

在進入正題之前,我上一篇關於復活節瑣事的簡報收到了一些出人意料的強烈反響。看來你們當中有些人對聖經相當了解,並對我的一些回答提出了質疑。以下是兩個主要抗議問題,它們之間密切相關:

問題8:猶大後來把錢還給了那些被雇來背叛耶穌的祭司。他們怎麼處理這些錢呢?

答案8:他們買了一塊窯戶的田,那裡埋葬著無人認領的屍體。 (太27:6-8)

有人向我指出,《使徒行傳》對那30塊銀幣的去向有不同的描述。其中說猶大自己買了窯戶的一塊田(徒1:18)。

問題 9:猶大是如何自殺的?

答案9:絞刑(太27:3-5)

再說一次,《使徒行傳》似乎另有版本。我不太明白該如何理解,就讓經文自己解釋吧:「猶大用他作惡所得的工價買了一塊田,就在那裡僕倒,身體崩裂,腸子流出來。」——使徒行傳 1:18。

我的理解是,猶大病了,全身腫脹,潰瘍暴露。最後,他虛弱無力,摔倒在地,腸子都裂開了。這次跌倒可能是故意的。

在研究這個問題的過程中,我發現一些聖經無誤論的擁護者竭盡全力試圖將這兩個故事混為一談,形成一個錯綜複雜的故事。然而,我對這樣的解釋只能翻白眼。

好了,讓我們進入本週的主題:高效編碼,如何讓七張牌的撲克牌手得分。考慮到計算機的速度,這似乎不是什麼大問題。然而,終極德州撲克需要分析56兆種發牌方式。每種方式都需要兩手七張牌的牌型才能算出結果。如果不走捷徑,這可能需要數年時間。

從一副 52 張牌的牌組中選出七張牌,一共有 combin(52,7) = 133,784,560 種方法。一個重要的省時技巧是給每種可能的組合都評分一次,並將分數保存到一個陣列中。但是,如何將七張牌分別放到陣列中的一個位置呢?

在給出我的答案之前,有人可能會建議使用一個大小為 52^7 的七維數組。這樣的陣列需要保存 1,028,071,702,528 個整數。我認為任何桌上型電腦都無法允許分配這麼大的記憶體。不,我們需要以某種方式將 7 張卡片映射到 0 到 133,784,559 之間的整數。我的 C++ 編譯器可以毫無問題地處理這種大小的陣列。

首先,將每張牌賦值給一個從 0 到 51 的整數。你可以按照自己喜歡的方式進行。我個人會先將 2 賦值給 0 到 3,3 賦值給 4 到 7,以此類推,直到 A,賦值範圍從 48 到 51。重要的是,當你用 4 除以一張牌時,餘數必須永遠是同一花色。例如,所有紅桃的模數可能都是 0,空格是 1,梅花是 2,方塊是 3。

我的函數將把最低的一組卡片 0,1,2,3,4,5,6 映射到數字 0。同樣,最大的一組 45,46,47,48,49,50,51 將映射到最大值 133,784,559。

舉例來說,讓我們考慮一組編號為 5、10、15、20、25、30、35 的卡片,並確定該組卡片應映射到哪個整數。

首先,考慮最小的牌,數字 5。我們可以跳過很多包含至少一張數字 0 到 4 的牌的組合。從剩下的 47 張牌中選出 7 張的方法數為 combin(47,7) = 62,891,499。如前所述,從 52 張牌中選出 7 張的方法數為 combin(52,7) = 133,784,560。因此,我們可以跳過 133,784,560 - 62,891,499 = 70,893,061 個至少包含一張數字 0 到 4 的牌的組合。

接下來,考慮第二張牌的點數為 10。我們可以跳過更多包含至少一張點數在 6 到 9 之間的牌的組合。從牌堆剩餘的 42 張牌中選出剩下的 6 張牌的方法數為 combin(42,6) = 5,245,786。這相當於從 combin(46,6)=9,366,819 種可能的方法中選擇第一張牌點數大於 5 的另外六張牌。因此,對於包含至少一張點數在 6 到 9 之間的牌組,我們可以跳過 9,366,819-5,245,786=4,121,033 個數字。

接下來,考慮第三張牌,其值為 15。我們可以跳過更多涉及至少一張 11 到 14 範圍內的牌的組合。從牌堆剩下的 37 張牌中選出剩下的 5 張牌的方法數為 combin(37,5) = 435,897。這就排除了 combin(41,5)=749,398 種可能的組合,用於選擇第二張牌點數大於 10 的另外五張牌。因此,對於至少包含一張 11 到 14 之間的點數的牌組,我們可以跳過 749,398-435,897=313,501 個數字。

接下來,考慮第四張牌,其點數為 20。我們可以跳過更多包含至少一張點數在 16 到 19 之間的牌的組合。從牌堆剩餘的 32 張牌中,選出剩餘 4 張牌的方法數為 combin(32,4) = 35,960。而選擇第三張牌點數大於 15 的另外四張牌的方法數為 combin(36,4) = 58,905。因此,對於包含至少一張點數在 16 到 19 之間的牌組,我們可以跳過 58,905-35,960=22,945 個數字。

接下來,考慮第五張牌,其點數為 25。我們可以跳過更多包含至少一張點數在 21 到 24 之間的牌的組合。從牌堆剩下的 27 張牌中選出剩下的三張牌的方法數為 combin(27,3) = 2,925。而從 combin(31,3) = 4,495 種可能的方法中,選出第四張牌點數大於 20 的另外三張牌。因此,對於包含至少一張點數在 21 到 24 之間的牌組,我們可以跳過 4,495-2,925=1,570 個數字。

接下來,考慮第六張牌,其點數為 30。我們可以跳過更多包含至少一張點數在 26 到 29 之間的牌的組合。從牌堆剩下的 22 張牌中選出剩下的兩張牌的方法數為 combin(22,2) = 231。從 combin(26,3) = 325 種可能的方法中選出第五張牌點數大於 20 的另外兩張牌。因此,對於包含至少一張點數在 26 到 29 之間的牌組,我們可以跳過 325-231=94 個數字。

現在只剩下一張牌了。從第六張牌來看,它的數字一定大於30。事實上,我們知道它是35。所以,我們可以跳過31到34這四張牌,直接選出第七張牌。

總共,我們跳過了 70,893,061+4,121,033+313,501+22,945+1,570+94+4 = 75,352,208 張卡片。

由於我們從零開始編號,就像所有優秀的程式設計師一樣,我們可以將數值分配給數字集 5,10,15,20,25,30,35 到數字 75,352,208。

當然,同樣的邏輯也適用於任何大小的牌組以及從中選擇任意數量的牌。

下週我計劃至少向您提供一份關於 2024 年 4 月 8 日日全食的初步報告!