Skip to content

Commit 36e31a6

Browse files
authored
Add baffling birthdays exercice (#3075)
1 parent 184c18c commit 36e31a6

File tree

14 files changed

+743
-0
lines changed

14 files changed

+743
-0
lines changed

config.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,20 @@
12111211
],
12121212
"difficulty": 6
12131213
},
1214+
{
1215+
"slug": "baffling-birthdays",
1216+
"name": "Baffling Birthdays",
1217+
"uuid": "b534049a-5920-4906-9091-0fa6d81a3636",
1218+
"practices": [],
1219+
"prerequisites": [
1220+
"for-loops",
1221+
"lists",
1222+
"sets",
1223+
"randomness",
1224+
"datetime"
1225+
],
1226+
"difficulty": 6
1227+
},
12141228
{
12151229
"slug": "bank-account",
12161230
"name": "Bank Account",
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Instructions
2+
3+
Your task is to estimate the birthday paradox's probabilities.
4+
5+
To do this, you need to:
6+
7+
- Generate random birthdates.
8+
- Check if a collection of randomly generated birthdates contains at least two with the same birthday.
9+
- Estimate the probability that at least two people in a group share the same birthday for different group sizes.
10+
11+
~~~~exercism/note
12+
A birthdate includes the full date of birth (year, month, and day), whereas a birthday refers only to the month and day, which repeat each year.
13+
Two birthdates with the same month and day correspond to the same birthday.
14+
~~~~
15+
16+
~~~~exercism/caution
17+
The birthday paradox assumes that:
18+
19+
- There are 365 possible birthdays (no leap years).
20+
- Each birthday is equally likely (uniform distribution).
21+
22+
Your implementation must follow these assumptions.
23+
~~~~
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Introduction
2+
3+
Fresh out of college, you're throwing a huge party to celebrate with friends and family.
4+
Over 70 people have shown up, including your mildly eccentric Uncle Ted.
5+
6+
In one of his usual antics, he bets you £100 that at least two people in the room share the same birthday.
7+
That sounds ridiculous — there are many more possible birthdays than there are guests, so you confidently accept.
8+
9+
To your astonishment, after collecting the birthdays of just 32 guests, you've already found two guests that share the same birthday.
10+
Accepting your loss, you hand Uncle Ted his £100, but something feels off.
11+
12+
The next day, curiosity gets the better of you.
13+
A quick web search leads you to the [birthday paradox][birthday-problem], which reveals that with just 23 people, the probability of a shared birthday exceeds 50%.
14+
15+
Ah. So _that's_ why Uncle Ted was so confident.
16+
17+
Determined to turn the tables, you start looking up other paradoxes; next time, _you'll_ be the one making the bets.
18+
19+
~~~~exercism/note
20+
The birthday paradox is a [veridical paradox][veridical-paradox]: even though it feels wrong, it is actually true.
21+
22+
[veridical-paradox]: https://en.wikipedia.org/wiki/Paradox#Quine's_classification
23+
~~~~
24+
25+
[birthday-problem]: https://en.wikipedia.org/wiki/Birthday_problem
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"authors": [
3+
"Baboushka"
4+
],
5+
"files": {
6+
"solution": [
7+
"src/main/java/BafflingBirthdays.java"
8+
],
9+
"test": [
10+
"src/test/java/BafflingBirthdaysTest.java"
11+
],
12+
"example": [
13+
".meta/src/reference/java/BafflingBirthdays.java"
14+
],
15+
"invalidator": [
16+
"build.gradle"
17+
]
18+
},
19+
"blurb": "Estimate the birthday paradox's probabilities.",
20+
"source": "Erik Schierboom",
21+
"source_url": "https://github.com/exercism/problem-specifications/pull/2539"
22+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import java.time.LocalDate;
2+
import java.util.ArrayList;
3+
import java.util.concurrent.ThreadLocalRandom;
4+
import java.util.HashSet;
5+
import java.util.List;
6+
import java.util.Set;
7+
8+
class BafflingBirthdays {
9+
private static final int nonLeapYear = 2001;
10+
private static final int daysInYear = 365;
11+
12+
boolean sharedBirthday(List<String> birthdates) {
13+
Set<String> seen = new HashSet<>();
14+
for (String birthdate : birthdates) {
15+
String monthDay = birthdate.substring(5);
16+
if (!seen.add(monthDay)) {
17+
return true;
18+
}
19+
}
20+
return false;
21+
}
22+
23+
List<String> randomBirthdates(int groupSize) {
24+
if (groupSize <= 0) {
25+
return List.of();
26+
}
27+
List<String> birthdates = new ArrayList<>(groupSize);
28+
ThreadLocalRandom random = ThreadLocalRandom.current();
29+
for (int i = 0; i < groupSize; i++) {
30+
int dayOfYear = random.nextInt(1, daysInYear + 1);
31+
LocalDate date = LocalDate.ofYearDay(nonLeapYear, dayOfYear);
32+
birthdates.add(date.toString());
33+
}
34+
return birthdates;
35+
}
36+
37+
double estimatedProbabilityOfSharedBirthday(int groupSize) {
38+
if (groupSize <= 1) {
39+
return 0.0;
40+
}
41+
if (groupSize > daysInYear) {
42+
return 100.0;
43+
}
44+
double probabilityNoSharedBirthday = 1.0;
45+
for (int k = 0; k < groupSize; k++) {
46+
probabilityNoSharedBirthday *= (daysInYear - k) / (double) daysInYear;
47+
}
48+
return (1 - probabilityNoSharedBirthday) * 100.0;
49+
}
50+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[716dcc2b-8fe4-4fc9-8c48-cbe70d8e6b67]
13+
description = "shared birthday -> one birthdate"
14+
15+
[f7b3eb26-bcfc-4c1e-a2de-af07afc33f45]
16+
description = "shared birthday -> two birthdates with same year, month, and day"
17+
18+
[7193409a-6e16-4bcb-b4cc-9ffe55f79b25]
19+
description = "shared birthday -> two birthdates with same year and month, but different day"
20+
21+
[d04db648-121b-4b72-93e8-d7d2dced4495]
22+
description = "shared birthday -> two birthdates with same month and day, but different year"
23+
24+
[3c8bd0f0-14c6-4d4c-975a-4c636bfdc233]
25+
description = "shared birthday -> two birthdates with same year, but different month and day"
26+
27+
[df5daba6-0879-4480-883c-e855c99cdaa3]
28+
description = "shared birthday -> two birthdates with different year, month, and day"
29+
30+
[0c17b220-cbb9-4bd7-872f-373044c7b406]
31+
description = "shared birthday -> multiple birthdates without shared birthday"
32+
33+
[966d6b0b-5c0a-4b8c-bc2d-64939ada49f8]
34+
description = "shared birthday -> multiple birthdates with one shared birthday"
35+
36+
[b7937d28-403b-4500-acce-4d9fe3a9620d]
37+
description = "shared birthday -> multiple birthdates with more than one shared birthday"
38+
39+
[70b38cea-d234-4697-b146-7d130cd4ee12]
40+
description = "random birthdates -> generate requested number of birthdates"
41+
42+
[d9d5b7d3-5fea-4752-b9c1-3fcd176d1b03]
43+
description = "random birthdates -> years are not leap years"
44+
45+
[d1074327-f68c-4c8a-b0ff-e3730d0f0521]
46+
description = "random birthdates -> months are random"
47+
48+
[7df706b3-c3f5-471d-9563-23a4d0577940]
49+
description = "random birthdates -> days are random"
50+
51+
[89a462a4-4265-4912-9506-fb027913f221]
52+
description = "estimated probability of at least one shared birthday -> for one person"
53+
54+
[ec31c787-0ebb-4548-970c-5dcb4eadfb5f]
55+
description = "estimated probability of at least one shared birthday -> among ten people"
56+
57+
[b548afac-a451-46a3-9bb0-cb1f60c48e2f]
58+
description = "estimated probability of at least one shared birthday -> among twenty-three people"
59+
60+
[e43e6b9d-d77b-4f6c-a960-0fc0129a0bc5]
61+
description = "estimated probability of at least one shared birthday -> among seventy people"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
plugins {
2+
id "java"
3+
}
4+
5+
repositories {
6+
mavenCentral()
7+
}
8+
9+
dependencies {
10+
testImplementation platform("org.junit:junit-bom:5.10.0")
11+
testImplementation "org.junit.jupiter:junit-jupiter"
12+
testImplementation "org.assertj:assertj-core:3.25.1"
13+
14+
testRuntimeOnly "org.junit.platform:junit-platform-launcher"
15+
}
16+
17+
test {
18+
useJUnitPlatform()
19+
20+
testLogging {
21+
exceptionFormat = "full"
22+
showStandardStreams = true
23+
events = ["passed", "failed", "skipped"]
24+
}
25+
}
Binary file not shown.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
4+
validateDistributionUrl=true
5+
zipStoreBase=GRADLE_USER_HOME
6+
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)