Task: Birthday problem


C++: #include <iostream>
#include <random>
#include <vector>

double equalBirthdays(int nSharers, int groupSize, int nRepetitions) {
    std::default_random_engine generator;
    std::uniform_int_distribution<int> distribution(0, 364);
    std::vector<int> group(365);

    int eq = 0;
    for (int i = 0; i < nRepetitions; i++) {
        std::fill(group.begin(), group.end(), 0);
        for (int j = 0; j < groupSize; j++) {
            int day = distribution(generator);
            group[day]++;
        }
        if (std::any_of(group.cbegin(), group.cend(), [nSharers](int c) { return c >= nSharers; })) {
            eq++;
        }
    }

    return (100.0 * eq) / nRepetitions;
}

int main() {
    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.0f);
        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, 50000);
            if (eq > 50.0) {
                groupEst = gs;
                printf("%d independant people in a group of %d share a common birthday. (%5.1f)\n", sharers, gs, eq);
                break;
            }
        }
    }

    return 0;
}










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;