Birthday problem: Difference between revisions

Add Scala implementation
(Added Wren)
(Add Scala implementation)
 
(8 intermediate revisions by 7 users not shown)
Line 1:
{{Wikipedia pre 15 June 2009|pagename=Birthday Problem|lang=en|oldid=296054030|timedate=21:44, 12 June 2009}}
{{draft task}}
[[Category:Probability and statistics]]
[[Category:Discrete math]]
{{Wikipedia pre 15 June 2009|pagename=Birthday Problem|lang=en|oldid=296054030|timedate=21:44, 12 June 2009}}
{{draft task}}
 
 
Line 9:
 
;Task
Using simulation, estimate the number of independent people required in a groupsgroup before we can expect a ''better than even chance'' that at least 2 independent people in a group share a common birthday. Furthermore: Simulate and thus estimate when we can expect a ''better than even chance'' that at least 3, 4 & 5 independent people of the group share a common birthday. For simplicity assume that all of the people are alive...
 
 
Line 21:
* Wolfram entry:   {{Wolfram|Birthday|Problem}}
<br><br>
=={{header|11l}}==
{{trans|D}}
 
<syntaxhighlight lang="11l">F equal_birthdays(sharers, groupsize, rep)
V eq = 0
L 0 .< rep
V group = [0] * 365
L 0 .< groupsize
group[random:(group.len)]++
I any(group.map(c -> c >= @sharers))
eq++
R (eq * 100.) / rep
 
V group_est = 2
L(sharers) 2..5
V groupsize = group_est + 1
L equal_birthdays(sharers, groupsize, 100) < 50.
groupsize++
 
L(gs) Int(groupsize - (groupsize - group_est) / 4.) .< groupsize + 999
V eq = equal_birthdays(sharers, gs, 250)
I eq > 50.
groupsize = gs
L.break
 
L(gs) groupsize - 1 .< groupsize + 999
V eq = equal_birthdays(sharers, gs, 50'000)
I eq > 50.
group_est = gs
print(‘#. independent people in a group of #. share a common birthday. (#3.1)’.format(sharers, gs, eq))
L.break</syntaxhighlight>
 
{{out}}
<pre>
2 independent people in a group of 23 share a common birthday. ( 50.6)
3 independent people in a group of 87 share a common birthday. ( 50.1)
4 independent people in a group of 187 share a common birthday. ( 50.5)
5 independent people in a group of 313 share a common birthday. ( 50.4)
</pre>
=={{header|Ada}}==
 
This solution assumes a 4-year cycle, with three 365-day years and one leap year.
 
<langsyntaxhighlight Adalang="ada">with Ada.Command_Line, Ada.Text_IO, Ada.Numerics.Discrete_random;
 
procedure Birthday_Test is
Line 98 ⟶ 136:
" persons sharing a common birthday.");
end loop;
end Birthday_Test;</langsyntaxhighlight>
 
{{out}}
Line 119 ⟶ 157:
An interesting observation:
The probability for groups of 313 persons having 5 persons sharing a common birthday is almost exactly 0.5. Note that a solution based on 365-day years, i.e., a solution ignoring leap days, would generate slightly but significantly larger probabilities.
 
=={{header|ALGOL 68}}==
{{works with|ALGOL 68|Revision 1}}
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-2.6 algol68g-2.6].}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
'''File: Birthday_problem.a68'''<langsyntaxhighlight lang="algol68">#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #
 
Line 188 ⟶ 225:
required common +:= 1
FI
OD # group size #</langsyntaxhighlight>'''Output:'''
<pre>
upb year: 365.2500; upb common: 5; upb sample size: 100000;
Line 202 ⟶ 239:
required common: 5; group size: 314; %age of years with required common birthdays: 50.66%;
</pre>
 
=={{header|C}}==
Computing probabilities to 5 sigmas of confidence. It's very slow, chiefly because to make sure a probability like 0.5006 is indeed above .5 instead of just statistical fluctuation, you have to run the simulation millions of times.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 300 ⟶ 336:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>
Line 308 ⟶ 344:
5 collision: 313 people, P = 0.500641 +/- 0.000128174
</pre>
 
