Треки
/
Clojure
Clojure
/
Вправи
/
Карткові ігри
Карткові ігри

Карткові ігри

Навчальна вправа

Вступ

У Clojure списки є колекціями, так само як і списки в інших мовах. Як і в інших мовах сімейства Lisp, Clojure використовує дужки для запису списків.

Списки в Clojure можна створити одним із двох способів. Функція list створює список, або ж список-літерал можна зацитувати за допомогою quote.

Списки особливі тим, що Clojure трактує їх як виклики. Виклик має починатися з оператора, який зазвичай є функцією. Решту елементів списку вважають операндами, тобто вони стають аргументами функції.

Саме через особливе ставлення Clojure до списків ми не можемо створити список-літерал безпосередньо. Цитування списку за допомогою quote або його скороченого запису ' означає, що список не слід обчислювати.

На відміну від деяких сучасних мов, списки в Clojure гетерогенні, тобто можуть містити елементи різних типів, наприклад '(2 "a" "b" 3). На відміну від інших діалектів Lisp, порожній список у Clojure є правдивим і не дорівнює nil або false.

Вказівки

Еліз дуже хоче пограти в покер (та інші карткові ігри) під час своєї майбутньої поїздки до Вегаса. Будучи великою прихильницею «самовідстеження», вона хоче створити кілька невеликих функцій, які допоможуть їй із завданнями відстеження, і просить нас допомогти все це обміркувати.

1. Відстеження раундів у покері

Еліз особливо любить покер і хоче відстежувати, скільки раундів вона грає, і які саме раунди. Кожен раунд має свій номер, і кожен стіл показує номер раунду, який грають зараз. Еліз обирає стіл і сідає грати свій перший раунд. Вона планує зіграти три раунди.

Реалізуйте функцію rounds, яка приймає номер поточного раунду й повертає один list із цим раундом і двома наступними:

(rounds 27)
;;=> (27 28 29)

2. Зберігання всіх раундів в одному місці

Еліз зіграла кілька раундів за першим столом, потім зробила перерву й зіграла ще кілька раундів за другим столом... але в підсумку отримала окремий масив для кожного столу! Вона хоче поєднати ці два масиви, щоб відстежувати всі раунди покеру в одному місці.

Реалізуйте функцію concat-rounds, яка приймає два масиви й повертає один list, що складається з усіх раундів із першого list, а далі з усіх раундів із другого list:

(concat-rounds '(27 28 29) '(35 36))
;;=> (27 28 29 35 36)

3. Пошук попередніх раундів

Коли мова заходить про деякі попередні раунди покеру, інший гравець зауважує, як схоже минули два з них. Еліз не певна, чи грала вона ті раунди.

Реалізуйте функцію contains-round?, яка приймає два аргументи: масив зіграних раундів і номер раунду. Функція поверне true, якщо раунд є в масиві зіграних раундів, і false, якщо ні:

(contains-round? '(27 28 29 35 36) 29)
;;=> true

(contains-round? '(27 28 29 35 36) 30)
;;=> false

4. Усереднення значень карт

Еліз хоче спробувати нову гру під назвою «Блек Джо». Вона схожа на блекджек, де наша мета - щоб карти в руці в сумі давали цільове значення, але в «Блек Джо» мета - щоб середнє значень карт дорівнювало 7. Середнє можна знайти, додавши всі значення карт, а потім поділивши цю суму на кількість карт у руці.

Реалізуйте функцію card-average, яка повертає середнє значення карт у руці в «Блек Джо».

(card-average '(5 6 7))
;;=> 6.0

5. Альтернативні способи усереднення

У «Блек Джо» важлива швидкість. Еліз спробує знайти швидший спосіб обчислити середнє.

Вона придумала два способи отримати число, схоже на середнє:

  • Узяти середнє першого й останнього числа в руці.
  • Скористатися медіаною (середньою картою) в руці.

Реалізуйте функцію approx-average?, яка приймає hand, масив зі значеннями карт у руці.

Поверніть true, якщо одна or обидві зі згаданих вище стратегій дають число, рівне фактичному середньому.

Примітка: Довжина всіх рук непарна, щоб легше було знайти медіану.

(approx-average? '(1 2 3))
;;=> true

(approx-average? '(2 3 4 8 8))
;;=> true

(approx-average? '(1 2 3 5 9))
;;=> false

6. Більше технік усереднення

Зацікавлена результатами свого експерименту з усередненням, Еліз думає, чи дадуть однаковий результат середнє карт на парних позиціях і середнє карт на непарних позиціях. Час для ще однієї тестової функції!

Реалізуйте функцію average-even-odd?, яка повертає булеве значення (англ. Boolean), що вказує, чи середнє карт на парних індексах дорівнює середньому карт на непарних індексах.

(average-even-odd? '(1 2 3))
;;=> true

(average-even-odd? '(1 2 3 4))
;;=> false

7. Правила бонусного раунду

Кожна 11-та рука в «Блек Джо» - бонусна рука з бонусним правилом: якщо остання карта, яку ми беремо, - валет, ми подвоюємо її значення.

Реалізуйте функцію maybe-double-last, яка приймає руку й перевіряє, чи остання карта - валет (11). Якщо остання карта є валетом (11), подвойте її значення перед поверненням руки.

(maybe-double-last '(5 9 11))
;;=> '(5 9 22)

(maybe-double-last '(5 9 10))
;;=> '(5 9 10)
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Clojure Exercism

Час розпочати Карткові ігри?

Зареєструйтеся на Exercism, щоб вивчати й опановувати Clojure, а також 12 концепцій105 вправ та справжнє наставництво від людей, і все це безкоштовно.