猜生日

通过询问对方5个问题,每个问题均是提问其生日在不在给出的集合中,如果是则输入1,不是输入0,那么在5个回合后,程序将给出这个人生日为几号。

参考《Foundations of Programming in Java》,下面是代码,代码有注释,就不多分析了,如果对代码有疑问的请在评论区留言,算法原理解析在最后,如果对这个算法还有更好的理解也请在评论区留言。

import java.util.Scanner;

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;

    // Create a Scanner
    Scanner input = new Scanner(System.in);

    // Prompt the user to answer questions
    System.out.print("Is your birthday in Set1?\n");
    System.out.print(set1);
    System.out.print("\nEnter 0 for No and 1 for Yes: ");
    int answer = input.nextInt();

    if (answer == 1)
      day += 1;

    // Prompt the user to answer questions
    System.out.print("\nIs your birthday in Set2?\n");
    System.out.print(set2);
    System.out.print("\nEnter 0 for No and 1 for Yes: ");
    answer = input.nextInt();

    if (answer == 1)
      day += 2;

    // Prompt the user to answer questions
    System.out.print("Is your birthday in Set3?\n");
    System.out.print(set3);
    System.out.print("\nEnter 0 for No and 1 for Yes: ");
    answer = input.nextInt();

    if (answer == 1)
      day += 4;

    // Prompt the user to answer questions
    System.out.print("\nIs your birthday in Set4?\n");
    System.out.print(set4);
    System.out.print("\nEnter 0 for No and 1 for Yes: ");
    answer = input.nextInt();

    if (answer == 1)
      day += 8;

    // Prompt the user to answer questions
    System.out.print("\nIs your birthday in Set5?\n");
    System.out.print(set5);
    System.out.print("\nEnter 0 for No and 1 for Yes: ");
    answer = input.nextInt();

    if (answer == 1)
      day += 16;

    System.out.println("\nYour birthday is " + day + "!");
  }
}
       

     解析:假设小红同学的生日为某月19号,(下图是输入和结果解析)因为第一步中有19号所以需要输入1,第二步中也有19号同样输入1,第三步和第四步没有19号,输入0,第五步有19号需要输入1,所以输入1的是1,2,5步,用左上角数字加起来刚好是小红生日的号数19号。


下图为程序运行过程的输入和输出:



算法的原理:

生日只能是[1,28](平年二月),[1,29](瑞年二月),[1,30](小月),[1,31](大月)号中的某一天,不会超过31天,所以用[1,31]天完全能够表示小红的生日的号数,31的二进制位11111=00001+00010+00100+01000+10000,也就是:

  00001--------------1

  00010--------------2

  00100--------------4

  01000--------------8

   +  10000--------------16

  ——————————————————————

       11111--------------31


然而我们知道,二进制只能由0或者1组成,所以一个数字[1,31]的各个位数只能是0或者1,所以由上面的数组合可以组合相加,可以得到任意一个数字。这样的话,我们任意取一个数字,其二进制表示为:ABCDE(注:对应A表示二进制由左往右第一位,B第二位,C第三位,D第四位,E第五位。例10110,则A=1,B=0,C=1,D=1,E=0).

则ABCDE可以由如下算式得到:

    0000E

    000D0

    00C00

    0B000

     +  A0000

  ———————————————————

    ABCDE

     显然这个ABCDE是任意的,并且A,B,C,D,E要么为0要么为1。这样我们可以将对应的生日放在5个集合的某个集合中,

规则是:

 如果这个数的E=1(不限定其他位数字),那么就应该放在集合set1中。

 如果这个数的D=1(不限定其他位数字),那么就应该放在集合set2中。

 如果这个数的C=1(不限定其他位数字),那么就应该放在集合set3中。

 如果这个数的B=1(不限定其他位数字),那么就应该放在集合set4中。

 如果这个数的A=1(不限定其他位数字),那么就应该放在集合set5中。

 注:可能一个生日会放在多个集合中。

 当将这些生日放置在不同的集合中后,通过指定某个生日存在于5个集合中的哪些集合。我们便可以轻易的得到这个生日号数。

 例:小红的生日19号(本篇算法只讨论号数),其二进制为10011,那么我们会将它放置到set1,set2,set5中。

 这样当你指定说某个数在集合set1,set2,set5,那么我们便知道,你说的某数必然是E=1,D=1,C=0,B=0,A=1

 很容易的我们便可以猜出你说的某数为1+2+0+0+16=19

 


  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值