=={{header|C++}}==
{{trans|Java}}
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <random>
#include <vector>
Line 367 ⟶ 402:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>2 independant people in a group of 23 share a common birthday. ( 50.6)
Line 373 ⟶ 408:
4 independant people in a group of 186 share a common birthday. ( 50.0)
5 independant people in a group of 313 share a common birthday. ( 50.5)</pre>
 
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.random, std.algorithm, std.conv;
 
/// For sharing common birthday must all share same common day.
Line 424 ⟶ 458:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>2 independent people in a group of 23 share a common birthday. ( 50.5)
Line 434 ⟶ 468:
Alternative version:
{{trans|C}}
<langsyntaxhighlight lang="d">import std.stdio, std.random, std.math;
 
enum nDays = 365;
Line 519 ⟶ 553:
writefln("%d collision: %d people, P = %g +/- %g", nCollisions, np, p, d);
}
}</langsyntaxhighlight>
{{out}}
<pre>2 collision: 23 people, P = 0.521934 +/- 0.00728933
Line 534 ⟶ 568:
{{libheader| System.SysUtils}}
{{Trans|C}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program Birthday_problem;
 
Line 639 ⟶ 673:
writeln('Press enter to exit');
readln;
end.</langsyntaxhighlight>
{{out}}
<pre>Wait for calculate
Line 647 ⟶ 681:
5 collision: 313 people, P = 0,50093354 +/- 0,00031116
Press enter to exit</pre>
=={{header|FreeBASIC}}==
{{trans|XPL0}}
<syntaxhighlight lang="freebasic">Function Simulacion(N As Integer) As Integer
Dim As Integer i, dias(365)
For i = 0 To 365-1
dias(i) = 0
Next i
Dim As Integer R, personas = 0
Do
R = Rnd * 365
dias(R) += 1
personas += 1
If dias(R) = N Then Return personas
Loop
End Function
 
Dim As Integer N, grupo, t
For N = 2 To 5
grupo = 0
For t = 1 To 10000
grupo += Simulacion(N)
Next t
Print Using "Average of # people in a population of ### share birthdays"; N; Int(grupo/10000)
Next N
Sleep</syntaxhighlight>
=={{header|Go}}==
{{trans|C}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 760 ⟶ 819:
n, np, p, d)
}
}</langsyntaxhighlight>
<pre>
2 collision: 23 people, P = 0.5081 ± 0.0016
Line 768 ⟶ 827:
</pre>
'''Also based on the C version:'''
<langsyntaxhighlight lang="go">package main
 
import (
Line 852 ⟶ 911:
}
return
}</langsyntaxhighlight>
{{Out}}
<pre>
Line 860 ⟶ 919:
5 collision: 313 people, P = 0.5011 ± 0.0002
</pre>
 
=={{header|Hy}}==
 
We use a simple but not very accurate simulation method.
 
<langsyntaxhighlight lang="lisp">(import
[numpy :as np]
[random [randint]])
Line 894 ⟶ 952:
(print (birthday 3))
(print (birthday 4))
(print (birthday 5))</langsyntaxhighlight>
 
=={{header|J}}==
 
Quicky approach (use a population of 1e5 people to get a quick estimate and then refine against a population of 1e8 people):
 
<langsyntaxhighlight Jlang="j">PopSmall=: 1e5 ?@# 365
PopBig=: 1e8 ?@# 365
 
Line 920 ⟶ 977:
assert. (2+y) > |approx-refine
refine, refine PopBig probShared y
)</langsyntaxhighlight>
 
Task cases:
 
<langsyntaxhighlight Jlang="j"> estGroupSz 2
23 0.507254
estGroupSz 3
Line 931 ⟶ 988:
187 0.502878
estGroupSz 5
313 0.500903</langsyntaxhighlight>
 
So, for example, we need a group of 88 to have at least a 50% chance of 3 people in the group having the same birthday in a year of 365 days. And, in that case, the simulated probability was 51.0737%
 
=={{header|Java}}==
Translation of [[Birthday_problem#Python|Python]] via [[Birthday_problem#D|D]]
{{works with|Java|8}}
<langsyntaxhighlight lang="java">import static java.util.Arrays.stream;
import java.util.Random;
 
Line 991 ⟶ 1,047:
}
}
}</langsyntaxhighlight>
 
