贴吧里有这样一个题目

下面楼主的补发:

这种魔术看起来是有魔术师有“读心术”?
实际上不然。
奥秘在于助手的出牌顺序,这背后有一套算法,展示后魔术师经过计算已经知道了最后一张牌的值(每张牌有一个编号),对应的可以找到隐藏的牌。

我的思路是这样的(这是编程设计算法的思路,查阅过一些资料总结的):
首先只有4种花色,抽5张牌,根据鸽巢原理(鸽洞原理),必定有重花色的情况出现。
然后一种花色只有13张牌,围成一个圈,最远的距离是6(双向可达)。
So,我们作如下规约:

  • 藏匿的卡牌花色与第一张相同
  • 藏匿卡牌的字面值与第一张相距在1~6之间(毕竟不能重复,0是不存在的)
  • 1~6 的距离由第2张~第4张展示的牌的大小顺序呈现(按照编号而不是字面值)
    • (小->中->大)= 1
    • (小->大->中)= 2
    • (中->小->大)= 3
    • (中->大->小)= 4
    • (大->小->中)= 5
    • (大->中->小)= 6
  • 编号顺序花色从Club(梅花)->Diamond(方片)->Heart(红心)->Spade(黑桃)
  • 花色内部编号从小到大A->2->3->…->K(与斗地主不同啊)
  • 依据先补满同字面值的花色再往后延伸字面值到K的顺序来编号

规约就是这样,然后就可以搞事情了嘿嘿嘿~~~

下面放出来Python描述的代码实现:

