问题描述:
据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
看的视频中是用C语言写的,所以自己想用Python去实现,一开始掉入了C语言中的思维陷阱,因为约瑟夫环属于循环列表,在C语言中,每次点到那个被杀掉的人,链表中的元素位置就需要重新分配下,而Python不需要,无论是往列表中增加还是删除元素,都很方便。
初始我总是想着像C语言那样去实现,点到那个被杀的人之后,把这个人从列表中的位置去除掉。但就是写不出来代码,后来一想,把被杀掉的人那个位置赋值为0,就代表他已经被杀了,下次数数的时候就跳过去。
代码:
a = range(1,42)
list = list(a)
# list:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
# 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41]
flag = 1
index = 0
print("被杀掉的顺序为:")
while True:
if (flag == 3) & (list[index]!=0): # 当数到3且那个人位置不为0时,才表示这个人要被杀掉
flag = 1
print('->' + str(list[index]))
list[index] = 0 # 置为0,表示这个位置的人已被杀掉
if index == 40: # 当索引到最后一个位置时
index = -1
if len(list) == 0: # 当所有人都被杀掉
break
if list[index]!=0: #
flag += 1
index += 1
# 输出:
# 被杀掉的顺序为:
# ->3->6->9->12->15->18->21->24->27->30->33->36->39->1->5->10->14->19->23
# ->28->32->37->41->7->13->20->26->34->40->8->17->29->38->11->25->2->22->4->35->16->31