在看 code 時又看到一段神奇的程式碼。有骰子大法的味道。

程式碼目標是隨機選出不重複的 A,B,C,其中 A 從 1 ~ N。這裡可以發現其實 A 不是隨機,所以不應該讓它也從 sample 得到。原程式碼的方法是隨機 sample 三個數字,看 A 有沒有在 sample 到的數字裡,沒有的話再重新骰一遍。另外上下文查看了一下 sort 似乎沒必要,所以就來修改了。

原始程式碼:

N = 10
for A in range(N):
    selected = []
    while A not in selected:
        selected = random.sample(range(N), 3)
        selected.sort()
    if selected.index(A) == 0:
        B = selected[1]
        C = selected[2]
    elif selected.index(A) == 1:
        B = selected[0]
        C = selected[2]
    elif selected.index(A) == 2:
        B = selected[0]
        C = selected[1]
    print(A, B, C)

這邊最主要的觀念應該是要如何避免 sample 到重複的 A,很簡單: 一開始把 A 拿掉再 sample 就好。修改後要排序也可以,B, C = selected 改成 B, C = sorted(selected) 即可。簡潔又沒有骰不到的問題。要更簡短的話可以 B, C = random.sample(...)

根據語義調整:

for A in range(N):
    selected = random.sample([i for i in range(N) if i != A], 2)
    B, C = selected
    print(A, B, C)
完整程式碼
import random

random.seed(0)

N = 10
for A in range(N):
    selected = []
    while A not in selected:
        selected = random.sample(range(N), 3)
        selected.sort()
    if selected.index(A) == 0:
        B = selected[1]
        C = selected[2]
    elif selected.index(A) == 1:
        B = selected[0]
        C = selected[2]
    elif selected.index(A) == 2:
        B = selected[0]
        C = selected[1]
    print(A, B, C)

print("---")
for A in range(N):
    selected = random.sample([i for i in range(N) if i != A], 2)
    B, C = sorted(selected)
    print(A, B, C)
python test.py
0 6 9
1 2 4
2 4 9
3 7 9
4 7 8
5 7 9
6 1 7
7 0 4
8 4 6
9 3 8
---
0 7 5
1 8 9
2 6 1
3 6 1
4 8 6
5 3 9
6 0 4
7 1 3
8 5 2
9 5 6