【第22期】观点:IT 行业加班,到底有没有价值?

猜生日

原创 2016年08月30日 23:44:55

通过询问对方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

 


版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

生日猜猜猜 HDU 4551

 生日猜猜猜 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tota...

编程艺术家经典试题解读:猜生日问题

这是一道很多人知道的经典题目,其中的逻辑推理堪称短小精悍试题的典范。 题目: 张老师的生日为M月D日,他将M值告诉给了小明,将D值告诉给了小强。然后给出如下这些日期: 3月4日,3月5日,3月8日,6月4日,6月7日,9月1日,9月5日,12月1日,12月2日,12月8日。</st

一段有趣的代码,猜生日

转自:http://www.oschina.net/code/snippet_10896_2907[代码] GuessBirthDate.cpp/** * 一段有趣的代码,猜生日。 * 运...

一个外语达人的经验(转自天涯)

[size=medium]自从我在网上连载自己学习各类小语种(包括德语、韩语、西班牙语、越南语)的笔记以来,很多朋友加我的QQ,然后问我学习的各个方面的经验。有一部分朋友,还是问最重要的英语如何学。英语是我学习的第一门外语,是十几年前学的,我已经忘记了入门时是什么一种感觉了,便觉得很难回答这些朋友的问题。      后来我想了一下。以我学过这么多门语言得到的一个感觉,那就是语言的学习是一理通、百理明的,有其相通之处。或者我把自己以前学英语的情况谈一下,不但对人数更远为庞大的想学英语的朋友有助,对学习其他小语种的朋友一定也是有益的。事实上,此前我已经写过关于德语、韩语、西班牙语的入门经验谈,

杭电4551生日猜猜猜

生日猜猜猜 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Su...
  • z8110
  • z8110
  • 2015-09-23 22:35
  • 138
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)