Task: Birthday problem





Java: import static java.util.Arrays.stream;
import java.util.Random;

public class Test {

    static double equalBirthdays(int nSharers, int groupSize, int nRepetitions) {
        Random rand = new Random(1);

        int eq = 0;

        for (int i = 0; i < nRepetitions; i++) {
            int[] group = new int[365];
            for (int j = 0; j < groupSize; j++)
                group[rand.nextInt(group.length)]++;
            eq += stream(group).anyMatch(c -> c >= nSharers) ? 1 : 0;
        }

        return (eq * 100.0) / nRepetitions;
    }

    public static void main(String[] a) {

        int groupEst = 2;

        for (int sharers = 2; sharers < 6; sharers++) {
            
            int groupSize = groupEst + 1;
            while (equalBirthdays(sharers, groupSize, 100) < 50.0)
                groupSize++;

            
            int inf = (int) (groupSize - (groupSize - groupEst) / 4.0);
            for (int gs = inf; gs < groupSize + 999; gs++) {
                double eq = equalBirthdays(sharers, groupSize, 250);
                if (eq > 50.0) {
                    groupSize = gs;
                    break;
                }
            }

            
            for (int gs = groupSize - 1; gs < groupSize + 999; gs++) {
                double eq = equalBirthdays(sharers, gs, 50_000);
                if (eq > 50.0) {
                    groupEst = gs;
                    System.out.printf("%d independent people in a group of "
                            + "%s share a common birthday. (%5.1f)%n",
                            sharers, gs, eq);
                    break;
                }
            }
        }
    }
}







Ada: with Ada.Command_Line, Ada.Text_IO, Ada.Numerics.Discrete_random;

procedure Birthday_Test is
   
   Samples: constant Positive := Integer'Value(Ada.Command_Line.Argument(1));
   
   
   
   subtype Day is integer range 0 .. 365; 
   subtype Extended_Day is Integer range 0 .. 365*4; 
   package ANDR is new Ada.Numerics.Discrete_Random(Extended_Day);
   Random_Generator: ANDR.Generator;

   function Random_Day return Day is (ANDR.Random(Random_Generator) / 4);
   
   
   type Checkpoint is record
      Multiplicity:  Positive;
      Person_Count:   Positive;
   end record;
   Checkpoints: constant array(Positive range <>) of Checkpoint 
     := ( (2, 22),  (2, 23),  (3, 86),  (3, 87), (3, 88),  
	  (4, 186), (4, 187), (5, 312), (5, 313), (5, 314) );
   type Result_Type is array(Checkpoints'Range) of Natural;
   Result: Result_Type := (others => 0);
   
   
   
   procedure Experiment(Result: in out Result_Type) is
   
      A_Year: array(Day) of Natural := (others => 0);
      A_Day: Day;
      Multiplicity: Natural := 0;
      People: Positive := 1;
   begin
      for I in Checkpoints'Range loop
	 while People <= Checkpoints(I).Person_Count loop
	    A_Day := Random_Day;
	    A_Year(A_Day) := A_Year(A_Day)+1;
	    if A_Year(A_Day) > Multiplicity then
	       Multiplicity := Multiplicity + 1;
	    end if;
	    People := People + 1;
	 end loop;
	 if Multiplicity >= Checkpoints(I).Multiplicity then
	    Result(I) := Result(I) + 1;
            
	 end if;
      end loop;
   end Experiment;
   
   package TIO renames Ada.Text_IO;
   package FIO is new TIO.Float_IO(Float);

begin
    
    ANDR.Reset(Random_Generator);

    
    for I in 1 .. Samples loop
       Experiment(Result);
    end loop;

    
    TIO.Put_Line("Birthday-Test with" & Integer'Image(Samples) & " samples:");
    for I in Result'Range loop
       FIO.Put(Float(Result(I))/Float(Samples), Fore => 3, Aft => 6, Exp => 0);
       TIO.Put_Line
	 ("% of groups with" & Integer'Image(Checkpoints(I).Person_Count) & 
	  " have"            & Integer'Image(Checkpoints(I).Multiplicity) & 
	  " persons sharing a common birthday.");
    end loop;
end Birthday_Test;