"""
三個商人帶了三個隨從準備過河,目前只有一條空船(至少需要一人划船),並且最大承重兩人,
這時隨從商議在河的任意一岸只要商人的數量少於隨從的數量,那隨從就會殺人越貨,
請問商人要怎麼安全過河?
"""
from collections import Counter
from random import sample, randint
class Solution:
"""解決問題的方案類"""
def __init__(self):
"""初始化屬性"""
self.left = ['商人'] * 3 + ['隨從'] * 3 # 後面用到了Counter,所以這裏可以用字符串表示,不用0,1表示,更直觀一點
self.left_checkpoint = [] # 左邊的存檔,用於試錯後恢復
self.right = []
self.right_checkpoint = []
self.result = [[]] # 結果,給個初始值是爲了避免out of index的情況,取結果的時候切片即可
self.result_checkpoint = []
self.r_direction = True # True爲右,False爲左
def go(self):
"""渡河"""
if self.r_direction: # 向右渡河
boat = sample(self.left, 2)
for i in boat:
self.left.remove(i)
self.right.append(i)
else: # 向左渡河
if len(self.right) > 1: # 這裏判斷是爲了避免sample取的時候越界(從1個裏面取2個)
boat = sample(self.right, randint(1, 2))
else:
boat = sample(self.right, 1)
for i in boat:
self.right.remove(i)
self.left.append(i)
return boat
def judge(self):
"""判斷"""
if self.left and self.right:
left_counter = Counter(self.left)
right_counter = Counter(self.right)
if (left_counter['商人'] and left_counter['商人'] < left_counter['隨從']) or \
(right_counter['商人'] and right_counter['商人'] < right_counter['隨從']):
return False
return True
def checkpoint(self):
"""檢查點"""
self.left_checkpoint, self.right_checkpoint, self.result_checkpoint = \
self.left.copy(), self.right.copy(), self.result.copy()
def reset(self):
"""讀檔"""
self.left, self.right, self.result = \
self.left_checkpoint.copy(), self.right_checkpoint.copy(), self.result_checkpoint.copy()
def get_result(self):
"""模擬渡河過程,獲取結果"""
while len(self.right) < 6:
self.checkpoint() # 存檔
boat = self.go() # 渡河
boat.sort()
if self.judge() and boat != self.result[-1]: # 這裏判斷是爲了避免相同的人來回的情況,以求儘可能少的解
self.r_direction = not self.r_direction # 調轉船頭
self.result.append(boat)
else:
self.reset() # 讀檔
return self.result[1:]
def main():
"""主函數"""
repeat = 10000 # 重複執行次數
result_set = set() # 解的集合
solution = Solution()
for _ in range(repeat):
result = solution.get_result()
result_set.add(str(result))
solution.__init__()
print(f'經{repeat}次執行,共得到{len(result_set)}種不同的結果,結果如下:', end='\n\n')
for result in result_set:
print(result)
if __name__ == '__main__':
main()
結果:
[['隨從', '隨從'], ['隨從'], ['隨從', '隨從'], ['隨從'], ['商人', '商人'], ['商人', '隨從'], ['商人', '商人'], ['隨從'], ['隨從', '隨從'], ['商人'], ['商人', '隨從']]
[['商人', '隨從'], ['商人'], ['隨從', '隨從'], ['隨從'], ['商人', '商人'], ['商人', '隨從'], ['商人', '商人'], ['隨從'], ['隨從', '隨從'], ['商人'], ['商人', '隨從']]
[['隨從', '隨從'], ['隨從'], ['隨從', '隨從'], ['隨從'], ['商人', '商人'], ['商人', '隨從'], ['商人', '商人'], ['隨從'], ['隨從', '隨從'], ['隨從'], ['隨從', '隨從']]
[['商人', '隨從'], ['商人'], ['隨從', '隨從'], ['隨從'], ['商人', '商人'], ['商人', '隨從'], ['商人', '商人'], ['隨從'], ['隨從', '隨從'], ['隨從'], ['隨從', '隨從']]