<pre>2 independent people in a group of 23 share a common birthday. ( 50,6)
Line 997 ⟶ 1,053:
4 independent people in a group of 187 share a common birthday. ( 50,1)
5 independent people in a group of 314 share a common birthday. ( 50,2)</pre>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
{{trans|Python}}
 
<langsyntaxhighlight lang="julia">function equalbirthdays(sharers::Int, groupsize::Int; nrep::Int = 10000)
eq = 0
for _ in 1:nrep
Line 1,040 ⟶ 1,095:
push!(gsizes, gsize)
@printf("%i independent people in a group of %s share a common birthday. (%5.3f)\n", sh, gsize, freq)
end</langsyntaxhighlight>
 
{{out}}
Line 1,047 ⟶ 1,102:
4 independent people in a group of 187 share a common birthday. (0.500)
5 independent people in a group of 314 share a common birthday. (0.507)</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.1.3
 
import java.util.Random
Line 1,095 ⟶ 1,149:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,105 ⟶ 1,159:
5 independent people in a group of 314 share a common birthday (50.2%)
</pre>
 
=={{header|Lasso}}==
<langsyntaxhighlight Lassolang="lasso">if(sys_listunboundmethods !>> 'randomgen') => {
define randomgen(len::integer,max::integer)::array => {
#len <= 0 ? return
Line 1,136 ⟶ 1,189:
'Threshold: '+#threshold+', qty: '+#qty+' - probability: '+#probability+'\r'
#qty += 1
^}</langsyntaxhighlight>
 
{{out}}
Line 1,160 ⟶ 1,213:
Threshold: 5, qty: 314 - probability: 50.000000
</pre>
=={{header|Nim}}==
{{trans|Kotlin}}
<syntaxhighlight lang="nim">import random, sequtils, strformat
 
proc equalBirthdays(nSharers, groupSize, nRepetitions: int): float =
randomize(1)
var eq = 0
for _ in 1..nRepetitions:
var group: array[1..365, int]
for _ in 1..groupSize:
inc group[rand(1..group.len)]
eq += ord(group.anyIt(it >= nSharers))
result = eq * 100 / nRepetitions
 
proc main() =
 
var groupEst = 2
for sharers in 2..5:
 
# Coarse.
var groupSize = groupEst + 1
while equalBirthdays(sharers, groupSize, 100) < 50:
inc groupSize
 
# Finer.
let inf = (groupSize.toFloat - (groupSize - groupEst) / 4).toInt()
for gs in inf..(groupSize+998):
let eq = equalBirthdays(sharers, groupSize, 250)
if eq > 50:
groupSize = gs
break
 
# Finest.
for gs in (groupSize-1)..(groupSize+998):
let eq = equalBirthdays(sharers, gs, 50_000)
if eq > 50:
groupEst = gs
echo &"{sharers} independent people in a group of {gs:3} ",
&"share a common birthday ({eq:4.1f}%)"
break
 
main()</syntaxhighlight>
 
{{out}}
<pre>2 independent people in a group of 23 share a common birthday (50.7%)
3 independent people in a group of 87 share a common birthday (50.0%)
4 independent people in a group of 187 share a common birthday (50.2%)
5 independent people in a group of 313 share a common birthday (50.2%)</pre>
=={{header|PARI/GP}}==
<langsyntaxhighlight lang="parigp">simulate(n)=my(v=vecsort(vector(n,i,random(365))),t,c=1); for(i=2,n,if(v[i]>v[i-1],t=max(t,c);c=1,c++)); t
find(n)=my(guess=365*n-342,t);while(1, t=sum(i=1,1e3,simulate(guess)>=n)/1e3; if(t>550, guess--); if(t<450, guess++); if(450<=t && t<=550, return(guess)))
find(2)
find(3)
find(4)
find(5)</langsyntaxhighlight>
 
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use List::AllUtils qw(max min uniqnum count_by any);
Line 1,196 ⟶ 1,295:
}
 
