看起來比較亂的歌單,反而更不隨機
你把一張十二首歌的清單按下洗牌,第一首和第二首卻來自同一位歌手。第三首換了人,第六首又和第五首撞在一起。那一刻很容易得出結論:隨機按鈕根本沒有把歌打散。
這個直覺不荒謬,只是它要求的不是數學上的均勻洗牌。均勻洗牌只承諾每一個完整次序得到相同機會;它從來沒有承諾相同歌手要平均分開,也沒有承諾剛播過的顏色不能立刻再出現。
洗牌只負責換位置
本篇把十二首歌想成十二張彼此不同的票券。票券分屬 A、B、C、D 四位虛構歌手,每位各三首。電腦從最後一個位置開始,隨機挑一張尚未固定的票券交換,再往前處理下一個位置。只要每次挑選都是均勻的,最後每一種完整排列就有相同機會。
這套方法不會先看顏色。A1 剛好落在 A3 旁邊時,演算法不會覺得畫面難看,也不會把其中一張移走。對均勻洗牌來說,相鄰重複和四種顏色交錯得很整齊,都是合法結果。
重複不是罕見的失手
十二首不同歌曲共有 12!,也就是 479,001,600 種完整次序。本篇把這些次序精確數完:其中 425,471,616 種至少有一組相鄰歌曲來自同一位歌手,只有 53,529,984 種完全沒有同歌手相鄰。
換成比例,在這個「四位歌手、每位三首」的特定歌單裡,約 88.8% 的均勻排列至少會出現一次同歌手連在一起。這不是所有歌單共用的神奇常數;歌手數量與每人歌曲數改變,比例也會改變。它只證明一件事:在一個很普通的固定樣本裡,相鄰重複不是洗牌偶爾失手,而是大多數合法次序本來就有的樣子。
425,471,616 個合法次序,至少有一組同歌手相鄰。
把兩種承諾放進同一條滑槽
十二張票都會保留。差別只在:第一個按鈕讓每個完整次序等機會;第二個按鈕主動排除同歌手相鄰。
- A1
- A2
- A3
- B1
- B2
- B3
- C1
- C2
- C3
- D1
- D2
- D3
把同色拆開,規則已經換了
現在加入一條新規則:同一位歌手的票券不能相鄰。清單會立刻更接近人眼期待的亂序,四種顏色輪流出現,短時間內也比較不容易再聽到同一個聲音。
代價同樣清楚。這條規則一次排除了原本約 88.8% 的完整次序。它仍然可以使用亂數決定許多細節,卻不再讓所有排列取得相同機會。本篇因此把它叫作「間隔優先」,而不是比較高級的均勻洗牌。
間隔優先不是欺騙。若產品要照顧長時間聆聽的變化感,主動降低短期重複是合理選擇;問題只出在介面把兩種不同承諾都縮成同一個「隨機」按鈕,讓讀者無法知道系統究竟保留了哪些可能。
有些清單根本無法完全隔開
新增限制之後,系統還得面對做不到的情況。假設六首歌中有四首來自 A,另外只有 B、C 各一首。B 和 C 最多只能把清單切成三個空位,四首 A 無論怎麼放,至少會有兩首相鄰。
一般來說,想讓同一歌手完全不相鄰,歌曲最多的那一組不能比其他歌曲總數多一首以上。超過這條線,間隔優先只能盡量減少重複,不能誠實保證零重複。這個失敗條件比漂亮的交錯畫面更重要,因為它說明限制不是魔法,只是另一種取捨。
最大一組 ≤ 其餘總數 + 1
你要的是哪一種公平?
若你在做抽樣、測試,或需要解釋每個次序的機率,均勻洗牌的承諾比較乾淨;相同歌手連著出現,也應被保留下來。若你只是想讓一段通勤時間聽起來更有變化,間隔優先可能更貼近真正需求,即使它主動刪除了許多排列。
下一次相同歌手又連著出現時,不必立刻判定隨機壞了。先問那顆按鈕應該保證什麼:讓每個次序機會相同,還是讓短期感受盡量分散?看起來比較亂的歌單,有時正因為有人替它整理過。
均勻洗牌
適合抽樣、測試與需要說明機率的情境。它保留難看的重複,換來每個完整次序同樣可能。
間隔優先
適合想降低短期重複的聆聽情境。它讓感受更分散,也誠實承認自己刪除了許多排列。
資料來源與事實邊界
本篇的均勻洗牌方法依 Richard Durstenfeld 1964 年發表的 Random permutation 演算法與 NIST 的 Fisher–Yates 條目實作。互動版使用 W3C Web Cryptography API 的 crypto.getRandomValues() 取得亂數,再完成有界整數抽樣;它只是瀏覽器內的示範,不代表任何商用音樂平台採用相同方法。
約 88.8% 來自本篇公開條件下的精確枚舉;未四捨五入的結果是 88.824675324675%。它不是抽樣估計,也不是對所有歌單的概括。全文沒有判斷或暗示任何現行串流服務的實際洗牌策略。
- 1964Richard Durstenfeld, “Algorithm 235: Random permutation”,均勻排列的原始演算法來源。
- NISTDictionary of Algorithms and Data Structures:Fisher–Yates shuffle,演算法定義與複雜度說明。
- W3CWeb Cryptography API Recommendation:getRandomValues(),互動亂數來源的正式規格。
- 本篇枚舉12! = 479,001,600;無同歌手相鄰 53,529,984;至少一組相鄰 425,471,616。