# 你可以读心术——随机抽取五张牌,其中一张隐藏起来,按照特定的顺序给四张牌,你就能知道第五张牌是什么!# deck是一个字符串列表,每个字符串是一张卡。名单上卡片的顺序很重要!!
deck = ['A_C', 'A_D', 'A_H', 'A_S', '2_C', '2_D', '2_H', '2_S','3_C', '3_D', '3_H', '3_S', '4_C', '4_D', '4_H', '4_S','5_C', '5_D', '5_H', '5_S', '6_C', '6_D', '6_H', '6_S','7_C', '7_D', '7_H', '7_S', '8_C', '8_D', '8_H', '8_S','9_C', '9_D', '9_H', '9_S', '10_C', '10_D', '10_H', '10_S','J_C', 'J_D', 'J_H', 'J_S', 'Q_C', 'Q_D', 'Q_H', 'Q_S','K_C', 'K_D', 'K_H', 'K_S']# 给5张牌,助手会藏一张合适的牌,TA仔细挑选了剩下的四张卡片,然后把它们读出来!
def AssistantOrderCards():print('Cards are character strings as shown below.')print('Ordering is:', deck)# 初始化cards, cind, cardsuits, cnumbers = [], [], [], []numsuits = [0, 0, 0, 0]# 将卡片作为用户/观众的输入# 填写各种数据结构for i in range(5):print('Please give card', i + 1, end=' ')card = input('in above format: ')cards.append(card)n = deck.index(card)cind.append(n)cardsuits.append(n % 4)cnumbers.append(n // 4)numsuits[n % 4] += 1if numsuits[n % 4] > 1:pairsuit = n % 4# 从5个相同的套装中找出两张牌。保证存在cardH = []for i in range(5):if cardsuits[i] == pairsuit:cardH.append(i)# 找出需要隐藏的卡和要编码的号码hidden, other, encode = outputFirstCard(cnumbers, cardH, cards)remindices = []for i in range(5):if i != hidden and i != other:remindices.append(cind[i])# 按升序排列这三张牌sortList(remindices)# 给定需要编码的号码,对卡片进行适当的排序outputNext3Cards(encode, remindices)return# 这个程序可以根据距离隐藏哪张卡。两张牌之间有相同的套装。它返回隐藏卡、第一张暴露卡和距离。
def outputFirstCard(ns, oneTwo, cards):encode = (ns[oneTwo[0]] - ns[oneTwo[1]]) % 13if 0 < encode <= 6:hidden = oneTwo[0]other = oneTwo[1]else:hidden = oneTwo[1]other = oneTwo[0]encode = (ns[oneTwo[1]] - ns[oneTwo[0]]) % 13print('First card is: ', cards[other])return hidden, other, encode# 这个程序根据“编码”命令三张卡。需要进行编码。
def outputNext3Cards(code, ind):if code == 1:s, t, f = ind[0], ind[1], ind[2]elif code == 2:s, t, f = ind[0], ind[2], ind[1]elif code == 3:s, t, f = ind[1], ind[0], ind[2]elif code == 4:s, t, f = ind[1], ind[2], ind[0]elif code == 5:s, t, f = ind[2], ind[0], ind[1]else:s, t, f = ind[2], ind[1], ind[0]print('Second card is:', deck[s])print('Third card is:', deck[t])print('Fourth card is:', deck[f])# 升序排列tList的元素
def sortList(tList):for ind in range(0, len(tList)-1):iSm = indfor i in range(ind, len(tList)):if tList[iSm] > tList[i]:iSm = itList[ind], tList[iSm] = tList[iSm], tList[ind]# 这个过程需要正确地编码四张卡并确定隐藏的卡
def MagicianGuessesCard():print('Cards are character strings are shown as below')print('Ordering is:', deck)cards, cind = [], []for i in range(4):print('Please give card', i+1, end=' ')card = input('in above format:')cards.append(card)n = deck.index(card)cind.append(n)if i == 0:suit = n % 4number = n // 4# 使用最后3张卡的顺序来确定与第一张卡的距离if cind[1] < cind[2] and cind[1] < cind[3]:if cind[2] < cind[3]:encode = 1else:encode = 2elif (cind[3] < cind[1] < cind[2]) or (cind[2] < cind[1] < cind[3]):if cind[2] < cind[3]:encode = 3else:encode = 4elif cind[1] > cind[2] and cind[1] > cind[3]:if cind[2] < cind[3]:encode = 5else:encode = 6# 知道号码和套装给出卡片索引然后字符串hiddenNumber = (number + encode) % 13index = hiddenNumber * 4 + suitprint('Hidden card is:', deck[index])# 类似于AssistantOrderCards(), 接收大量的卡,然后“随机”生成五张卡。
def ComputerAssistant():print('Cards are character strings as shown below.')print('Ordering is:', deck)cards, cind, cardsuits, cnumbers = [], [], [], []numsuits = [0, 0, 0, 0]number = 0while number < 99999:number = int(input('Please give random number' +' of at least 6 digits:'))for i in range(5):number = number * (i + 1) // (i + 2)n = number % 52cards.append(deck[n])cind.append(n)cardsuits.append(n % 4)cnumbers.append(n // 4)numsuits[n % 4] += 1if numsuits[n % 4] > 1:pairsuit = n % 4cardH = []for i in range(5):if cardsuits[i] == pairsuit:cardH.append(i)hidden, other, encode = outputFirstCard(cnumbers, cardH, cards)remindices = []for i in range(5):if i != hidden and i != other:remindices.append(cind[i])sortList(remindices)outputNext3Cards(encode, remindices)guess = input('What is the hidden card?')if guess == cards[hidden]:print('You are a Mind Reader Extraordinaire!')else:print('Sorry, not impressed!')returnAssistantOrderCards()
MagicianGuessesCard()
ComputerAssistant()

有三种模式:
AssistantOrderCards()是助手的算法,——助手抽4张牌,可以经过此算法知道何种顺序展示哪四张牌(当然了,展示的顺序很多种,这是助手跟魔术师约定的“秘钥”,我们这里只按我们的思路来)。
MagicianGuessesCard()是魔术师的算法——魔术师按照助手展示的顺序“读出”牌的值以及展示顺序背后的秘密,算出最后隐藏而他“不知道”的牌。
ComputerAssistant()是没有助手的魔术师“自行训练”所用,随机抽多张卡(输入大于100000停止),然后猜,看猜得对不对用来检验技术达不达标。

OK,终于解决,下面升华一下主题,咳咳~~
这个“读心术”涉及到了一个 信息编码 的问题:
这个玩法里有 3! = 6 种排列方式,而一般对于 n! 来说,我们可以通过一个具体排列方式对传递的消息进行简单编码,普通的监听者知道有秘密但是他并不能轻易的破解(除非他知道秘钥,对吧…),而传递信息的双方则可以根据加密解密来传递信息,蛮有趣的呢~~

