-
-
Notifications
You must be signed in to change notification settings - Fork 159
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Card Games exercise as WIP (#583)
* port instructions * create Clojure project * create Clojure project * test list of input vals * concat-rounds * contains-round * card-average * approx-average * average-even-odd * complete solution and tests * create stub and exemplar * add introduction * add exercise config * add card games to track config as wip * add hints, prerequisites * clean up code comments
- Loading branch information
1 parent
c6789a4
commit af8c5a9
Showing
10 changed files
with
363 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Hints | ||
|
||
## Tracking Poker Rounds | ||
|
||
- The [`list`][list] function returns a list consisting of the arguments it is passed. | ||
|
||
## Keeping all Rounds in the Same Place | ||
|
||
- The [`concat`][concat] function can be used to concatenate two lists together. | ||
|
||
## Finding Prior Rounds | ||
|
||
- The [`some`][some] function will return the first logically true value in a collection. | ||
- [`boolean`][boolean] is useful in cases where a function returns a value but the tests are expecting a boolean. | ||
|
||
## Averaging Card Values | ||
|
||
- Recall basic arithmetic operators such as [`/`][division] and [`+`][addition]. | ||
- A collection of numbers can be summed using either [`apply`][apply] or [`reduce`][reduce]. | ||
- The [`count`][count] function returns the number of items in a collection. | ||
- The `/` function returns a ratio type when operating on integers. You can use [`double`][double] to convert a ratio to a decimal. | ||
|
||
## Alternate Averages | ||
|
||
- There are sequence functions to return the [`first`][first] or [`last`] element of a sequential collection. | ||
- To find the middle card you can divide the number of cards by 2, round to the lowest integer with [`int`][int], and retrieve the card at that index using [`nth`][nth]. | ||
- Use [`or`][or] to determine if either condition is true. | ||
|
||
## More Averaging Techniques | ||
|
||
- One way of retrieving the cards at even/odd indices would be to [`map`][map] a function using [`nth`][nth] over a [`range`][range], which takes an optional `step` argument. | ||
|
||
## Bonus Round Rules | ||
|
||
- Recall how to use [`if`][if] from the exercise on conditionals. | ||
- You can return all items of a collection except for the last one using [`butlast`][butlast]. | ||
|
||
[addition]: https://clojuredocs.org/clojure.core/+ | ||
[apply]: https://clojuredocs.org/clojure.core/apply | ||
[boolean]: https://clojuredocs.org/clojure.core/boolean | ||
[butlast]: https://clojuredocs.org/clojure.core/butlast | ||
[concat]: https://clojuredocs.org/clojure.core/concat | ||
[count]: https://clojuredocs.org/clojure.core/count | ||
[division]: https://clojuredocs.org/clojure.core/_fs | ||
[double]: https://clojuredocs.org/clojure.core/double | ||
[first]: https://clojuredocs.org/clojure.core/first | ||
[if]: https://clojuredocs.org/clojure.core/if | ||
[int]: https://clojuredocs.org/clojure.core/int | ||
[last]: https://clojuredocs.org/clojure.core/last | ||
[list]: https://clojuredocs.org/clojure.core/list | ||
[map]: https://clojuredocs.org/clojure.core/map | ||
[nth]: https://clojuredocs.org/clojure.core/nth | ||
[or]: https://clojuredocs.org/clojure.core/or | ||
[range]: https://clojuredocs.org/clojure.core/range | ||
[reduce]: https://clojuredocs.org/clojure.core/reduce | ||
[some]: https://clojuredocs.org/clojure.core/some |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# Instructions | ||
|
||
Elyse is really looking forward to playing some poker (and other card games) during her upcoming trip to Vegas. | ||
Being a big fan of "self-tracking" she wants to put together some small functions that will help her with tracking tasks and has asked for your help thinking them through. | ||
|
||
## 1. Tracking Poker Rounds | ||
|
||
Elyse is especially fond of poker, and wants to track how many rounds she plays - and _which rounds_ those are. | ||
Every round has its own number, and every table shows the round number currently being played. | ||
Elyse chooses a table and sits down to play her first round. She plans on playing three rounds. | ||
|
||
Implement a function `rounds` that takes the current round number and returns a single `list` with that round and the _next two_ that are coming up: | ||
|
||
```clojure | ||
(rounds 27) | ||
;;=> (27 28 29) | ||
``` | ||
|
||
## 2. Keeping all Rounds in the Same Place | ||
|
||
Elyse played a few rounds at the first table, then took a break and played some more rounds at a second table ... but ended up with a different list for each table! | ||
She wants to put the two lists together, so she can track all of the poker rounds in the same place. | ||
|
||
Implement a function `concat-rounds` that takes two lists and returns a single `list` consisting of all the rounds in the first `list`, followed by all the rounds in the second `list`: | ||
|
||
```clojure | ||
(concat-rounds '(27 28 29) '(35 36)) | ||
;;=> (27 28 29 35 36) | ||
``` | ||
|
||
## 3. Finding Prior Rounds | ||
|
||
Talking about some of the prior Poker rounds, another player remarks how similarly two of them played out. | ||
Elyse is not sure if she played those rounds or not. | ||
|
||
Implement a function `contains-round?` that takes two arguments, a list of rounds played and a round number. | ||
The function will return `true` if the round is in the list of rounds played, `false` if not: | ||
|
||
```clojure | ||
(contains-round? '(27 28 29 35 36) 29) | ||
;;=> true | ||
|
||
(contains-round? '(27 28 29 35 36) 30) | ||
;;=> false | ||
``` | ||
|
||
## 4. Averaging Card Values | ||
|
||
Elyse wants to try out a new game called Black Joe. | ||
It's similar to Black Jack - where your goal is to have the cards in your hand add up to a target value - but in Black Joe the goal is to get the _average_ of the card values to be 7. | ||
The average can be found by summing up all the card values and then dividing that sum by the number of cards in the hand. | ||
|
||
Implement a function `card-average` that will return the average value of a hand of Black Joe. | ||
|
||
```clojure | ||
(card-average '(5 6 7)) | ||
;;=> 6.0 | ||
``` | ||
|
||
## 5. Alternate Averages | ||
|
||
In Black Joe, speed is important. Elyse is going to try and find a faster way of finding the average. | ||
|
||
She has thought of two ways of getting an _average-like_ number: | ||
|
||
- Take the average of the _first_ and _last_ number in the hand. | ||
- Using the median (middle card) of the hand. | ||
|
||
Implement the function `approx-average?`, given `hand`, a list containing the values of the cards in your hand. | ||
|
||
Return `true` if either _one_ `or` _both_ of the, above named, strategies result in a number _equal_ to the _actual average_. | ||
|
||
Note: _The length of all hands are odd, to make finding a median easier._ | ||
|
||
```clojure | ||
(approx-average? '(1 2 3)) | ||
;;=> true | ||
|
||
(approx-average? '(2 3 4 8 8)) | ||
;;=> true | ||
|
||
(approx-average? '(1 2 3 5 9)) | ||
;;=> false | ||
``` | ||
|
||
## 6. More Averaging Techniques | ||
|
||
Intrigued by the results of her averaging experiment, Elyse is wondering if taking the average of the cards at the _even_ positions versus the average of the cards at the _odd_ positions would give the same results. | ||
Time for another test function! | ||
|
||
Implement a function `average-even-odd?` that returns a Boolean indicating if the average of the cards at even indexes is the same as the average of the cards at odd indexes. | ||
|
||
```clojure | ||
(average-even-odd? '(1 2 3)) | ||
;;=> true | ||
|
||
(average-even-odd? '(1 2 3 4)) | ||
;;=> false | ||
``` | ||
|
||
## 7. Bonus Round Rules | ||
|
||
Every 11th hand in Black Joe is a bonus hand with a bonus rule: if the last card you draw is a Jack, you double its value. | ||
|
||
Implement a function `maybe-double-last` that takes a hand and checks if the last card is a Jack (11). | ||
If the last card **is** a Jack (11), double its value before returning the hand. | ||
|
||
```clojure | ||
(maybe-double-last '(5 9 11)) | ||
;;=> '(5 9 22) | ||
|
||
(maybe-double-last '(5 9 10)) | ||
;;=> '(5 9 10) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Introduction | ||
|
||
In Clojure, Lists are [collections][type-collection], just as like [lists in other languages][type-list]. Similar to other languages in the Lisp family, Clojure uses parentheses to express lists. | ||
|
||
Clojure lists can be created in one of two ways. The `list` function can create a list, or you can `quote` a literal list. | ||
|
||
Lists are special because Clojure will treat them as _calls_. It expects the call to start with an _operator_, which is usually a function. The remaining items of the list are considered _operands_, meaning they become the function's arguments. | ||
|
||
Clojure's special treatment of lists is why we cannot create a list literal directly. Quoting a list using `quote` or its shorthand `'` indicates that the list should not be evaluated. | ||
|
||
Unlike some modern languages, Clojure lists are _heterogeneous_, meaning they can contain multiple types of items internally e.g., `'(2 "a" "b" 3)`. | ||
Unlike other Lisps, an empty list in Clojure is truthy and is not equivalent to `nil` or `false`. | ||
|
||
[type-list]: https://github.com/exercism/v3/blob/main/reference/types/list.md | ||
[type-collection]: https://github.com/exercism/v3/blob/main/reference/types/collection.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"authors": [ | ||
"bobbicodes" | ||
], | ||
"forked_from": [ | ||
"python/card-games" | ||
], | ||
"files": { | ||
"solution": [ | ||
"src/card_games.clj" | ||
], | ||
"test": [ | ||
"test/card_games_test.clj" | ||
], | ||
"exemplar": [ | ||
".meta/exemplar.clj" | ||
] | ||
}, | ||
"icon": "poker", | ||
"blurb": "Learn about lists by tracking hands in card games." | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
(ns card-games) | ||
|
||
(defn rounds | ||
"Takes the current round number and returns | ||
a `list` with that round and the _next two_." | ||
[n] | ||
(list n (inc n) (+ n 2))) | ||
|
||
(defn concat-rounds | ||
"Takes two lists and returns a single `list` | ||
consisting of all the rounds in the first `list`, | ||
followed by all the rounds in the second `list`" | ||
[l1 l2] | ||
(concat l1 l2)) | ||
|
||
(defn contains-round? | ||
"Takes a list of rounds played and a round number. | ||
Returns `true` if the round is in the list, `false` if not." | ||
[l n] | ||
(boolean (some #{n} l))) | ||
|
||
(defn card-average | ||
"Returns the average value of a hand" | ||
[hand] | ||
(double (/ (apply + hand) (count hand)))) | ||
|
||
(defn approx-average? | ||
"Returns `true` if average is equal to either one of: | ||
- Take the average of the _first_ and _last_ number in the hand. | ||
- Using the median (middle card) of the hand." | ||
[hand] | ||
(or (= (card-average hand) (double (/ (+ (first hand) (last hand)) 2))) | ||
(= (card-average hand) (double (nth hand (int (/ (count hand) 2.0))))))) | ||
|
||
(defn average-even-odd? | ||
"Returns true if the average of the cards at even indexes | ||
is the same as the average of the cards at odd indexes." | ||
[hand] | ||
(let [evens (map #(nth hand %) (range 1 (count hand) 2)) | ||
odds (map #(nth hand %) (range 0 (count hand) 2))] | ||
(= (double (/ (apply + evens) (count evens))) | ||
(double (/ (apply + odds) (count odds)))))) | ||
|
||
(defn maybe-double-last | ||
"If the last card is a Jack (11), doubles its value | ||
before returning the hand." | ||
[hand] | ||
(if (= 11 (last hand)) | ||
(concat (butlast hand) '(22)) | ||
hand)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{:aliases {:test {:extra-paths ["test"] | ||
:extra-deps {io.github.cognitect-labs/test-runner | ||
{:git/url "https://github.com/cognitect-labs/test-runner.git" | ||
:sha "705ad25bbf0228b1c38d0244a36001c2987d7337"}} | ||
:main-opts ["-m" "cognitect.test-runner"] | ||
:exec-fn cognitect.test-runner.api/test}}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
(defproject bird-watcher "0.1.0-SNAPSHOT" | ||
:description "card-games exercise." | ||
:url "https://github.com/exercism/clojure/tree/main/exercises/concept/card-games" | ||
:dependencies [[org.clojure/clojure "1.11.1"]]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
(ns card-games) | ||
|
||
(defn rounds | ||
"Takes the current round number and returns | ||
a `list` with that round and the _next two_." | ||
[n] | ||
) | ||
|
||
(defn concat-rounds | ||
"Takes two lists and returns a single `list` | ||
consisting of all the rounds in the first `list`, | ||
followed by all the rounds in the second `list`" | ||
[l1 l2] | ||
) | ||
|
||
(defn contains-round? | ||
"Takes a list of rounds played and a round number. | ||
Returns `true` if the round is in the list, `false` if not." | ||
[l n] | ||
) | ||
|
||
(defn card-average | ||
"Returns the average value of a hand" | ||
[hand] | ||
) | ||
|
||
(defn approx-average? | ||
"Returns `true` if average is equal to either one of: | ||
- Take the average of the _first_ and _last_ number in the hand. | ||
- Using the median (middle card) of the hand." | ||
[hand] | ||
) | ||
|
||
(defn average-even-odd? | ||
"Returns true if the average of the cards at even indexes | ||
is the same as the average of the cards at odd indexes." | ||
[hand] | ||
) | ||
|
||
(defn maybe-double-last | ||
"If the last card is a Jack (11), doubles its value | ||
before returning the hand." | ||
[hand] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
(ns card-games-test | ||
(:require [clojure.test :refer [deftest is testing]] | ||
card-games)) | ||
|
||
(deftest rounds-test | ||
(is (= '((0 1 2) (1 2 3) (10 11 12) | ||
(27 28 29) (99 100 101) (666 667 668)) | ||
(map card-games/rounds '(0 1 10 27 99 666))))) | ||
|
||
(deftest concat-rounds-test | ||
(is (= '(() (0 1) (1 2) (1 2) | ||
(27 28 29 35 36) | ||
(1 2 3 4 5 6)) | ||
(map #(apply card-games/concat-rounds %) | ||
'((() ()) ((0 1) ()) (() (1 2)) | ||
((1) (2)) ((27 28 29) (35 36)) | ||
((1 2 3) (4 5 6))))))) | ||
|
||
(deftest contains-round-test | ||
(is (= '(false false false true true true) | ||
(map #(apply card-games/contains-round? %) | ||
'(([], 1), ([1, 2, 3], 0), ([27, 28, 29, 35, 36], 30), | ||
([1], 1), ([1, 2, 3], 1), ([27, 28, 29, 35, 36], 29)))))) | ||
|
||
(deftest card-average-test | ||
(is (= '(1.0 6.0 2.5 37.0) | ||
(map card-games/card-average '((1) (5 6 7) (1 2 3 4) (1 10 100)))))) | ||
|
||
(deftest approx-average-test | ||
(is (= '(false false false false true true true true) | ||
(map card-games/approx-average? | ||
'((0 1 5) (3 6 9 12 150) (1 2 3 5 9) | ||
(2 3 4 7 8) (1 2 3) (2 3 4) | ||
(2 3 4 8 8) (1 2 4 5 8)))))) | ||
|
||
(deftest average-even-odd-test | ||
(is (= '(false false true true true) | ||
(map card-games/average-even-odd? | ||
'((5 6 8) (1 2 3 4) (1 2 3) (5 6 7) (1 3 5 7 9)))))) | ||
|
||
(deftest maybe-double-last-test | ||
(is (= '((1 2 22) (5 9 22) (5 9 10) (1 2 3)) | ||
(map card-games/maybe-double-last | ||
'((1 2 11) (5 9 11) (5 9 10) (1 2 3)))))) |