Фон
Парадокс дня рождения является популярной проблемой в теории вероятностей, бросает вызов ( у большинства людей) математическая интуиция. Постановка проблемы:
Учитывая N человек, какова вероятность того, что по крайней мере два из них имеют одинаковый день рождения (без учета года).
Проблема обычно упрощается за счет полного игнорирования високосных дней. В этом случае ответом для N = 23 является P (23) ≈ 0.5072972 (в качестве общего примера). В связанной статье Википедии объясняется, как прийти к такой вероятности. Кроме того, это видео Numberphile делает действительно хорошую работу.
Тем не менее, для этой задачи мы хотим сделать это правильно и не игнорировать високосные годы. Это немного сложнее, поскольку теперь нужно добавить 29 февраля, но этот конкретный день рождения менее вероятен, чем все остальные.
Мы также будем использовать правила полного високосного года :
- Если год делится на 400, это високосный год.
- Иначе, если год делится на 100, это не високосный год.
- Иначе, если год делится на 4, это високосный год.
- Иначе, это не високосный год.
Смущенный? Это означает, что 1700, 1800, 1900, 2100, 2200, 2300 лет не являются високосными, а 1600, 2000, 2400 (как и любой другой год, делимый на 4). Этот календарь повторяется каждые 400 лет, и мы будем предполагать равномерное распределение дней рождения в течение этих 400 лет.
Исправленный результат для N = 23 теперь равен P (23) ≈ 0.5068761 .
Соревнование
Учитывая целое число 1 ≤ N < 100
, определите вероятность того, что среди N
людей как минимум двое имеют одинаковый день рождения при рассмотрении правил високосного года. Результатом должно быть число с плавающей точкой или число с фиксированной запятой с точностью не менее 6 десятичных знаков. Допустимо усекать конечные нули.
Вы можете написать программу или функцию, принимая ввод через STDIN (или ближайшую альтернативу), аргумент командной строки или аргумент функции и выводить результат через STDOUT (или ближайшую альтернативу), возвращаемое значение функции или параметр функции (out).
Ваше решение должно быть в состоянии произвести вывод для всех 99 входов за считанные секунды. Это в основном исключает методы Монте-Карло с тоннами выборок, поэтому, если вы используете принципиально быстрый и точный алгоритм на чрезмерно медленном эзотерическом языке, я хочу дать свободу в этом правиле.
Тестовые случаи
Вот полная таблица результатов:
1 => 0.000000
2 => 0.002737
3 => 0.008195
4 => 0.016337
5 => 0.027104
6 => 0.040416
7 => 0.056171
8 => 0.074251
9 => 0.094518
10 => 0.116818
11 => 0.140987
12 => 0.166844
13 => 0.194203
14 => 0.222869
15 => 0.252642
16 => 0.283319
17 => 0.314698
18 => 0.346578
19 => 0.378764
20 => 0.411063
21 => 0.443296
22 => 0.475287
23 => 0.506876
24 => 0.537913
25 => 0.568260
26 => 0.597796
27 => 0.626412
28 => 0.654014
29 => 0.680524
30 => 0.705877
31 => 0.730022
32 => 0.752924
33 => 0.774560
34 => 0.794917
35 => 0.813998
36 => 0.831812
37 => 0.848381
38 => 0.863732
39 => 0.877901
40 => 0.890932
41 => 0.902870
42 => 0.913767
43 => 0.923678
44 => 0.932658
45 => 0.940766
46 => 0.948060
47 => 0.954598
48 => 0.960437
49 => 0.965634
50 => 0.970242
51 => 0.974313
52 => 0.977898
53 => 0.981043
54 => 0.983792
55 => 0.986187
56 => 0.988266
57 => 0.990064
58 => 0.991614
59 => 0.992945
60 => 0.994084
61 => 0.995055
62 => 0.995880
63 => 0.996579
64 => 0.997169
65 => 0.997665
66 => 0.998080
67 => 0.998427
68 => 0.998715
69 => 0.998954
70 => 0.999152
71 => 0.999314
72 => 0.999447
73 => 0.999556
74 => 0.999645
75 => 0.999717
76 => 0.999775
77 => 0.999822
78 => 0.999859
79 => 0.999889
80 => 0.999913
81 => 0.999932
82 => 0.999947
83 => 0.999959
84 => 0.999968
85 => 0.999976
86 => 0.999981
87 => 0.999986
88 => 0.999989
89 => 0.999992
90 => 0.999994
91 => 0.999995
92 => 0.999996
93 => 0.999997
94 => 0.999998
95 => 0.999999
96 => 0.999999
97 => 0.999999
98 => 0.999999
99 => 1.000000
(Конечно, P (99) только 1,0 из-за округления. Вероятность не достигнет точно 1,0, пока P (367) .)
источник
Ответы:
Pyth, 31
34байтаДемонстрация , Испытательный жгут
Это работает аналогично старой версии, за исключением того, что вместо отдельной генерации значения (366 + n * (.2425 - 1)) и его умножения оно начинается с генерации списка, который расширяется с 366 до 365 - n + 2, затем изменяет 366 на месте, чтобы стать (366 + n * (.2425 - 1)), а затем берет произведение из списка. Кроме того, константы 366 и -7575 используются вместо 365 и .2425.
Старая версия:
Pyth, 34 байта
Есть два возможных способа, чтобы не было пары людей с одинаковым днем рождения: у всех разные дни рождения, и у кого-то нет дня рождения 29 февраля, и у кого-то день рождения 29-го, и у всех остальных день рождения разные. дни рождения в обычные дни.
Вероятность первого появления равна (365 * 364 * ... 365 - n + 1) / (365,2425 ^ n).
Вероятность второго появления (365 * 364 * ... 365 - n + 2) * .2425 * n / (365.2425 ^ n)
Они могут быть записаны вместе как (365 * 364 * ... 365 - n + 2) * (365 - n + 1 + .2425 * n) / (365.2425 ^ n) = (365 * 364 * ... 365 - n + 2) * (365 + 1 + (.2425 - 1) * n) / (365,2425 ^ n).
Это вероятность отсутствия пар, поэтому вероятность, по крайней мере, одной пары, равна одному минус вышеуказанное число.
источник
Питон,
179178144143140136135133p(n)
дает результат. Перейдите.2425
на,fractions.Fraction(97,400)
чтобы получить точный результат.источник
2
иand
.1/
течениеg
и разделить на ней вместо этого?e=365
и заменить 365 на е и 367 на е + 2Python
155153151142140 байтПозвоните
a(n)
для результата. Для точных результатов завернитеd
в дробь.Тест здесь
Использует ту же технику, что и здесь , но с измененными константами.
источник
2
иand
.80386 машинный код, 43 байта
Hexdump кода:
Я начал со следующей формулы (для дополнительной вероятности):
(Вот
d = 366 * 400 - 303
количество дней в 400 лет)Вот код C ++, который его реализует (он уже немного оптимизирован):
Код устроен так, что для него требуется минимальное количество констант - только две (
400 / d
и303 / d
). Я используюfloat
тип для их представления, потому что он занимает меньше места (4 байта на константу). Кроме того, я не хотел умножатьconst2
наk - 1
(потому что это потребовало бы преобразованияk - 1
вfloat
); код вычитаетconst2
вместо этого несколько раз.Вот листинг на ассемблере:
источник