【Python】Magician“专属”神秘的“读心术”相关推荐

  1. python爆破端口_挑战全网多线程批量扫描爆破弱办事端口工具,Python制造专属!...

    挑战全网多线程批量扫描&爆破弱办事端口工具,Python制造专属!-1.jpg (29.47 KB, 下载次数: 0) 2018-8-16 17:05 上传 前言 你学习Python的目的是什 ...

  2. python开发专属表情包_Python开发个人专属表情包网站

    "表情包"是一种利用图片来表示感情的一种方式.表情包是在社交软件活跃之后,形成的一种流行文化,表情包流行于互联网上面,基本人人都会发表情. 曾经你是否也有过找不到表情包去应对别人的 ...

  3. 【趣味征文大赛】Python端午节专属玫瑰贺卡制作(玫瑰贺卡)

    一分钟学会利用Python的turtle库进行端午玫瑰贺卡制作 端午节到了,突发奇想,能不能利用Python的turtle制作一个贺卡,它的效果大概是这样子的: 1.应用场景及效果 (2022年全国端 ...

  4. Python 实现专属字典生成器

    编写一个密码生成工具,这里我们使用弱密码与个性化数组组合形成一个定制字典,例如收集用户的姓名,昵称,QQ号手机号等资源,然后通过Python对搜集到的数据与弱密码进行结合,从而定制出属于某个人的专属密 ...

  5. python开发专属表情包_Python开发个人专属的表情包网站

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. "表情包"是一种利用图片来表示感情的一种方式.表情包是 ...

  6. Python编程专属骚技巧9

    九.字典推导 Python不光列表用推导式,字典/集合也有 #列表 l=[[0 for i in range(4)] for i in range(4)]#生成二维列表 print(l) # [[0, ...

  7. Python编程专属骚技巧6

    六. 四种翻转字符串/列表的方式 # 翻转列表本身testList = [1, 3, 5] testList.reverse() print(testList) #-> [5, 3, 1]# 在 ...

  8. Python编程专属骚技巧2

    二.链状比较操作符 Python不用很多条件一个一个写,比较操作符可以聚合. n = 10 result = 1 < n < 20 print(result)# Trueresult = ...

  9. Python编程专属骚技巧1

    一.原地交换 Python 提供了一个直观的在一行代码中赋值与交换(变量值)的方法 x, y = 10, 20 print(x, y)x, y = y, x print(x, y)#1 (10, 20 ...

最新文章

  1. 转:ECharts图表组件之简单关系图:如何轻松实现另类站点地图且扩展节点属性实现点击节点页面跳转...
  2. ListView中让TextView中的文字进行单独滚动
  3. Pytorch Anaconda 安装CPU版本
  4. 【图像处理】libtiff读写三维TIFF图像(附详细代码)
  5. php 调用日历控制,基于ThinkPHP实现的日历功能实例详解
  6. 格力电器上半年净利94.57亿元,同比增长48.64%
  7. Android图片缩放方法
  8. 【笔记】Java 信任所有SSL证书(解决PKIX path building failed问题)
  9. Power Designer的4种模型文件
  10. 微信科室预约挂号小程序
  11. 全新按摩控制板助力按摩产品发展
  12. 【随笔】那些免费友好的遥感影像数据下载网站
  13. SkyLine——3DGIS三维地理信息系统软件产品介绍
  14. python数字转字符串_字符串转换与格式化
  15. nvme分区选mbr还是guid_怎么分辨硬盘是GUID格式还是MBR格式以及怎样更改
  16. GitChat · 架构 | 如何从零开始搭建高性能直播平台?
  17. Ubuntu使用bind9配置DNS服务器
  18. 【有利可图网】PS实战教程35:用PS快速抠透明的水花
  19. 【毕业设计】远程智能浇花灌溉系统 - stm32 单片机 嵌入式 物联网
  20. 安卓手机端微信网页浏览记录清理debugx5.qq.com

热门文章

  1. python操作excel常用的方法
  2. java代码生成器 快速开发平台 二次开发 外包项目利器 springmvc SSM后台框架源码...
  3. for-each循环
  4. Servlet添加商品
  5. Java--File文件操作
  6. ECMall2.x模板制作入门系列之2(模板标签/语法)
  7. tool vmmap 配置符号文件 symbolic file
  8. [程序员必备工具]分享一款不错的个人代码个人知识管理软件wiz
  9. ATL 线程池的使用
  10. 助人快乐:笔记本连网