Nästan lika enkelt som att köra en slumpmässig simulering är att skriva ett program som går igenom totala sökträdet av alla födelsedagskombinationer, eliminerar de förgreningar där tre eller fler fyller år samma dag, dividerar alla funna utfall med totala möjliga antalet, och till sist räknar ut den komplementära sannolikheten.
Kod:
// Beräkna exakta sannolikheten för att en klass
// har 3 eller fler elever som fyller år någon dag
import java.util.Random;
public class treebirthday
{
static final int DEFAULT_PEOPLE = 21;
public static void main(String a[])
{
Random rnd = new Random(System.currentTimeMillis());
int elever = DEFAULT_PEOPLE;
if (a.length>0)
{
try{
elever = Integer.parseInt(a[0]);
}catch(NumberFormatException nfe){}
}
double compProb = func(0,0,elever);
System.out.println("Sannolikhet: "+((1.0-compProb)*100.0)+"%");
}
static double func(int singlar, int dubbletter, int kvar)
{
if (kvar == 0)
return 1.0;
else
return (singlar*func(singlar-1, dubbletter+1, kvar-1) +
(365-singlar-dubbletter)*func(singlar+1, dubbletter, kvar-1))/365.0;
}
}
Jag testade programmet mot fallen där man har en extremt liten klass på bara 3, 4, resp. 5 elever, som är relativt lätta att räkna ut analytiskt:
3: ((3 över 3)*365) / (365^3) = 0.000751%
4: ((4 över 4)*365 + (4 över 3)*365*(1 över 1)*364) / (365^4) = 0.00300%
5: ((5 över 5)*365 + (5 över 4)*365*(1 över 1)*364 + (5 över 3)*365*(2 över 2)*364^2)/(365^5) = 0.00748%
Mitt program:
3: 0.000751%
4: 0.00300%
5: 0.00748%
Körning med 21 elever i klassen gav
0.959%.
Angående resonemanget om skottår: Det vanliga är att alla elever i en skolklass är födda samma år. Det året är alltså antingen ett skottår för alla elever eller för ingen. Här har jag räknat på en klass som är född t.ex. år 1997 (365 dagar).