printf "$_ people in a group of %s share a common birthday. (%.4f)\n", simulation($_) for 2..5</langsyntaxhighlight>
{{out}}
<pre>2 people in a group of 23 share a common birthday. (0.5083)
Line 1,202 ⟶ 1,301:
4 people in a group of 187 share a common birthday. (0.5034)
5 people in a group of 313 share a common birthday. (0.5008)</pre>
 
=={{header|Phix}}==
{{trans|D}}
<!--<syntaxhighlight lang="phix">(phixonline)[very/too slow]-->
<lang Phix>constant nDays = 365
<span style="color: #008080;">constant</span> <span style="color: #000000;">nDays</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">365</span>
-- 5 sigma confidence. Conventionally people think 3 sigmas are
<span style="color: #000080;font-style:italic;">-- 5 sigma confidence. Conventionally people think 3 sigmas are
-- good enough, but for the case of 5 people sharing a birthday,
-- good enough, but for the case of 5 people sharing a birthday,
-- 3 sigmas actually sometimes gives a slightly wrong answer.
-- 3 sigmas actually sometimes gives a slightly wrong answer.</span>
constant nSigmas = 5.0; -- Currently 3 for smaller run time.
<span style="color: #008080;">constant</span> <span style="color: #000000;">nSigmas</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5.0</span><span style="color: #0000FF;">;</span> <span style="color: #000080;font-style:italic;">-- Change to 3 for smaller run time.</span>
function simulate1(integer nPeople, nCollisions)
<span style="color: #008080;">function</span> <span style="color: #000000;">simulate1</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">nPeople</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nCollisions</span><span style="color: #0000FF;">)</span>
--
<span style="color: #000080;font-style:italic;">--
-- Given n people, if m of them have same birthday in one run.
-- Given n people, if m of them have same birthday in one run.
--
--</span>
sequence days = repeat(0,nDays)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">days</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nDays</span><span style="color: #0000FF;">)</span>
for p=1 to nPeople do
<span style="color: #008080;">for</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nPeople</span> <span style="color: #008080;">do</span>
integer day = rand(nDays)
<span style="color: #004080;">integer</span> <span style="color: #000000;">day</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nDays</span><span style="color: #0000FF;">)</span>
days[day] += 1
<span style="color: #000000;">days</span><span style="color: #0000FF;">[</span><span style="color: #000000;">day</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if days[day] == nCollisions then
<span style="color: #008080;">if</span> <span style="color: #000000;">days</span><span style="color: #0000FF;">[</span><span style="color: #000000;">day</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">nCollisions</span> <span style="color: #008080;">then</span>
return true
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return false;
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">;</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function prob(integer np, nCollisions, atom pThresh)
<span style="color: #008080;">function</span> <span style="color: #000000;">prob</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">np</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nCollisions</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">pThresh</span><span style="color: #0000FF;">)</span>
--
<span style="color: #000080;font-style:italic;">--
-- Decide if the probablity of n out of np people sharing a birthday
-- Decide if the probablity of n out of np people sharing a birthday
-- is above or below pThresh, with nSigmas sigmas confidence.
-- is above or below pThresh, with nSigmas sigmas confidence.
-- If pThresh is very low or hi, minimum runs need to be much higher.
-- If pThresh is very low or hi, minimum runs need to be much higher.
--
--</span>
atom p, d; -- Probablity and standard deviation.
<span style="color: #004080;">atom</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">;</span> <span style="color: #000080;font-style:italic;">-- Probablity and standard deviation.</span>
integer nRuns = 0, yes = 0;
<span style="color: #004080;">integer</span> <span style="color: #000000;">nRuns</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">yes</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">;</span>
while nRuns<10 or (abs(p - pThresh) < (nSigmas * d)) do
<span style="color: #008080;">while</span> <span style="color: #000000;">nRuns</span><span style="color: #0000FF;"><</span><span style="color: #000000;">10</span> <span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">pThresh</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;"><</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">nSigmas</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">do</span>
yes += simulate1(np, nCollisions)
<span style="color: #000000;">yes</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">simulate1</span><span style="color: #0000FF;">(</span><span style="color: #000000;">np</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nCollisions</span><span style="color: #0000FF;">)</span>
nRuns += 1
<span style="color: #000000;">nRuns</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
p = yes/nRuns
<span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">yes</span><span style="color: #0000FF;">/</span><span style="color: #000000;">nRuns</span>
d = sqrt(p * (1 - p) / nRuns);
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span> <span style="color: #0000FF;">*</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">1</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">nRuns</span><span style="color: #0000FF;">);</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
return {p,d}
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">}</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function findHalfChance(integer nCollisions)
<span style="color: #008080;">function</span> <span style="color: #000000;">findHalfChance</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">nCollisions</span><span style="color: #0000FF;">)</span>
-- Bisect for truth.
<span style="color: #000080;font-style:italic;">-- Bisect for truth.</span>
atom p, dev
<span style="color: #004080;">atom</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dev</span>
integer mid = 1,
<span style="color: #004080;">integer</span> <span style="color: #000000;">mid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
lo = 0,
<span style="color: #000000;">lo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
hi = nDays * (nCollisions - 1) + 1;
<span style="color: #000000;">hi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nDays</span> <span style="color: #0000FF;">*</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">nCollisions</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">;</span>
while lo < mid or p < 0.5 do
<span style="color: #008080;">while</span> <span style="color: #000000;">lo</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">mid</span> <span style="color: #008080;">or</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">0.5</span> <span style="color: #008080;">do</span>
mid = floor((hi + lo) / 2)
<span style="color: #000000;">mid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">hi</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">lo</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
{p,dev} = prob(mid, nCollisions, 0.5)
<span style="color: #0000FF;">{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dev</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">prob</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mid</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nCollisions</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0.5</span><span style="color: #0000FF;">)</span>
if (p < 0.5) then
<span style="color: #008080;">if</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">p</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">0.5</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
lo = mid + 1;
<span style="color: #000000;">lo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mid</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">;</span>
else
<span hi style="color: mid#008080;">else</span>
<span style="color: #000000;">hi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mid</span><span style="color: #0000FF;">;</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
 
if (hi < lo) then
<span style="color: #008080;">if</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">hi</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">lo</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
return findHalfChance(nCollisions) -- reset
<span style="color: #008080;">return</span> <span style="color: #000000;">findHalfChance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nCollisions</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- reset</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
 
return {p,dev,mid}
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dev</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mid</span><span style="color: #0000FF;">}</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
for nCollisions=2 to 6 do
<span style="color: #008080;">for</span> <span style="color: #000000;">nCollisions</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">6</span> <span style="color: #008080;">do</span>
atom {p,d,np} = findHalfChance(nCollisions)
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">np</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">findHalfChance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nCollisions</span><span style="color: #0000FF;">)</span>
printf(1,"%d collision: %d people, P = %g +/- %g\n", {nCollisions, np, p, d})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d collision: %d people, P = %g +/- %g\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">nCollisions</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">np</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">})</span>
end for</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,291 ⟶ 1,391:
6 collision: 460 people, P = 0.502901 +/- 0.000580137
</pre>
 
