Duplicate Birthdates - with String format checking

  Download Source Code



/************************************************************\
Stew Dent is a student at OHS (Our High School).
Stew is exploring a probability puzzle - that in a
group of 24 students, there is a probability over
50% that at least 2 of them share the same birthday.
To explore this puzzle, he asked students to type
their birthday into a computer program.  For this to
function, the birthdays must all be in the same format,
so matches can be detected.  This program inputs birthdates
and attempts to store them in the common format MMM DD.
\************************************************************/

import java.util.*;

public class Birthdates
{
  Vector birthDates = new Vector();
  int count = 0;
  
  public Birthdates()
  {
    while(true)                                   // loop forever
    {
      String bd = input("Type your birthdate as MMM DD");
      String fixed = fix(bd);
      if(fixed.equals(""))          // bad dates return "" error code
      {
        output(bd + " is not valid - it has been rejected."); 
      }
      else
      {
        count = count + 1;
        if(birthDates.contains(fixed))
        {
          output("Duplicate birthdate after " + count + " inputs");
          System.exit(0);
        }
        else
        {
          birthDates.add(fixed); 
          System.out.println(fixed);
        }
      }
    }  
  }
  
  String fix(String bd)  // attempts to convert date to MMM DD format
  {
    bd = bd.toUpperCase();
    int space = bd.indexOf(" ");
    if(space < 0)
    { return ""; }     // blank space is missing
    if(space < 3)      // check for "3 Apr" or "03 Apr"
    {
      bd = bd.substring(space+1) + " " + bd.substring(0,space); 
    }
    String month = bd.substring(0,3);
    String date = bd.substring(4);
    int d = Integer.parseInt(date);               
    if(d <= 0 || d > 31)
    { return ""; }                   // date is not valid
    String mlist = "JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC";
    if(mlist.indexOf(month) < 0)
    { return ""; }                   // name of month not valid
    bd = month + " " + d;
    return bd; 
  }
  
  public static void main(String[] args)
  {  new Birthdates();  }
  
  public String input(String prompt)
  { return javax.swing.JOptionPane.showInputDialog(null,prompt); }
  
  public void output(String message)
  {  javax.swing.JOptionPane.showMessageDialog(null,message);  }
}

.toUpperCase

Java is case-sensitive.  That means it thinks small and CAPITAL letters are not the same.  When comparing Strings,
most people expect CAPITAL and small letters to treated as equal, e.g. "JAN" and "Jan" and "jan" are all the same. 
One way to do this is by using .equalIgnoreCase for comparisons.  Another way is to FORCE input to
the CAPITAL letter format, by using .toUpperCase .  That changes all letters to capital letters,
but leaves digits and punctuation unchanged. This program uses .toUpperCase on the month abbreviation input,
and then searches for the 3 letter abbreviation in a list of abbreviations.

.indexOf

One way to check for a correct abbreviation is to store 12 abbreviations in an Array, and then search through the array. 
This program uses a different approach that does not require a loop.  The command mlist.indexOf(month) tells Java
that it should look inside the mlist String and search for month, then return the position of where month was found. 
If month is not found in the mlist String, the result is -1 . So the following command decides wether month is valid:

    if(mlist.indexOf(month) < 0)    // if it's negative, them month is not valid

This only requires one command, rather than using a loop.  It is also simpler to write.

.substring

Before checking whether month is valid, the program uses bd.substring(0,3) to extract the first 3 letters of the input,
which is supposed to be in the format MMM DD .  It also uses bd.substring(4) to get the day number(s). 
This means go to position 4 in the String and copy everything that follows, all the way to the end of the String.  

Substring is a bit confusing until you understand that you are counting the positions BETWEEN the letters -
you are not counting the letters.  Like this:

    String S :  E x c e l l e n t
    Positions: 0 1 2 3 4 5 6 7 8 9

The String "cell" goes from position 2 to position 6, so

    S.substring(2,6) ==> "cell"

    S.substring(5)   ==> "lent"

    S.substring(9,10) ==> ""     //  an empty String

    S.substring(0,1) ==> "E"     //  the first letter

    S.substring(S.length() - 1 ) ==> "t"   // the last letter

That formula for the last letter always works, for any contents of S.

Programming Practice