zh3036 / codingQuestions

um, ask in pull request
7 stars 0 forks source link

Birthday problems #6

Closed Emilysea closed 7 years ago

Emilysea commented 7 years ago

This birthday generator should print out the trials of finding two birthdays within k days range, the difference they had(how far apart they are), and their actual values. I did the first part: the number of trials. But then I stuck at calculating their difference and returning their values, I thought it was the value of "i", but then I figured it was not. It should be the difference of the "new birthday" and "old birthday", as well as the value of "new birthday" and "old birthday". How can I get the new&old values at the same time, and how can I return them out of the while loop in the last println?

/** This birthday generator generates the counts of trails of finding
 *  two birthday within the given range. First we entered the range k, then 
 *  within a while loop, we stored the first returned number plus or minus k 
 *  equals true. By repeating this step, we are then going to store every new
 *  generated number's relative range number true. Next time when we see the
 *  new number appeared in some previous number's range, we are going to
 *  stop the program and returned the count. 
 *   
 */
import java.util.Scanner;
public class Birthday2 {

   public static void main(String[] args) {
       int count;       
       boolean[] used = new boolean[365];  
       count = 0;
       System.out.println("Enter the interval number of days between two birthdays");
       Scanner sc = new Scanner(System.in);
       int k = sc.nextInt(); //getting the input k

    while (true) {
       int birthday;  
       birthday = (int)(Math.random()*365);
       count++;
       int i;

       System.out.printf("Person %d has birthday number %d", count, birthday);
       System.out.println();

         if (used[birthday] == true)// if the new generated used[] returns true
         {
              break; //marking the stopping point, getting the result

         }

         for(i=0; i<=k; i++){
           used[(birthday+i+365)%365] = used[(birthday-i+365)%365] = true; 
           //making sure it is not out of boundary
         }  

    }
    System.out.println("A  birthday with "+ k + " interval was found after " 
                        + count + " tries");              
    }
}
zh3036 commented 7 years ago

话说 说中文也没关系的

notcome commented 7 years ago

实际上,能说中文就不要说英文了

notcome commented 7 years ago

一、你说的是「trials」还是「trails」?我英语不太好,不知道「trails」这里的意思。

二、你最好把原题发给我们看一下。

Emilysea commented 7 years ago

我拼错了,是trial😂 题目就是根据之前的一个例子:多少次能找到两个一样的生日(实际就是多少次能找到两个相同的任意生成的数字)--引申到现在这个原题:多少次能找到两个相差在k天里的生日,并求出两次生日的index位置和具体差值。 In Section 3.8.3 in the textbook, you read about the birthday problem. This little problem has quite a large Wikipedia page. Scroll down to the section on Near Matches and read about the related problem of finding people with birthdays within k days of each other.

Write a BirthdayProblem2 class that asks the user to input k and repeatedly picks birthdays until it find two that are within k days of each other. It should then print out the birthdays and how far apart they are. Here's an example run of the program:

k = 4

Person 1 has birthday number 191 Person 2 has birthday number 172 Person 3 has birthday number 18 Person 4 has birthday number 130 Person 5 has birthday number 48 Person 6 has birthday number 87 Person 7 has birthday number 170

Birthdays within -2 days found after 7 tries: 170, 172 Make sure to include comments at the top of the class that:

Explain what the class does. How the new part of the code works. Provide a good amount of detail. Upload your BirthdayProblem2.java file.

Emilysea commented 7 years ago

这是原题里面提到的3.8.3textbook内容

/**
 * Simulate choosing people at random and checking the day of the year they 
 * were born on.  If the birthday is the same as one that was seen previously, 
 * stop, and output the number of people who were checked.
 */
public class BirthdayProblem {

   public static void main(String[] args) {

       boolean[] used;  // For recording the possible birthdays
                        //   that have been seen so far.  A value
                        //   of true in used[i] means that a person
                        //   whose birthday is the i-th day of the
                        //   year has been found.

       int count;       // The number of people who have been checked.

       used = new boolean[365];  // Initially, all entries are false.

       count = 0;

       while (true) {
             // Select a birthday at random, from 0 to 364.
             // If the birthday has already been used, quit.
             // Otherwise, record the birthday as used.

          int birthday;  // The selected birthday.
          birthday = (int)(Math.random()*365);
          count++;

          System.out.printf("Person %d has birthday number %d", count, birthday);
          System.out.println();

          if ( used[birthday] ) {  
                // This day was found before; it's a duplicate.  We are done.
             break;
          }

          used[birthday] = true;

       } // end while

       System.out.println();
       System.out.println("A duplicate birthday was found after " 
                                             + count + " tries.");
   }

} // end class BirthdayProblem
notcome commented 7 years ago

我大概知道你的问题了。你试图在生成一个生日之后,把它周围 k 天全部标为已使用。这会有一个问题:当你生成了一个生日,发现对应区间已经被使用之后,你不知道原来那个占位的生日究竟是这 2k+1 区间里的哪一个。

解决方法很简单,你不要把周围 k 天全部标为已使用,你直接在生成一个新生日之后,检查一下周围 k 天有没有已使用的即可。

顺便说一下,你可以谷歌一下 GitHub 里代码是如何染色的,类似下面这样。会方便我们阅读很多。

/**
 * Simulate choosing people at random and checking the day of the year they 
 * were born on.  If the birthday is the same as one that was seen previously, 
 * stop, and output the number of people who were checked.
 */
public class BirthdayProblem {

   public static void main(String[] args) {

       boolean[] used;  // For recording the possible birthdays
                        //   that have been seen so far.  A value
                        //   of true in used[i] means that a person
                        //   whose birthday is the i-th day of the
                        //   year has been found.

       int count;       // The number of people who have been checked.

       used = new boolean[365];  // Initially, all entries are false.

       count = 0;

       while (true) {
             // Select a birthday at random, from 0 to 364.
             // If the birthday has already been used, quit.
             // Otherwise, record the birthday as used.

          int birthday;  // The selected birthday.
          birthday = (int)(Math.random()*365);
          count++;

          System.out.printf("Person %d has birthday number %d", count, birthday);
          System.out.println();

          if ( used[birthday] ) {  
                // This day was found before; it's a duplicate.  We are done.
             break;
          }

          used[birthday] = true;

       } // end while

       System.out.println();
       System.out.println("A duplicate birthday was found after " 
                                             + count + " tries.");
   }

} // end class BirthdayProblem
Emilysea commented 7 years ago

嗯那我是不是根据原题,把原题里的 ``` if (used[birthday]) ```

改为 ``` for(int i = 0; i<k; i++) if (used[birthday+i]) { break; } ``` 再输出i。我有三个小疑问: 1.这是“birthday+i”;还有一种情况是“birthday-i”,怎么把它并列进去呢? 2.怎么解决[birthday+i]或[birthday-1]的值超出365或小于零的界限呢? 3.如果要输出i,i又在 while loop里面,怎么在loop外面输出i的值呢?

notcome commented 7 years ago
  1. 「`」是半角字符,不要开中文输入法的时候输入。
  2. for 循环从 -k 开始,到 k 结束(可能是 -k + 1,取决于开区间还是闭区间)。
  3. 就普通的 (x + 365) % 365。
  4. 在 while 循环外建立变量,把值存储过去。
Emilysea commented 7 years ago

嗯嗯前两个明白了,最后那个我这么理解不知道对不对:在外面建一个int delta; 然后再break后面第二行输入dealta = i;最后在loop外面输出i?

notcome commented 7 years ago

怎么方便怎么来就好,细节自己把握。

notcome commented 7 years ago

如果你写好的话,你就自己 close 这个 issue 吧