=={{header|PL/I}}==
<langsyntaxhighlight PLlang="pl/Ii">*process source attributes xref;
bd: Proc Options(main);
/*--------------------------------------------------------------------
Line 1,343 ⟶ 1,442:
End;
End;
End;</langsyntaxhighlight>
Output:
<pre>
Line 1,417 ⟶ 1,516:
1182 496957 503043 50.304% <-
1183 494414 505586 50.559% <-</pre>
 
=={{header|Python}}==
Note: the first (unused), version of function equal_birthdays() uses a different but equally valid interpretation of the phrase "common birthday".
<langsyntaxhighlight lang="python">
from random import randint
 
Line 1,460 ⟶ 1,558:
break
group_est.append(groupsize)
print("%i independent people in a group of %s share a common birthday. (%5.1f)" % (sharers, groupsize, eq))</langsyntaxhighlight>
 
{{out}}
Line 1,470 ⟶ 1,568:
===Enumeration method===
The following enumerates all birthday distributation of n people in a year. It's patentedly unscalable.
<langsyntaxhighlight lang="python">from collections import defaultdict
days = 365
 
Line 1,510 ⟶ 1,608:
n, good, combos = find_half(x)
print "%d of %d people sharing birthday: %d out of %d combos"% (x, n, good, combos)
</syntaxhighlight>
</lang>
{{out}}
<pre>2 of 23 people sharing birthday: 43450860051057961364418604769486195435604861663267741453125 out of 85651679353150321236814267844395152689354622364044189453125 combos
Line 1,517 ⟶ 1,615:
</pre>
===Enumeration method #2===
<langsyntaxhighlight lang="python"># ought to use a memoize class for all this
# factorial
def fact(n, cache={0:1}):
Line 1,563 ⟶ 1,661:
return
 
for x in range(2, 6): find_half(x)</langsyntaxhighlight>
{{out}}
<pre>
Line 1,571 ⟶ 1,669:
313 of 5 people: 498385488882289...2578125/99464149835930...2578125 combos
</pre>
 
=={{header|Racket}}==
{{trans|Python}}Based on the Python task. For three digits precision use 250000 repetitions. For four digits precision use 25000000 repetitions, but it’s very slow. See discussion page.
<langsyntaxhighlight Racketlang="racket">#lang racket
 
#;(define repetitions 25000000) ; for \sigma=1/10000
Line 1,622 ⟶ 1,719:
(search-from sharers (search-coarse-group-size sharers))])
(printf "~a independent people in a group of ~a share a common birthday. (~a%)\n"
sharers group-size (~r (* probability 100) #:precision '(= 2)))))</langsyntaxhighlight>
'''Output'''
<pre>2 independent people in a group of 23 share a common birthday. (50.80%)
Line 1,629 ⟶ 1,726:
5 independent people in a group of 313 share a common birthday. (50.17%)
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
Gives correct answers, but more of a proof-of-concept at this point, even with max-trials at 250K it is too slow to be practical.
<syntaxhighlight lang="raku" perl6line>sub simulation ($c) {
my $max-trials = 250_000;
my $min-trials = 5_000;
Line 1,647 ⟶ 1,743:
}
 
printf "$_ people in a group of %s share a common birthday. (%.3f)\n", simulation($_) for 2..5;</langsyntaxhighlight>
{{out}}
<pre>2 people in a group of 23 share a common birthday. (0.506)
Line 1,653 ⟶ 1,749:
4 people in a group of 187 share a common birthday. (0.500)
5 people in a group of 313 share a common birthday. (0.507)</pre>
 
=={{header|REXX}}==
===version 1===
Line 1,661 ⟶ 1,756:
 
This REXX version doesn't need a precalculated group size to find the percentage required to exceed 50%.
<langsyntaxhighlight lang="rexx">/*REXX pgm examines the birthday problem via random# simulation (with specifiable parms)*/
parse arg dups samp seed . /*get optional arguments from the CL. */
if dups=='' | dups=="," then dups= 10 /*Not specified? Then use the default.*/
Line 1,692 ⟶ 1,787:
end /*try=start.g*/ /* [↑] where the try─outs happen. */
say right(g, 15) right(try, 15) center( format( s / samp * 100, , 4)'%', 30)
end /*g*/ /*stick a fork in it, we're all done. */</langsyntaxhighlight>
{{out|output|text= &nbsp; when using the default inputs:}}
<pre>
Line 1,712 ⟶ 1,807:
 
