用Python来实现2024年春晚刘谦魔术

news2024/11/19 10:08:09

简介

这是新春的第一篇,今天早上睡到了自然醒,打开手机刷视频就被刘谦的魔术所吸引,忍不住用编程去模拟一下这个过程。

首先,声明的一点,大年初一不学习,所以这其中涉及的数学原理约瑟夫环大家可以找找其他的教程看看,我这块只是复现它魔术里面的每个步骤。

魔术的步骤

总而言之,可以分为以下8个步骤:

Step 1: 将四张4张牌撕成两半,直接将两堆叠放;
Step 2: 假设姓名为n个字,重复n次,将堆在最上的牌放到最下面;
Step 3: 将牌堆最上的3张拿出,不改变顺序,并随机插入牌堆中间;
Step 4: 将牌堆最上方的牌拿走,放在一旁;
Step 5: 按照南/北/不知道是南或者北方地区,判断自己属于哪一地区,并分别将牌堆最上的1/2/3,不改变顺序,并随机插入牌堆中间;
Step 6: 按性别男/女,从牌堆最上方拿走1/2张牌,一边念口诀:“见证奇迹的时刻”,每念一个字,将牌堆最上方的牌放到牌堆最下;
Step 7: 念口诀“好运留下米”时,将牌堆最上的牌放到牌堆最下;念“烦恼扔出去”时,将牌堆最上方的牌移除。重复这两句口诀,直到手中只有一张牌;
Step 8: 最后留下的牌和Step 4拿走的牌是一样的。

过程拆开分来其实就是对列表进行一个简单的操作了

用python实现其中的过程

0. 模拟扑克牌打乱并抽取的过程;

import random
import itertools
import copy
# 定义扑克牌
suits = ['红桃', '方块', '梅花', '黑桃']
ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
jokers = ['小王', '大王']
deck_of_cards = list(itertools.product(suits, ranks)) + jokers
random.shuffle(deck_of_cards)       # 模拟打乱的操作
print(f"随机生成的{len(deck_of_cards)}扑克牌:", deck_of_cards)
selected_cards = random.sample(deck_of_cards, 4)
print("随机抽取其中的四张牌:", selected_cards)

随机抽取其中的四张牌: [('红桃', '9'), ('黑桃', '8'), ('黑桃', 'A'), ('黑桃', 'K')]

1. 将四张4张牌撕成两半,直接将两堆叠放;

def split_and_stack(cards):
    cards_copy = copy.copy(cards)
    merged_cards = cards + cards_copy
    return merged_cards

split_cards = split_and_stack(selected_cards)
print("撕成两半后堆叠:", split_cards)

