2024春晚刘谦魔术与约瑟夫环问题

各位小伙伴们大家——过~年~好~~![]~( ̄▽ ̄)~*

昨晚播出了2024春节联欢晚会,本着在乡下无聊也是无聊不如看看今年春晚有没有什么乐子的心态从晚上20点到次日0点40共4个多小时的时间在人生中首次看完了一整场春晚直播

(((φ(◎ロ◎;)φ)))

刘谦的魔术节目经我和另外一位唯一也看了全场直播的小伙伴一致认为是全场最佳!春晚刚结束网上就有大佬给出了第二个魔术(拼扑克牌)的数学模拟,也有大佬发布了代码程序。今天博主在模拟了魔术过程之后,也分享一下程序代码。

顺便,借此回顾一下约瑟夫环问题。

目录

一、拼扑克牌魔术编程揭秘

1.过程图解

2.Python代码

二、约瑟夫环问题

1.问题介绍

2.数组实现

思路模拟

代码实现

3.循环链表实现

4.递归实现


一、拼扑克牌魔术编程揭秘

1.过程图解

假设初始的4张完整的牌为 [7,8,9,10]:

2.Python代码

用Python语言是因为它对列表操作(切片、拼接等)特别方便:

import random# 初始卡片cards队列,4张牌,假设为 7,8,9,10
cards = [7, 8, 9, 10]# 一、把4张牌撕开成8张,放到原来4张牌后
cards += cards
# print(cards)# 二、名字有几个字,名字有几个字就从队头拿几张牌放到队尾
# 从队头取name_len个元素插入队尾
name_len = int(input('名字长度(2~7的整数):'))  # 名字长度
for _ in range(name_len):cards.append(cards.pop(0))
# print(cards)# 三、拿起最上面三张,把这三张整体插进剩下卡片的中间任意位置
first_three = cards[:3]  # 队首3个元素,待插入 
other_cards = cards[3:]  # 剩下5个元素# 队首3个元素插入到剩下5个元素的位置是随机的
index = random.randint(1, 4)  # index 可取 1,2,3
cards = other_cards[:index] + first_three + other_cards[index:]
# print(cards)# 四、把第一张牌放到屁股下
key_card = cards.pop(0)# 五、按南北方人取牌,重复上述过程
south_north = int(input('南北方人(南方1,北方2,分不清3):'))  # 南方人还是北方人
first_cards = cards[:south_north]
other_cards = cards[south_north:]# 插入的位置是随机的
index = random.randint(1, 7 - south_north - 1)
cards = other_cards[:index] + first_cards + other_cards[index:]
# print(cards)# 六、按性别取牌,并撒出去
gender = int(input('性别(男1,女2):'))  # 性别
for _ in range(gender):cards.pop(0)
# print(cards)# 七、洗牌,“见证奇迹的时刻”
for _ in range(7):cards.append(cards.pop(0))
# print(cards)
# 此时若为女,队尾元素调整至倒数第3;若为男,倒数第2# 八、好运留下来,烦恼丢出去
while len(cards) > 1:# 好运留下来cards.append(cards.pop(0))# 烦恼丢出去cards.pop(0)# print(cards)print(f"assert cards[0] == key_card ? :{cards[0] == key_card}")

运行结果:


二、约瑟夫环问题

1.问题介绍

“约瑟夫环问题”也叫“丢手绢问题”。百度百科介绍了此问题的起源:

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

问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

可以把分析约瑟夫环问题的过程总结成以下步骤:

  • 总共有 n 个人围成一桌坐下,编号从 1 到 n,从编号为 1 的人开始报数。
  • 报数也从 1 开始,报到 m 的人出局,从出局者的下一位在座成员开始继续从 1 开始报数。
  • 重复这个过程求各成员的出局次序,或求最后一个在座的成员编号。

为了便于接下来的讨论,这里取约瑟夫环问题的一个具体的变式:

30个人在一条船上,船只超载,现需15人下船。于是人们排成一队,排队的位置即为他们的编号。人们循环报数,从1开始,数到9的人下船。如此循环,直到船上仅剩15人为止,问:都有哪些编号的人下船了?

