I used a mix of a bit of TDD, a lot of REPL-driven development (RDD) following this cycle:
- Write a failing test (using examples that a bit more complicated than the typical ones you use when doing only TDD).
- Explore and triangulate on the REPL until I made the test pass with some ugly but complete solution.
- Refactor the code to make it more readable.
These are the tests I wrote using Midje:
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
(ns scrabble-sets.core-test | |
(:require | |
[midje.sweet :refer :all] | |
[scrabble-sets.core :as scrabble])) | |
(facts | |
"about scrabble" | |
(fact | |
"it shows the tiles that are left in the bag | |
in descending order of the quantity of each tile left. | |
In cases where more than one letter has the same quantity remaining, | |
those letters appear in alphabetical order, with blank tiles at the end" | |
(fact | |
"when no tiles are in play" | |
(scrabble/tiles-left | |
"") => (str "12: E\n" | |
"9: A, I\n" | |
"8: O\n" | |
"6: N, R, T\n" | |
"4: D, L, S, U\n" | |
"3: G\n" | |
"2: B, C, F, H, M, P, V, W, Y, _\n" | |
"1: J, K, Q, X, Z"))) | |
(fact | |
"when some tiles are in play" | |
(scrabble/tiles-left | |
"PQAREIOURSTHGWIOAE_") => (str "10: E\n" | |
"7: A, I\n" | |
"6: N, O\n" | |
"5: T\n" | |
"4: D, L, R\n" | |
"3: S, U\n" | |
"2: B, C, F, G, M, V, Y\n" | |
"1: H, J, K, P, W, X, Z, _\n" | |
"0: Q") | |
(scrabble/tiles-left | |
"LQTOONOEFFJZT") => (str "11: E\n" | |
"9: A, I\n" | |
"6: R\n" | |
"5: N, O\n" | |
"4: D, S, T, U\n" | |
"3: G, L\n" | |
"2: B, C, H, M, P, V, W, Y, _\n" | |
"1: K, X\n" | |
"0: F, J, Q, Z")) | |
(fact | |
"when trying to put in play too many tiles of some kind" | |
(scrabble/tiles-left | |
"AXHDRUIOR_XHJZUQEE") | |
=> "Invalid input. More X's have been taken from the bag than possible.")) |
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
(ns scrabble-sets.core | |
(:require | |
[clojure.string :as string])) | |
(def ^:private tiles-in-bag | |
{"E" 12 "A" 9 "I" 9 "O" 8 "N" 6 "R" 6 "T" 6 | |
"L" 4 "S" 4 "U" 4 "D" 4 "G" 3 "_" 2 "B" 2 | |
"C" 2 "M" 2 "P" 2 "F" 2 "H" 2 "V" 2 "W" 2 | |
"Y" 2 "K" 1 "J" 1 "X" 1 "Q" 1 "Z" 1}) | |
(def ^:private group-by-frequency | |
(partial group-by second)) | |
(defn- format-tile [[freq tiles]] | |
(str freq ": " (string/join ", " (map str tiles)))) | |
(defn- format-tiles [sorted-tiles] | |
(->> sorted-tiles | |
(map format-tile) | |
(string/join "\n"))) | |
(defn- sort-by-frequency [tiles-in-bag] | |
(map (fn [[freq & [tiles]]] | |
[freq (sort (map first tiles))]) | |
(sort-by key > (group-by-frequency tiles-in-bag)))) | |
(defn- consume-tile [tiles-in-bag tile-in-play] | |
(update tiles-in-bag tile-in-play dec)) | |
(defn- consume [tiles-in-play tiles-in-bag] | |
(reduce consume-tile tiles-in-bag tiles-in-play)) | |
(defn- format-error-message [consumed-tiles] | |
(str "Invalid input. More " | |
(string/join ", " (map first consumed-tiles)) | |
"'s have been taken from the bag than possible.")) | |
(defn- display-distribution [tiles-in-bag] | |
(let [overconsumed-tiles (filter #(neg? (second %)) tiles-in-bag)] | |
(if (empty? overconsumed-tiles) | |
(format-tiles (sort-by-frequency tiles-in-bag)) | |
(format-error-message overconsumed-tiles)))) | |
(defn tiles-left [tiles-in-play] | |
(->> tiles-in-bag | |
(consume (map str tiles-in-play)) | |
display-distribution)) |
You can find all the code on GitHub.
No comments:
Post a Comment