您当前的位置:首页 > 计算机 > 编程开发 > Python

基督徒问题的三种python实现方式

时间:12-06来源:作者:点击数:

问题:

有15个基督徒和15个非基督徒在海上遇险,为了能让一部分人活下来不得不将其中15个人扔到海里面去。

有个人想了个办法就是大家围成一个圈,由某个人开始从1报数,报到9的人就扔到海里面,他后面的人接着从1开始报数,报到9的人继续扔到海里面,直到扔掉15个人。

由于上帝的保佑,15个基督徒都幸免于难,问这些人最开始是怎么站的,哪些位置是基督徒哪些位置是非基督徒。

方案一:位置标记

思路:

由于需要标记哪些位置是非基督徒(被扔海里的人),所以30个人的位置不能变,被扔海里的人的位置还需要留着。

所以用people来轮询报数的人的位置,由于是个圈,所以超过30之后要取余数。

用'1'表示活着,用'0'表示丢海里死掉了,是个空位置。

所以刚开始的时候有30个'1'。

然后每次数到9,就把'1'变成'0',报数的时候先判断那个位置上有没有人(是‘1’还是‘0’),没人(‘0’)就跳过。

people_list = list('1'*30) # 用1表示活着
people = 0 # 位置索引
dead = 0   # 统计死掉的人
count = 1  # 报数
while dead < 15:
	people = people % 30  # 围成一个圈,所以30个人不停循环
	if people_list[people] == '1': 		# 如果这个人还没死
		if count == 9:					  # 如果他报了9
			people_list[people] = '0'     # 那他就死了
			dead = dead + 1               # 死掉的人+1
			count = 1 					  # 重新报数
		else:							# 如果不是报的9
			count = count + 1 			  # 下一个人报数+1
	people = people + 1 				# 下一个人继续

print(people_list)

结果:

类似的思路也可以用来解决灯开关的问题:

有100盏灯,初始状态为关闭,全由拉绳开关控制。

第一次:被3整除的灯拉一次开关。

第二次:被5整除的灯拉一次开关。

第三次:被7整除的灯拉一次开关 。

最后有几盏灯亮,分别是哪几盏灯?

deng = list('开'*100)

def on_down(i):
	global deng
	if deng[i] == '开':
		deng[i] = '关'
	else:
		deng[i] = '开'

for i in range(100):
	if (i+1)%3 ==0:
		on_down(i)
	if (i+1)%5 ==0:
		on_down(i)
	if (i+1)%7 ==0:
		on_down(i)

print(deng)

方案二:重新组队

双向队列可以同时在左右两边进行增加和删除,每次把队列左边的8个人拿出来放到队列右边,这时候最左边的人就是报数9的人,毫不犹豫地杀掉,然后继续从左边取8个人放到队列右边,重复15次就完事了。

import collections

q = collections.deque([i for i in range(1, 31)]) # 从1到30的队列

for _ in range(15):    # 重复15次,杀掉15个人
    for _ in range(8):  # 每次拿出8个人
        q.append(q.popleft())  # 把这8个人从左边放到右边
    q.popleft()  # 拿完8个人就杀掉最左边的人(第9个人)

print(q)

结果:

其实用列表也可以更简单地实现:

lists = [i for i in range(1, 31)]
for i in range(15):
	lists = lists[9:] + lists[:8]  # 第9个人之后的队伍和前8个人重新组成数组
print(lists)

结果:

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