2.数组实现

思路模拟

用数组这种数据结构来描述船上每个人之间的关系。

数组实现的方式非常简单,我们可以先手动进行以下模拟:

由此,便能得到出局的元素序列。将以上模拟过程编码就能得到解答程序。由于数组中每个元素是连续且位置固定的,当我们遍历约瑟夫环时,报数报到 m 的人要出局,此处的“出局”是逻辑删除,而不是物理删除(即只是把该号元素标记为“已出局”,而不是真的把这个元素从数组中删去)。

每次遍历约瑟夫环中元素时,通过判断该元素是否被标记为“已出局”来判断该元素是否需要进行报数,因为报数只在未出局的元素中进行。

需要特别注意的是,上述模拟中我们将第一个元素编号为1,而实际Java数组中第一个元素的下标为0。

代码实现

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;public class Solution1 {/*** 数组解决约瑟夫问题* @param n 一共有 n 个人* @param m 报数到 m 就出局* @param peopleLeft 要求最终幸存的人数*/public static List<Integer> JosephusArray(int n, int m, int peopleLeft){// 存放出局元素序列List<Integer> out_items = new ArrayList<>();// 用于标记某位置的人是否还在船上,0表示未出局,1表示已出局// 共n个元素,但由于第一个元素的下标为0,而题干要求从1开始报数,为了和下标匹配,长度定义为n+1,下标为0的元素闲置int[] flag = new int[n + 1];// cnt:目前已出局的人数;i:某编号的人;k:当前报的数int cnt = 0, i = 0, k = 0;while (peopleLeft != n-cnt) {// 从第一个人依次进行报数i++;if (i > n) {i = 1;}if (flag[i] == 0) {  // 如果 i 位置的人未出局k++;  // 就报一个数if (k == m) {  // 如果报到要求出局的数 mflag[i] = 1;  // 标记为出局cnt++;  // 已出局人数+1out_items.add(i);k = 0;  // 清空k,下次重新从0开始报数}}}return out_items;}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("数组实现约瑟夫环问题:");System.out.print("共有 n 人:");int n = scanner.nextInt();  // n 为总人数System.out.print("数到数字 m 时出局:");int m = scanner.nextInt();  // 数到 m 时出局System.out.print("要留下多少人:");int peopleLeft = scanner.nextInt();  // 要留下的人数System.out.println(JosephusArray(n, m, peopleLeft));}
}

运行结果: 

3.循环链表实现

思路模拟

用循环链表的数据结构来描述船上每个人之间的关系,示意图如下:

遍历约瑟夫环(此时是一个循环链表),每要出局一个元素,就通过更改元素之间next指向的方式将该元素真正从循环链表中删去(物理删除),并记录到出局元素序列。多轮删除后,循环链表中留下的元素即幸存者。

代码实现

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;class Node {int data;Node next;Node(int data){this.data = data;}
}public class Solution2 {/*** 循环链表解决约瑟夫问题* @param n 一共有 n 个人* @param m 报数到 m 就出局* @param peopleLeft 要求最终幸存的人数*/static List<Integer> JosephusCircleList(int n, int m, int peopleLeft) {List<Integer> out_items = new ArrayList<>();    // 存放出局元素序列// 1-创建循环链表Node head = new Node(1);    // 节点编号从1开始head.next = head;Node pre = head;for (int i = 2; i <= n; i++) {Node node = new Node(i);pre.next = node;node.next = head;pre = pre.next;}int cnt = 0;    // 已经出局了的人数Node cur = head;// 2-遍历约瑟夫环while(peopleLeft != n-cnt) {    // 当没有达到要求剩下的人数时for (int k = 1; k < m; k++) {pre = cur;cur = cur.next;}out_items.add(cur.data);cnt++;pre.next = cur.next;cur = cur.next;}return out_items;}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("循环链表实现约瑟夫环问题:");System.out.print("共有 n 人:");int n = scanner.nextInt();  // n 为总人数System.out.print("数到数字 m 时出局:");int m = scanner.nextInt();  // 数到 m 时出局System.out.print("要留下多少人:");int peopleLeft = scanner.nextInt();  // 要留下的人数System.out.println(JosephusCircleList(n,m,peopleLeft));}
}

运行结果: 

4.递归实现

(先去拜个年,拜完年回来补~)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2778290.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql索引优化建议

1&#xff0c;最左前缀法则 如果为一张表创建了多列的组合索引&#xff0c;要遵守最左前缀法则。就是指查询从索引的最左前列开始并且不要跳过索引中的列。&#xff08;因为Mysql的InnoDB引擎的索引树是一个按顺利排序存储的数据结构&#xff08;BTREE&#xff09;&#xff0c…

[论文精读]Community-Aware Transformer for Autism Prediction in fMRI Connectome

论文网址&#xff1a;[2307.10181] Community-Aware Transformer for Autism Prediction in fMRI Connectome (arxiv.org) 论文代码&#xff1a;GitHub - ubc-tea/Com-BrainTF: The official Pytorch implementation of paper "Community-Aware Transformer for Autism P…

ClickHouse--02--安装

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 安装官网 &#xff1b;[https://clickhouse.com/docs/zh/getting-started/install](https://clickhouse.com/docs/zh/getting-started/install)![在这里插入图片描述…

【算法与数据结构】42、LeetCode接雨水

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;   程序如下&#xff1a; 复杂度分析&#xff1a; 时间复杂度&#xff1a; O ( ) O() O()。空间复…

JDK新特性

JDK新特性 函数式接口和Lambda 表达式Stream流操作新日期API操作其他新特性 Lambda 是一个匿名函数&#xff0c;我们可以把 Lambda表达式理解为是一段可以传递的代码&#xff08;将代码 像数据一样进行传递&#xff09;。可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码…

网络原理(一)

&#x1f495;"Echo"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;网络原理(一) 一. 应用层 应用层是和程序员联系最密切的一层,对于应用层来说,程序员可以自定义应用层协议,应用层的协议一般要约定好以下两部分内容: 根据需求,明确要传输哪些信…

[职场] 测试工程师面试会问些什么 #其他#微信#学习方法

测试工程师面试会问些什么 在测试工程师面试过程中&#xff0c;可能会涉及到具体测试工具、技术和方法的问题。所以在准备面试前&#xff0c;需要熟悉常用的测试理论和实践&#xff0c;掌握基本的测试技能和工具使用。 一.常见问题及答案 1. 你是如何理解软件测试的作用和重要…

nginx添加lua模块

目录 已安装了nginx&#xff0c;后追加lua模块nginx 重新编译知识参考&#xff1a; 从零安装一、首先需要安装必要的库&#xff08;pcre、zlib、openssl&#xff09;二、安装LUA环境及相关库 &#xff08;LuaJIT、ngx_devel_kit、lua-nginx-module&#xff09;注意&#xff1a;…

C# 夺冠,微软.NET前途光明!

本文以C# 摘得 “2023 年度编程语言“称号为背景&#xff0c;介绍.NET的历史、生态及发展势头&#xff0c;该文章是本人C#专栏的第一篇文章。 这里写目录标题 1.C#摘得"2023年度编程语言"奖项2.什么是.NET&#xff1f;2.1.NET简史2.2.NET是用于应用程序开发的生态系…

【Java EE初阶十二】网络初识

1. 网络发展史 网络发展的几个主要时期&#xff1a; 单机时代->局域网时代->广域网时代->移动互联网时代 随着时代的发展&#xff0c;越来越需要计算机之间互相通信&#xff0c;共享软件和数据&#xff0c;即以多个计算机协同工作来完成 业务&#xff0c;就有了网络互…

【Linux系统学习】6.Linux系统软件安装

实战章节&#xff1a;在Linux上部署各类软件 前言 为什么学习各类软件在Linux上的部署 在前面&#xff0c;我们学习了许多的Linux命令和高级技巧&#xff0c;这些知识点比较零散&#xff0c;进行练习虽然可以基础掌握这些命令和技巧的使用&#xff0c;但是并没有一些具体的实…

LLM之RAG实战(二十五)| 使用LlamaIndex和BM25重排序实践

本文&#xff0c;我们将研究高级RAG方法的中的重排序优化方法以及其与普通RAG相比的关键差异。 一、什么是RAG&#xff1f; 检索增强生成&#xff08;RAG&#xff09;是一种复杂的自然语言处理方法&#xff0c;它包括两个不同的步骤&#xff1a;信息检索和生成语言建模。这种方…

YOLOv8算法改进【NO.101】引入最新的损失函数Focaler-IoU

前 言 YOLO算法改进系列出到这&#xff0c;很多朋友问改进如何选择是最佳的&#xff0c;下面我就根据个人多年的写作发文章以及指导发文章的经验来看&#xff0c;按照优先顺序进行排序讲解YOLO算法改进方法的顺序选择。具体有需求的同学可以私信我沟通&#xff1a; 第一…

C#向数组指定索引位置插入新的元素值:自定义插入方法 vs List<T>.Add(T) 方法

目录 一、使用的方法 1.自定义插入方法 2.使用List.Add(T) 方法 二、实例 1.示例1&#xff1a;List.Add(T) 方法 2.示例&#xff1a;自定义插入方法 一、使用的方法 1.自定义插入方法 首先需要定义一个一维数组&#xff0c;然后修改数组的长度(这里使用Length属性获取…

统计数字出现次数的数位动态规划解法-数位统计DP

在处理数字问题时,我们经常遇到需要统计一定范围内各个数字出现次数的情况。这类问题虽然看起来简单,但当数字范围较大时,直接遍历统计的方法就变得不再高效。本文将介绍一种利用数位动态规划(DP)的方法来解决这一问题,具体来说,是统计两个整数a和b之间(包含a和b)所有…

题目练习(生死时速2.0版)

题目一&#xff08;Before an Exam&#xff09; 题意翻译 题目背景 明天皮特将要考生物。他并不很喜欢生物&#xff0c;但在 d 天前他得知他将不得不参加此次考试。皮特严厉的父母勒令他立即复习&#xff0c;因此他在第 i 天将需要学习不少于 minTimei​ 小时&#xff0c;不…

Java:JDK8新特性(Stream流)、File类、递归 --黑马笔记

一、JDK8新特性&#xff08;Stream流&#xff09; 接下来我们学习一个全新的知识&#xff0c;叫做Stream流&#xff08;也叫Stream API&#xff09;。它是从JDK8以后才有的一个新特性&#xff0c;是专业用于对集合或者数组进行便捷操作的。有多方便呢&#xff1f;我们用一个案…

备战蓝桥杯---动态规划之经典背包问题

看题&#xff1a; 我们令f[i][j]为前i个物品放满容量为j的背包的最大价值。 f[i][j]max(f[i-1][j],f[i-1][j-c[i]]w[i]); 我们开始全副成负无穷。f[0][0]0;最后循环最后一行求max; 负无穷&#xff1a;0xc0c0c0c0;正无穷&#xff1a;0x3f3f3f3f 下面是v12,n6的图示&#xff…

vue2源码调试,在vscode中直接调试vue源代码操作指南

依赖安装 使用 yarn 安装所有依赖 package.json 启动 添加配置 在dev 命令里 加上 –sourcemap,便于源码调试 在源码根目录中运行npm run dev 运行npm run dev 在dist文件夹下生成 vue.js文件 新建一个test目录&#xff0c;并创建test.html文件用于测试 m在html文件中使…

【Linux】构建模块

&#x1f525;博客主页&#xff1a;PannLZ &#x1f38b;系列专栏&#xff1a;《Linux系统之路》 &#x1f94a;不要让自己再留有遗憾&#xff0c;加油吧&#xff01; 文章目录 构建第一个模块1模块的makefile2内核树内构建3内核树外构建 构建第一个模块 可以在两个地方构建模…