Files
freeCodeCamp's Camper Bot cc87f4455d chore(i18n,learn): processed translations (#54077)
Co-authored-by: Naomi Carrigan <nhcarrigan@gmail.com>
2024-03-25 16:31:40 +00:00

260 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: 5e44414f903586ffb414c950
title: Калькулятор вірогідностей
challengeType: 23
forumTopicId: 462364
dashedName: probability-calculator
---
# --description--
Уявімо, що у капелюсі лежить 5 синіх, 4 червоні та 2 зелені кульки. Яка вірогідність того, що з 4 кульок, які ви витягнете, принаймні 1 буде червоною та 2 зеленими? І хоча можливо прорахувати вірогідність за допомогою вищої математики, легше буде написати програму для виконання великої кількості експериментів, щоб оцінити приблизну вірогідність.
У цьому проєкті напишіть програму, яка визначатиме вірогідність випадкового діставання певних кульок із капелюха.
Спочатку створіть клас `Hat` в `main.py`. Клас має приймати змінну кількість аргументів, які вказують кількість кульок всіх кольорів із капелюха. Наприклад, об’єкт класу можна створити такими способами:
```py
hat1 = Hat(yellow=3, blue=2, green=6)
hat2 = Hat(red=5, orange=4)
hat3 = Hat(red=5, orange=4, black=1, blue=0, pink=2, striped=9)
```
Капелюх завжди створюється з принаймні однією кулькою. Аргументи, які передаються в об’єкт-капелюх, під час створення мають конвертуватися в поле класу `contents`. `contents` має бути списком рядків, де один елемент дорівнює кожній кульці у капелюсі. Кожний елемент списку має бути назвою кольору, яка позначає кульку певного кольору. Наприклад, якщо капелюх `{"red": 2, "blue": 1}`, то `contents` має бути `["red", "red", "blue"]`.
Клас `Hat` повинен мати метод `draw`, який приймає аргумент з позначенням кількості кульок, які можна витягти з капелюха. Цей метод має випадково витягати кульки з `contents` та повертати ці кульки у вигляді списку рядків. Кульки не повинні повертатися до капелюха після того, як їх витягли (як в експерименті з урною без заміни). Якщо кількість кульок, які треба витягти, перевищує доступну кількість, поверніть усі кульки.
Потім створіть функцію `experiment` в `main.py` (не в класі `Hat`). Ця функція повинна приймати наступні аргументи:
- `hat`: об’єкт-капелюх з кульками, що потрібно скопіювати у функцію.
- `expected_balls`: об’єкт, який вказує на точну кількість кульок, які треба вийняти з капелюха для експерименту. Наприклад, щоб визначити вірогідність того, що ви витягнете 2 сині та 1 червону кульки з капелюха, встановіть `expected_balls` на `{"blue":2, "red":1}`.
- `num_balls_drawn`: кількість кульок, які треба витягти з капелюха в кожному експерименті.
- `num_experiments`: кількість експериментів, які треба провести. (Чим більше експериментів було проведено, тим точнішою буде вірогідність.)
Функція `experiment` повинна повертати вірогідність.
Допустимо, ви хочете визначити вірогідність витягти щонайменше дві червоні кульки та одну зелену, коли витягаєте п’ять кульок з капелюха, який містить шість чорних, чотири червоні та три зелені кульки. Для цього вам треба виконати `N` експериментів, порахувати скільки `M` разів ви можете витягти принаймні дві червоні кульки і одну зелену кульку та вирахувати вірогідність як `M/N`. Кожен експеримент складається з капелюха (з певними кульками), витягування декількох кульок та перевірки, чи ви витягли необхідні кульки.
Ось так ви можете викликати функцію `experiment`, базуючись на прикладі зверху з 2000 експериментами:
```py
hat = Hat(black=6, red=4, green=3)
probability = experiment(hat=hat,
expected_balls={"red":2,"green":1},
num_balls_drawn=5,
num_experiments=2000)
```
Результат буде приблизно таким:
```bash
>>> 0.356
```
Оскільки все базується на випадкових витяганнях, то вірогідність буде злегка відрізнятися з кожним новим запуском коду.
_Підказка: спробуйте використати вже імпортовані модулі зверху. Не ініціалізуйте випадкове початкове значення у файлі._
# --hints--
Створення об’єкта `hat` має додати правильний вміст.
```js
({
test: () => {
pyodide.FS.writeFile("/home/pyodide/probability_calculator.py", code);
pyodide.FS.writeFile(
"/home/pyodide/test_module.py",
`
import unittest
import probability_calculator
from importlib import reload
reload(probability_calculator)
probability_calculator.random.seed(95)
class UnitTests(unittest.TestCase):
maxDiff = None
def test_hat_class_contents(self):
hat = probability_calculator.Hat(red=3,blue=2)
actual = hat.contents
expected = ["red","red","red","blue","blue"]
self.assertEqual(actual, expected, 'Expected creation of hat object to add correct contents.')
`
);
const testCode = `
from unittest import main
import test_module
from importlib import reload
reload(test_module)
t = main(module='test_module', exit=False)
t.result.wasSuccessful()
`;
const out = __pyodide.runPython(testCode);
assert(out);
},
});
```
Метод `draw` у класі `hat` має зменшити кількість елементів у вмісті.
```js
({
test: () => {
pyodide.FS.writeFile("/home/pyodide/probability_calculator.py", code);
pyodide.FS.writeFile(
"/home/pyodide/test_module.py",
`
import unittest
import probability_calculator
from importlib import reload
reload(probability_calculator)
probability_calculator.random.seed(95)
def test_hat_draw(self):
hat = probability_calculator.Hat(red=5,blue=2)
actual = hat.draw(2)
expected = ['blue', 'red']
self.assertEqual(actual, expected, 'Expected hat draw to return two random items from hat contents.')
actual = len(hat.contents)
expected = 5
self.assertEqual(actual, expected, 'Expected hat draw to reduce number of items in contents.')
`
);
const testCode = `
from unittest import main
import test_module
from importlib import reload
reload(test_module)
t = main(module='test_module', exit=False)
t.result.wasSuccessful()
`;
const out = __pyodide.runPython(testCode);
assert(out);
},
});
```
Метод `experiment` має повернути іншу вірогідність.
```js
({
test: () => {
pyodide.FS.writeFile("/home/pyodide/probability_calculator.py", code);
pyodide.FS.writeFile(
"/home/pyodide/test_module.py",
`
import unittest
import probability_calculator
from importlib import reload
reload(probability_calculator)
probability_calculator.random.seed(95)
class UnitTests(unittest.TestCase):
maxDiff = None
def test_prob_experiment(self):
hat = probability_calculator.Hat(blue=3,red=2,green=6)
probability = probability_calculator.experiment(hat=hat, expected_balls={"blue":2,"green":1}, num_balls_drawn=4, num_experiments=1000)
actual = probability
expected = 0.272
self.assertAlmostEqual(actual, expected, delta = 0.01, msg = 'Expected experiment method to return a different probability.')
hat = probability_calculator.Hat(yellow=5,red=1,green=3,blue=9,test=1)
probability = probability_calculator.experiment(hat=hat, expected_balls={"yellow":2,"blue":3,"test":1}, num_balls_drawn=20, num_experiments=100)
actual = probability
expected = 1.0
self.assertAlmostEqual(actual, expected, delta = 0.01, msg = 'Expected experiment method to return a different probability.')
`
);
const testCode = `
from unittest import main
import test_module
from importlib import reload
reload(test_module)
t = main(module='test_module', exit=False)
t.result.wasSuccessful()
`;
const out = __pyodide.runPython(testCode);
assert(out);
},
});
```
# --seed--
## --seed-contents--
```py
import copy
import random
class Hat:
pass
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
pass
```
# --solutions--
```py
import copy
import random
class Hat:
def __init__(self, **hat):
self.hat = hat
contents = []
for i in hat:
for j in range(hat[i]):
contents.append(i)
self.contents = contents
def draw(self, number):
drawn = []
if number >= len(self.contents):
return self.contents
else:
for i in range(number):
drawn.append(
self.contents.pop(random.randrange(len(self.contents)))
)
return drawn
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
expected_balls_list = []
drawn_list = []
success = 0
for i in expected_balls:
for j in range(expected_balls[i]):
expected_balls_list.append(i)
for j in range(num_experiments):
hat_copy = copy.deepcopy(hat)
drawn_list.append(hat_copy.draw(num_balls_drawn))
exp_ball_list_copy = expected_balls_list[:]
for k in range(len(drawn_list[j])):
try:
ind = exp_ball_list_copy.index(drawn_list[j][k])
exp_ball_list_copy.pop(ind)
except:
continue
if len(exp_ball_list_copy) == 0:
success += 1
probability = success/num_experiments
return probability
```