问题来历据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决。Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

引言约瑟夫环是一个数学的应用问题,也是利用Python设计程序进行解答的一个经典编程问题,我们将用Python程序完整地表达出我们的数学思维,进而解决问题。

问题描述已知 n 个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。. 从编号为 k 的人开始报数,数到 m 的那个人出圈;他的下一个人又从 1 开始报数,数到 m 的那个人又出圈;依此规律重复下去,直到剩余最后一个胜利者。. 例如:有10个人围成一圈进行此游戏,每个人编号为 1-10 。. 若规定数到 3 的人出圈。. 则游戏过程如下。(1)开始报数,第一个数到 3 的人为 3 号,3 号出圈。(2)从4号重新从1开始计数,则接下来数到3的人为6号,6号出圈。(3)按以上的方法依次类推。

算法描述

 

 

 

所需函数

def: Python 使用def开始函数定义,紧接着是函数名,括号内部为函数的参数,内部为函数的 具体功能实现代码。

for-in-循环for...in 语句用于对数组或者对象的属性进行循环操作。 for... in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。 

while循环如果使用 while 循环,只要条件为真,我们就可以一直执行一组语句直到条件不成立。

returnreturn 表示把程序流程从被调函数转向主调函数并把表达式的值带回主调函数,实现函数值的返回,返回时可附带一个返回值,由return后面的参数指定。

完整代码

ls1 = [i for i in range(1,42)]
ls2 = []
num = 0
while len(ls1) > 1:
    num +=1
    count = ls1.pop(0)
    if num == 3:
        ls2.append(count)
        num = 0
    else:
        ls1.append(count)
print(ls1)

 

代码进阶:我们可以在此代码的基础上使用def定义函数而设定不同参数(数据个数、间隔数),以使用于不同场景。

def Josephus(data,step):
    ls1 = [i for i in range(1,data+1)]
    ls2 = []
    num = 0
    while len(ls1) > 1:
        num +=1
        count = ls1.pop(0)
        if num == step:
            ls2.append(count)
            num = 0
        else:
            ls1.append(count)
    return {
        "lastData":ls1[0],
        "delData":ls2
    }
result = Josephus(55,4)
print("最后剩下的是第",result["lastData"],"人")
print("淘汰顺序为",result["delData"])

 

运行结果为:

 

结语

本文介绍了约瑟夫环的问题来历,以及如何使用Python设计程序解决约瑟夫环,并且进行了拓展,使该程序能应用于更多相似的问题。

但对于使用到函数的介绍相对空乏,并未通过举例详细介绍函数的使用方法,会对此加以改进。后续还会对Python算法的经典案例进行研究并以自己认为容易理解的方式进行分析,敬请期待!

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