python解决约瑟夫环问题

标题python解决约瑟夫环问题

问题描述:编号为 1-N 的 N 个士兵围坐在一起形成一个圆圈,从编号为 1 的士兵开始依次报数(1,2,3…这样依次报),数到 m 的 士兵会被杀死出列,之后的士兵再从 1 开始报数。直到最后剩下一士兵,求这个士兵的编号。

有用递归函数 f(n,m) 的返回结果是存活士兵的编号,推导出old 与 new 之间的关系为 old = (new + m - 1) % n + 1。即f(n,m)=(f(n - 1, m) + m - 1) % n + 1,号称可以一行代码可以搞定,按着学习的思路。
用python写出代码如下:如果n=6,m=4时:去除的编号为4 2 1 3 6 5;

def f( n,  m):
    if(n == 1):  
        return n
    # print(n-1,m,f(n - 1, m) )
    return (f(n - 1, m) + m - 1) % n + 1
print(f(6,4))

如果去掉#print 的行,一共有5行代码;
但发现有两个问题:
一、推导出最后的数字是对的,但过程中的未显示出来;
二、如果把f(n-1,m);f(n-2,m)…f(1,m)显示出来,发现并不是想要的编码结果;
f(1,4)=1;f(2,4)=1;f(3,4)=2;f(4,4)=2;f(5,4)=1,f(6,4)=5 只有最后的数字是对的;

如何能用比较短的行代码来运行出正确的顺序并显示出来呢

写出代码如下:应该有高手来总结出更简洁的代码

n=6;m=4;a=(list(i for i in range(1,n+1))*3*m);
for j in range(1,n):
	print ("删除: ",a[m-1]);b=a[m-1];a=a[m:];
	for i in range(len(a)-1,-1,-1):
		if a[i]==b:a.pop(i)
print ("剩余: ",a[0])

运行结果如下:
删除: 4
删除: 2
删除: 1
删除: 3
删除: 6
剩余: 5
顺序与编号都是一致的,用了6行代码;
首先建立一个大list,让1到n循环3M次(不是口罩了,都卖脱销了,这里也没有;注:2M次会出错)
然后运行n-1次,从头数M个数,即为要删除的数,在此数前全部不要,后面含此数的也遍历删除,然后再数M个数。。。直到剩余一个数并显示出来。
不会用for循环 和if在一行语句里判断,请高手来指导,争取也能两行完成。

后记:
用第一个递推时,运行f(3811,4)时出错,机器的递归深度达到极限了,虽然用
import sys
sys.setrecursionlimit(1000000) #修改递归深度的值
但没有什么用,第二个程序出错,

import math
n=10000;m=4;a=(list(i for i in range(1,n+1))*int((-1)*math.log(n)/math.log((m-1)/m)+1));
for j in range(1,n):
	print ("删除: ",a[m-1],end='');b=a[m-1];a=a[m:];
	for i in range(len(a)-1,-1,-1):
		if a[i]==b:a.pop(i)
print ("剩余: ",a[0])

这样修改了,不出错了,但代码又长了一点。运行时间也长了。但当n<m时,又出错了,原来是list的定义有了问题,再次修改。

import math
n=10000;m=4;a=(list(i for i in range(1,n+1))*(3*m if m>n else int((-1)*math.log(n)/math.log((m-1)/m)+1)));
for j in range(1,n):
	print ("删除: ",a[m-1]);b=a[m-1];a=a[m:];
	for i in range(len(a)-1,-1,-1):
		if a[i]==b:a.pop(i)
print ("剩余: ",a[0])

运行正常,能不能再把list只用一次,然后循环利用呢,答案是可以的,用截取再相加的方法,循环利用list

n=12;m=4;a=(list(i for i in range(1,n+1)))
for j in range(1,n):
	d=(m if m<=len(a) else (len(a) if m%len(a)==0 else m%len(a)));b=a[:d-1];c=a[d-1];print ("删除: ",c);a=a[d:];a=a+b
print ("剩余: ",a[0])

其中的条件语句是这样的:
条件为真的值 if 条件 else 条件为假的值

运行也快,解决,如果能把for 和 print也能写入一行,就再完美了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值