最近看到一个很有趣的小游戏:
询问朋友5个问题,找到他出生在一个月的哪一天。每个问题都是询问他的生日是否是5个数字集合中的一个。
这5个集合分别是:
set1:1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
set2:2 3 6 7 10 11 14 15 18 19 22 23 26 27 30 31
set3:4 5 6 7 12 13 14 15 20 21 22 23 28 29 30 31
set4:8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31
set5:16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
生日是出现这一天的每个集合的第一个数字之和,例如生日是19,那么它会出现在集合1、2和5中,三个集合的第一个数字分别是1、2和16,它们的和就是19。
用Java实现就是:
import javax.swing.JOptionPane; public class GuessBirthday{
public static void main(String[] args) {
String set1=
" 1 3 5 7\n"+
" 9 11 13 15\n"+
"17 19 21 23\n"+
"25 27 29 31"; String set2=
" 2 3 6 7\n"+
"10 11 14 15\n"+
"18 19 22 23\n"+
"26 27 30 31"; String set3=
" 4 5 6 7\n"+
"12 13 14 15\n"+
"20 21 22 23\n"+
"28 29 30 31"; String set4=
" 8 9 10 11\n"+
"12 13 14 15\n"+
"24 25 26 27\n"+
"28 29 30 31"; String set5=
"16 17 18 19\n"+
"20 21 22 23\n"+
"24 25 26 27\n"+
"28 29 30 31"; int day=0; //Prompt the user to answer questions
int answer=JOptionPane.showConfirmDialog(null,
"Is your birthday in these numbers?\n"+set1); if(answer==JOptionPane.YES_OPTION)
day+=1; answer=JOptionPane.showConfirmDialog(null,
"Is your birthday in these numbers?\n"+set2); if(answer==JOptionPane.YES_OPTION)
day+=2; answer=JOptionPane.showConfirmDialog(null,
"Is your birthday in these numbers?\n"+set3); if(answer==JOptionPane.YES_OPTION)
day+=4; answer=JOptionPane.showConfirmDialog(null,
"Is your birthday in these numbers\n"+set4); if(answer==JOptionPane.YES_OPTION)
day+=8; answer=JOptionPane.showConfirmDialog(null,
"Is your birthday in these numbers?\n"+set5); if(answer==JOptionPane.YES_OPTION)
day+=16; JOptionPane.showMessageDialog(null, "Your birthday is "+
day+"!");
}
}
运行测试:
测试日期为19
集合2:选择“是”
集合1:选择“是”
集合3:选择“否”
集合4:选择“否”
集合5:选择“是”
显示生日19,正确!
原理的话,涉及到一些二进制相关的知识。
从1到31的十进制数最多用5位的二进制数就可以表示:
十进制 | 二进制 |
1 | 00001 |
2 | 00010 |
3 | 00011 |
… | |
19 | 10011 |
… | |
31 | 11111 |
假设二进数表示为b5b4b3b2b1,
而这5个Set中的数分别是b1为1的集合,b2为1的集合,b3为1的集合,b4为1的集合,b5为1的集合,
如果某天的bk位为1,那么该数就出现在Setk中,
例如: 19的二进制数为10011,所以它就出现在Set1,Set2,Set5中;
30的二进制数为11111,所以它在Set1~Set5中都有出现。
总之就是5个集合确定5位二进制数中对应位置上的值是1还是0,出现在集合中为1,未出现为0,最后组成一个5位二进制数,换算成10进制数就得到生日日期。
根据这个方法同理可以猜测月份,甚至年份,大家可以自行探索!