===version 2===
<langsyntaxhighlight lang="rexx"> /*--------------------------------------------------------------------
* 04.11.2013 Walter Pachl translated from PL/I
* Take samp samples of groups with gs persons and check
Line 1,743 ⟶ 1,838:
Say format(gs,10) cnt.0 cnt.1 100*hits||'%'||arrow
End
End</langsyntaxhighlight>
Output:
<pre>
Line 1,785 ⟶ 1,880:
461 49316 50684 50.68400% <-
462 49121 50879 50.87900% <-</pre>
 
=={{header|Ruby}}==
{{trans|Java}}
<langsyntaxhighlight lang="ruby">def equalBirthdays(nSharers, groupSize, nRepetitions)
eq = 0
 
Line 1,833 ⟶ 1,927:
end
 
main()</langsyntaxhighlight>
{{out}}
<pre>2 independant people in a group of 23 share a common birthday. ( 50.5)
Line 1,839 ⟶ 1,933:
4 independant people in a group of 187 share a common birthday. ( 50.3)
5 independant people in a group of 313 share a common birthday. ( 50.3)</pre>
 
 
=={{header|Scala}}==
{{trans|Java}}
<syntaxhighlight lang="Scala">
import scala.util.Random
import scala.util.control.Breaks._
 
object Test {
 
def equalBirthdays(
nSharers: Int,
groupSize: Int,
nRepetitions: Int
): Double = {
val rand = new Random(1)
var eq = 0
 
for (_ <- 1 to nRepetitions) {
val group = new Array[Int](365)
for (_ <- 1 to groupSize) {
val birthday = rand.nextInt(group.length)
group(birthday) += 1
}
if (group.exists(_ >= nSharers)) eq += 1
}
 
(eq * 100.0) / nRepetitions
}
 
def main(args: Array[String]): Unit = {
var groupEst = 2
 
for (sharers <- 2 until 6) {
// Coarse.
var groupSize = groupEst + 1
while (equalBirthdays(sharers, groupSize, 100) < 50.0)
groupSize += 1
 
// Finer.
val inf = (groupSize - (groupSize - groupEst) / 4.0).toInt
breakable({
for (gs <- inf until groupSize + 999) {
val eq = equalBirthdays(sharers, groupSize, 250)
if (eq > 50.0) {
groupSize = gs
break
}
}
})
 
// Finest.
breakable({
for (gs <- (groupSize - 1) until groupSize + 999) {
val eq = equalBirthdays(sharers, gs, 50000)
if (eq > 50.0) {
groupEst = gs
println(
f"$sharers independent people in a group of $gs share a common birthday. ($eq%5.1f)"
)
break
}
}
})
}
}
}
</syntaxhighlight>
{{out}}
<pre>
2 independent people in a group of 23 share a common birthday. ( 50.6)
3 independent people in a group of 87 share a common birthday. ( 50.4)
4 independent people in a group of 187 share a common birthday. ( 50.1)
5 independent people in a group of 314 share a common birthday. ( 50.2)
 
</pre>
 
 
=={{header|SQL}}==
birthday.sql
<syntaxhighlight lang="sql">
<lang SQL>
with
c as
Line 1,905 ⟶ 2,076:
from sol where rownum = 1
;
</syntaxhighlight>
</lang>
 
SQL> @ birthday.sql
Line 1,913 ⟶ 2,084:
----------
23
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">proc birthdays {num {same 2}} {
for {set i 0} {$i < $num} {incr i} {
set b [expr {int(rand() * 365)}]
Line 1,948 ⟶ 2,118:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,979 ⟶ 2,149:
level found: 315 people
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "random" for Random
import "./fmt" for Fmt
 
var equalBirthdays = Fn.new { |nSharers, groupSize, nRepetitions|
Line 2,026 ⟶ 2,195:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,036 ⟶ 2,205:
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">func Sim(N);
\Simulate birthdays and return number of people to have N same days
int N, I, People, R;
char Days(365);
[for I:= 0 to 365-1 do Days(I):= 0;
People:= 0;
loop [R:= Ran(365);
Days(R):= Days(R)+1;
People:= People+1;
if Days(R) = N then return People;
];
];
 
int N, Sum, Trial;
[for N:= 2 to 5 do
[Sum:= 0;
for Trial:= 1 to 10000 do
Sum:= Sum + Sim(N);
IntOut(0, N); Text(0, ": "); IntOut(0, Sum/10000); CrLf(0);
];
]</syntaxhighlight>
 
{{out}}
<pre>
2: 24
3: 88
4: 187
5: 311
</pre>
=={{header|zkl}}==
Pure simulation; adding a person to a population until there are the required number of collisions, then repeating that a bunch of times to get an average.
<langsyntaxhighlight lang="zkl">fcn bdays(N){ // N is shared birthdays in a population
year:=(0).pump(365,List.createLong(365).write,0); // 365 days == one year
shared:=people:=0; do{ // add a new person to population
Line 2,051 ⟶ 2,250:
println("Average of %d people in a populatation of %s share birthdays"
.fmt(n,simulate(n,0d10_000)));
}</langsyntaxhighlight>
{{out}}
<pre>
338

edits