撕成两半后堆叠: [('红桃', '9'), ('黑桃', '8'), ('黑桃', 'A'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', '8'), ('黑桃', 'A'), ('黑桃', 'K')]

2. 假设姓名为n个字,重复n次,将堆在最上的牌放到最下面;

def repeat_name(cards, name):
    name_length = len(name)
    for _ in range(name_length):
        # 取出堆在最上的牌,放到最下面
        top_card = cards.pop(0)  
        cards.append(top_card) 
    return cards

split_cards_repeated = repeat_name(split_cards, name)
print(f"{name} 重复姓名字数次后的牌堆:", split_cards_repeated)

夏天是冰红茶 重复姓名字数次后的牌堆: [('黑桃', 'A'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', '8'), ('黑桃', 'A'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', '8')]

3. 将牌堆最上的3张拿出,不改变顺序,并随机插入牌堆中间;

def take_top_and_insert(cards):
    top_three_cards = cards[:3]  # 取出最上面的3张牌
    remaining_cards = cards[3:]  # 剩下的牌
    insert_index = random.randint(1, len(remaining_cards))
    shuffled_cards = remaining_cards[:insert_index] + top_three_cards + remaining_cards[insert_index:]
    return shuffled_cards

shuffled_cards = take_top_and_insert(split_cards_repeated)
print("牌堆最上的3张拿出,随机插入后的牌堆:", shuffled_cards)

牌堆最上的3张拿出,随机插入后的牌堆: [('黑桃', '8'), ('黑桃', 'A'), ('黑桃', 'A'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', '8')]

4. 将牌堆最上方的牌拿走,放在一旁;

def take_top_card(cards):
    top_card = cards.pop(0)  # 取出最上方的牌
    return top_card

top_card = take_top_card(shuffled_cards)
print("拿走的牌:", top_card)
print("剩余的牌:", shuffled_cards)

拿走的牌: ('黑桃', '8')
剩余的牌: [('黑桃', 'A'), ('黑桃', 'A'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', '8')] 

5. 按照南/北/不知道是南或者北方地区,判断自己属于哪一地区,并分别将牌堆最上的1/2/3,不改变顺序,并随机插入牌堆中间;

def insert_cards_based_on_region(cards, region):
    if region == "南":
        insert_count = 1
    elif region == "北":
        insert_count = 2
    else:
        insert_count = 3

    top = cards[:insert_count]
    remaining_cards = cards[insert_count:]
    insert_index = random.randint(0, len(remaining_cards)-1)
    shuffled_cards = remaining_cards[:insert_index] + top + remaining_cards[insert_index:]

    return shuffled_cards


shuffled_cards_region = insert_cards_based_on_region(shuffled_cards, region)
print(f"{region}方地区插入后的牌堆:", shuffled_cards_region)

南方地区插入后的牌堆: [('黑桃', 'A'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', 'K'), ('黑桃', 'A'), ('红桃', '9'), ('黑桃', '8')] 

6. 按性别男/女,从牌堆最上方拿走1/2张牌,一边念口诀:“见证奇迹的时刻”,每念一个字,将牌堆最上方的牌放到牌堆最下;

def take_and_chant(cards, gender, chant="见证奇迹的时刻"):
    take_count = 0
    if gender == "男":
        take_count = 1
    elif gender == "女":
        take_count = 2
    else:
        print("未知性别")

    remaining_cards = cards[take_count:]  # 剩下的牌
    print(remaining_cards)
    # 念口诀过程
    for c in chant:
        remaining_cards.append(remaining_cards.pop(0))  # 将最上方的牌放到牌堆最下

    return remaining_cards

remaining_cards= take_and_chant(shuffled_cards_region, gender, chant)
print(f"剩余的牌堆:", remaining_cards)

[('黑桃', 'K'), ('红桃', '9'), ('黑桃', 'K'), ('黑桃', 'A'), ('红桃', '9'), ('黑桃', '8')]
剩余的牌堆: [('红桃', '9'), ('黑桃', 'K'), ('黑桃', 'A'), ('红桃', '9'), ('黑桃', '8'), ('黑桃', 'K')] 

7/8. 念口诀“好运留下米”时,将牌堆最上的牌放到牌堆最下;念“烦恼扔出去”时,将牌堆最上方的牌移除。重复这两句口诀,直到手中只有一张牌;最后留下的牌和Step 4拿走的牌是一样的。

def chant_and_modify(cards):
    iter = 1
    while len(cards) > 1:
        chant_good_luck = "好运留下米"
        chant_throw_away = "烦恼扔出去"
        print(f"\n第{iter}轮口诀开始:")
        cards.append(cards.pop(0))
        print(f"口诀{chant_good_luck}结束后手上的牌:", cards)
        cards.pop(0)
        print(f"口诀{chant_throw_away}结束后手上的牌:", cards)
        iter += 1

    return cards[0]

final_card = chant_and_modify(remaining_cards)
print(f"\n最终留下的牌:{final_card}, Step 4:{top_card}")

第1轮口诀开始:
口诀好运留下米结束后手上的牌: [('黑桃', 'K'), ('黑桃', 'A'), ('红桃', '9'), ('黑桃', '8'), ('黑桃', 'K'), ('红桃', '9')]
口诀烦恼扔出去结束后手上的牌: [('黑桃', 'A'), ('红桃', '9'), ('黑桃', '8'), ('黑桃', 'K'), ('红桃', '9')]

第2轮口诀开始:
口诀好运留下米结束后手上的牌: [('红桃', '9'), ('黑桃', '8'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', 'A')]
口诀烦恼扔出去结束后手上的牌: [('黑桃', '8'), ('黑桃', 'K'), ('红桃', '9'), ('黑桃', 'A')]

第3轮口诀开始:
口诀好运留下米结束后手上的牌: [('黑桃', 'K'), ('红桃', '9'), ('黑桃', 'A'), ('黑桃', '8')]
口诀烦恼扔出去结束后手上的牌: [('红桃', '9'), ('黑桃', 'A'), ('黑桃', '8')]

第4轮口诀开始:
口诀好运留下米结束后手上的牌: [('黑桃', 'A'), ('黑桃', '8'), ('红桃', '9')]
口诀烦恼扔出去结束后手上的牌: [('黑桃', '8'), ('红桃', '9')]

第5轮口诀开始:
口诀好运留下米结束后手上的牌: [('红桃', '9'), ('黑桃', '8')]
口诀烦恼扔出去结束后手上的牌: [('黑桃', '8')]

最终留下的牌:('黑桃', '8'), Step 4:('黑桃', '8')

完整的代码

import random
import itertools
import copy
# 定义扑克牌
suits = ['红桃', '方块', '梅花', '黑桃']
ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
jokers = ['小王', '大王']
deck_of_cards = list(itertools.product(suits, ranks)) + jokers
random.shuffle(deck_of_cards)       # 模拟打乱的操作
print(f"随机生成的{len(deck_of_cards)}扑克牌:", deck_of_cards)
selected_cards = random.sample(deck_of_cards, 4)
print("随机抽取其中的四张牌:", selected_cards)


# 模拟性别为男的情况
name = "夏天是冰红茶"
gender = "男"
chant = "见证奇迹的时刻"
region = "南"

# step 1: 将四张4张牌撕成两半,直接将两堆叠放;
def split_and_stack(cards):
    cards_copy = copy.copy(cards)
    merged_cards = cards + cards_copy
    return merged_cards

split_cards = split_and_stack(selected_cards)
print("撕成两半后堆叠:", split_cards)

# Step 2: 设你的姓名为n个字,重复n次,将堆在最上的牌放到最下面;
def repeat_name(cards, name):
    name_length = len(name)
    for _ in range(name_length):
        # 取出堆在最上的牌,放到最下面
        top_card = cards.pop(0)
        cards.append(top_card)
    return cards

split_cards_repeated = repeat_name(split_cards, name)
print(f"{name} 重复姓名字数次后的牌堆:", split_cards_repeated)

# Step 3: 将牌堆最上的3张拿出,不改变顺序,并随机插入牌堆中间
def take_top_and_insert(cards):
    top_three_cards = cards[:3]  # 取出最上面的3张牌
    remaining_cards = cards[3:]  # 剩下的牌
    insert_index = random.randint(1, len(remaining_cards))
    shuffled_cards = remaining_cards[:insert_index] + top_three_cards + remaining_cards[insert_index:]
    return shuffled_cards

shuffled_cards = take_top_and_insert(split_cards_repeated)
print("牌堆最上的3张拿出,随机插入后的牌堆:", shuffled_cards)

# Step 4: 将牌堆最上方的牌拿走,放在一旁
def take_top_card(cards):
    top_card = cards.pop(0)  # 取出最上方的牌
    return top_card

top_card = take_top_card(shuffled_cards)
print("拿走的牌:", top_card)
print("剩余的牌:", shuffled_cards)

# Step 5: 按照南/北/不知道是南或者北方地区,判断自己属于哪一地区,并分别将牌堆最上的1/2/3,不改变顺序,并随机插入牌堆中间
def insert_cards_based_on_region(cards, region):
    if region == "南":
        insert_count = 1
    elif region == "北":
        insert_count = 2
    else:
        insert_count = 3

    top = cards[:insert_count]
    remaining_cards = cards[insert_count:]
    insert_index = random.randint(0, len(remaining_cards)-1)
    shuffled_cards = remaining_cards[:insert_index] + top + remaining_cards[insert_index:]

    return shuffled_cards


shuffled_cards_region = insert_cards_based_on_region(shuffled_cards, region)
print(f"{region}方地区插入后的牌堆:", shuffled_cards_region)


# Step 6: 按性别男/女,从牌堆最上方拿走1/2张牌,一边念口诀:“见证奇迹的时刻”,每念一个字,将牌堆最上方的牌放到牌堆最下。
def take_and_chant(cards, gender, chant="见证奇迹的时刻"):
    take_count = 0
    if gender == "男":
        take_count = 1
    elif gender == "女":
        take_count = 2
    else:
        print("未知性别")

    remaining_cards = cards[take_count:]  # 剩下的牌
    print(remaining_cards)
    # 念口诀过程
    for c in chant:
        remaining_cards.append(remaining_cards.pop(0))  # 将最上方的牌放到牌堆最下

    return remaining_cards


remaining_cards= take_and_chant(shuffled_cards_region, gender, chant)
print(f"剩余的牌堆:", remaining_cards)

# Step 7: 念口诀“好运留下米”时,将牌堆最上的牌放到牌堆最下;念“烦恼扔出去”时,将牌堆最上方的牌移除。重复这两句口诀,直到手中只有一张牌;
def chant_and_modify(cards):
    iter = 1
    while len(cards) > 1:
        chant_good_luck = "好运留下米"
        chant_throw_away = "烦恼扔出去"
        print(f"\n第{iter}轮口诀开始:")
        cards.append(cards.pop(0))
        print(f"口诀{chant_good_luck}结束后手上的牌:", cards)
        cards.pop(0)
        print(f"口诀{chant_throw_away}结束后手上的牌:", cards)
        iter += 1

    return cards[0]

# Step 8: 最后留下的牌和Step 4拿走的牌是一样的。
final_card = chant_and_modify(remaining_cards)
print(f"\n最终留下的牌:{final_card}, Step 4:{top_card}")

大家可以自己去试一试,在步骤6后男生拿走的牌总是会在对应的第5位,女生拿走的牌总是会在对应的第3位。

结语

其实说实话,这种数学魔术在我小时候买的书里就曾经看到过许多。虽然现在了解了其中的数学原理,但当时的惊奇与欢乐感觉依然难以忘怀。刘谦老师在表演中展现了非凡的技艺,不仅仅是数学的巧妙运用,更是他善于抓住观众的好奇心,创造出让人难以置信的奇迹。

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

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

相关文章

【C++】友元、初始化列表、内部类、static修饰成员详解

文章目录 前言1. 构造函数不为人知的那些事1.1 构造函数体赋值1.2 初始化列表1.3 explicit关键字 2. static成员2.1 概念2.2 特性2.3 小总结 3. C11 成员变量初始化新用法4. 友元4.1 友元函数4.2 友元类 5. 内部类5.1概念及特性 总结 前言 提示:这里可以添加本文要…

Qt安装配置教程windows版(包括:Qt5.8.0版本,Qt5.12,Qt5.14版本下载安装教程)(亲测可行)

目录 Qt5.8.0版本安装教程Qt5.8.0版本下载安装 Qt5.12.2版本安装教程下载安装 Qt 5.14.2安装教程下载安装和创建项目 参考视频 QT为嵌入式系统提供了大量的库和可重用组件。 WPS Office,咪咕音乐,Linux桌面环境等都是QT开发的。 Qt5.8.0版本安装教程 Q…

MinIO对象存储介绍和使用

一、MinIO介绍 MinIO 是一个开源的对象存储服务器。MinIO 提供了一个强大而灵活的对象存储解决方案,适用于各种规模的应用场景。详细介绍可看官网文档:MinIO对象存储 Windows — MinIO中文文档 | MinIO Windows中文文档 1.1 特点 高性能: MinIO 具有出…

【深度学习】:滴滴出行-交通场景目标检测

清华大学驭风计划课程链接 学堂在线 - 精品在线课程学习平台 (xuetangx.com) 代码和报告均为本人自己实现(实验满分),只展示主要任务实验结果,如果需要详细的实验报告或者代码可以私聊博主,接实验技术指导1对1 有任…

单片机学习笔记---DS1302时钟

上一节我们讲了DS1302的工作原理,这一节我们开始代码演示。 新创建一个工程写上框架 我们需要LCD1602进行显示,所以我们要将LCD1602调试工具那一节的LCD1602的模块化代码给添加进来 然后我们开始创建一个DS1302.c和DS1302.h 根据原理图,为了…

【Web】Spring rce CVE-2022-22965漏洞复现学习笔记

目录 原理概览 漏洞简述 Tomcat AccessLogValve 和 access_log 例题: 原理概览 spring框架在传参的时候会与对应实体类自动参数绑定,通过“.”还可以访问对应实体类的引用类型变量。使用getClass方法,通过反射机制最终获取tomcat的日志配置成员属性…

FOC--有感--clion

配置CLion用于STM32开发【优雅の嵌入式开发】 - 知乎 TIM1_CH3N是TIM1_CH3的互补输出通道。TIM1是一个高级定时器,具有互补输出功能。TIM1_CHx是PWM的主通道,而TIM1_CHxN则是PWM的互补输出通道。 开漏输出和推挽输出: 输出电平能力: 推挽输…

HiveSQL——共同使用ip的用户检测问题【自关联问题】

注:参考文章: SQL 之共同使用ip用户检测问题【自关联问题】-HQL面试题48【拼多多面试题】_hive sql 自关联-CSDN博客文章浏览阅读810次。0 问题描述create table log( uid char(10), ip char(15), time timestamp);insert into log valuesinsert into l…

2.6日学习打卡----初学RabbitMQ(一)

2.6日学习打卡 初识RabbitMQ、 一. MQ 消息队列 MQ全称Message Queue(消息队列),是在消息的传输过程中保 存消息的容器。多用于系统之间的异步通信。 同步通信相当于两个人当面对话,你一言我一语。必须及时回复 异步通信相当于通…

猫头虎分享:2024龙年IT行业热门技术大全

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …

Python爬虫之文件存储#5

爬虫专栏:http://t.csdnimg.cn/WfCSx 文件存储形式多种多样,比如可以保存成 TXT 纯文本形式,也可以保存为 JSON 格式、CSV 格式等,本节就来了解一下文本文件的存储方式。 TXT 文本存储 将数据保存到 TXT 文本的操作非常简单&am…

Maui blazor ios 按设备类型设置是否启用safeArea

需求&#xff0c;新做了个app&#xff0c; 使用的是maui blazor技术&#xff0c;里面用了渐变背景&#xff0c;在默认启用SafeArea情况下&#xff0c;底部背景很突兀 由于现版本maui在SafeArea有点bug&#xff0c;官方教程的<ContentPage SafeAreafalse不生效&#xff0c;于…

【web前端开发】HTML及CSS简单页面布局练习

案例一 网页课程 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-wi…

二阶系统的迹-行列式平面方法(trace-determinant methods for 2nd order system)

让我们再次考虑二阶线性系统 d Y d t A Y \frac{d\mathbf{Y}}{dt}A\mathbf{Y} dtdY​AY 我们已经知道&#xff0c;分析这种二阶系统。最主要的是注意它的特征值情形。 &#xff08;此处没有重根的情形&#xff0c;所有是partial&#xff09; 而特征值&#xff0c;也就是系…

Java异常的处理 try-catch-finally

目录 什么是异常通过if-else处理异常用if-else堵漏洞的缺点 try-catch例第一种处理第二种处理第三种处理第四种处理 try-catch-finally例 System.exit(0);//终止当前的虚拟机执行 什么是异常 Exception&#xff1a;在程序的运行过程中&#xff0c;发生了不正常的现象&#xff0…

探索未来:集成存储器计算(IMC)与深度神经网络(DNN)的机遇与挑战

开篇部分&#xff1a;人工智能、深度神经网络与内存计算的交汇 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;已经成为科技领域的一股强大力量&#xff0c;而深度神经网络&#xff08;DNN&#xff09;则是AI的核心引擎之一。DNN是一种模仿人类神经系统运作…

【Java八股面试系列】并发编程-并发关键字,线程池

目录 并发关键字 Synchronized synchronized最主要的三种使用方式&#xff1a; 具体使用&#xff1a;双重校验锁单例模式 synchronized 底层实现原理&#xff1f; synchronized锁的优化 偏向锁 轻量级锁 重量级锁 Mark Word 与 Monitor 之间的关系 总结 偏向锁、轻量…

2024年【高压电工】报名考试及高压电工操作证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年高压电工报名考试为正在备考高压电工操作证的学员准备的理论考试专题&#xff0c;每个月更新的高压电工操作证考试祝您顺利通过高压电工考试。 1、【单选题】 高压电动机发生单相接地故障时,只要接地电流大于()…

苹果mac电脑如何优化系统?保持不卡顿呢

再强悍的性能和优秀的操作系统&#xff0c;但长时间使用后&#xff0c;有时也会出现卡顿的情况。为了让你的苹果电脑保持高效运行&#xff0c;我们将深入探讨导致电脑卡顿的原因&#xff0c;并提供苹果电脑如何优化系统的解决方案&#xff0c;帮助你优化系统。 过多的启动项 …

第十七篇【传奇开心果系列】Python的OpenCV库技术点案例示例:自适应阈值二值化处理图像提取文字

传奇开心果短博文系列 系列短博文目录Python的OpenCV库技术点案例示例系列短博文目录前言一、自适应阈值二值化处理图像提取文字轮廓的初步示例代码:二、扩展思路介绍三、调整自适应阈值二值化的参数示例代码四、对二值化图像进行形态学操作示例代码五、使用轮廓特征进行筛选示…