From a99f789c810afb286b256dd0d6cfdb7e8f9c04ca Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Sat, 6 May 2023 13:59:27 +0200 Subject: [PATCH] Add robot-name exercise --- config.json | 15 +++++- .../practice/robot-name/.docs/instructions.md | 14 ++++++ .../practice/robot-name/.meta/config.json | 18 +++++++ .../robot-name/.meta/src/example.cljs | 15 ++++++ exercises/practice/robot-name/deps.edn | 10 ++++ .../practice/robot-name/src/robot_name.cljs | 13 +++++ .../robot-name/test/robot_name_test.cljs | 47 +++++++++++++++++++ 7 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 exercises/practice/robot-name/.docs/instructions.md create mode 100644 exercises/practice/robot-name/.meta/config.json create mode 100644 exercises/practice/robot-name/.meta/src/example.cljs create mode 100644 exercises/practice/robot-name/deps.edn create mode 100644 exercises/practice/robot-name/src/robot_name.cljs create mode 100644 exercises/practice/robot-name/test/robot_name_test.cljs diff --git a/config.json b/config.json index caf434f7..6b212b93 100644 --- a/config.json +++ b/config.json @@ -341,7 +341,7 @@ "uuid": "c895c0f5-0fe5-4ce1-a3a9-b6cd911d9275", "practices": [], "prerequisites": [ - "lists", + "lists", "numbers", "strings" ], @@ -394,7 +394,7 @@ ], "difficulty": 2 }, - { + { "slug": "acronym", "name": "Acronym", "uuid": "e6147a0d-3000-4b3c-9a60-3f8800730691", @@ -584,6 +584,17 @@ "conditionals" ], "difficulty": 2 + }, + { + "slug": "robot-name", + "name": "Robot Name", + "uuid": "33c4d67c-8365-41d2-9a3e-c41bbf0dd131", + "practices": [], + "prerequisites": [ + "numbers", + "strings" + ], + "difficulty": 2 } ] }, diff --git a/exercises/practice/robot-name/.docs/instructions.md b/exercises/practice/robot-name/.docs/instructions.md new file mode 100644 index 00000000..fca3a41a --- /dev/null +++ b/exercises/practice/robot-name/.docs/instructions.md @@ -0,0 +1,14 @@ +# Instructions + +Manage robot factory settings. + +When a robot comes off the factory floor, it has no name. + +The first time you turn on a robot, a random name is generated in the format of two uppercase letters followed by three digits, such as RX837 or BC811. + +Every once in a while we need to reset a robot to its factory settings, which means that its name gets wiped. +The next time you ask, that robot will respond with a new random name. + +The names must be random: they should not follow a predictable sequence. +Using random names means a risk of collisions. +Your solution must ensure that every existing robot has a unique name. diff --git a/exercises/practice/robot-name/.meta/config.json b/exercises/practice/robot-name/.meta/config.json new file mode 100644 index 00000000..09cf9eae --- /dev/null +++ b/exercises/practice/robot-name/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "ErikSchierboom" + ], + "files": { + "solution": [ + "src/robot_name.cljs" + ], + "test": [ + "test/robot_name_test.cljs" + ], + "example": [ + ".meta/src/example.cljs" + ] + }, + "blurb": "Manage robot factory settings.", + "source": "A debugging session with Paul Blackwell at gSchool." +} diff --git a/exercises/practice/robot-name/.meta/src/example.cljs b/exercises/practice/robot-name/.meta/src/example.cljs new file mode 100644 index 00000000..32b61fb4 --- /dev/null +++ b/exercises/practice/robot-name/.meta/src/example.cljs @@ -0,0 +1,15 @@ +(ns robot-name) + +(def ^:private letters (map char (range 65 91))) +(defn- generate-name [] + (format "%s%03d" (apply str (repeatedly 2 #(rand-nth letters))) + (rand-int 1000))) + +(defn robot [] + (atom {:name (generate-name)})) + +(defn robot-name [robot] + (:name @robot)) + +(defn reset-name [robot] + (swap! robot assoc :name (generate-name))) diff --git a/exercises/practice/robot-name/deps.edn b/exercises/practice/robot-name/deps.edn new file mode 100644 index 00000000..5c65da55 --- /dev/null +++ b/exercises/practice/robot-name/deps.edn @@ -0,0 +1,10 @@ +{:deps + {org.clojure/clojure {:mvn/version "1.10.1"} + org.clojure/clojurescript {:mvn/version "1.10.773"}} + + :aliases + {:test + {:extra-paths ["test"] + :extra-deps + {olical/cljs-test-runner {:mvn/version "3.8.0"}} + :main-opts ["-m" "cljs-test-runner.main"]}}} diff --git a/exercises/practice/robot-name/src/robot_name.cljs b/exercises/practice/robot-name/src/robot_name.cljs new file mode 100644 index 00000000..c98554a6 --- /dev/null +++ b/exercises/practice/robot-name/src/robot_name.cljs @@ -0,0 +1,13 @@ +(ns robot-name) + +(defn robot [] ;; <- arglist goes here + ;; your code goes here +) + +(defn robot-name [robot] ;; <- arglist goes here + ;; your code goes here +) + +(defn reset-name [robot] ;; <- arglist goes here + ;; your code goes here +) diff --git a/exercises/practice/robot-name/test/robot_name_test.cljs b/exercises/practice/robot-name/test/robot_name_test.cljs new file mode 100644 index 00000000..addeb272 --- /dev/null +++ b/exercises/practice/robot-name/test/robot_name_test.cljs @@ -0,0 +1,47 @@ +(ns robot-name-test + (:require [clojure.test :refer [deftest is testing]] + robot-name)) + +(deftest robot-name + (let [a-robot (robot-name/robot) + its-name (robot-name/robot-name a-robot)] + (is (re-seq #"[A-Z]{2}\d{3}" its-name)))) + +(deftest name-matches-pattern + (let [a-robot (robot-name/robot) + its-name (robot-name/robot-name a-robot)] + (is (= its-name (robot-name/robot-name a-robot))))) + +(deftest different-robots-different-names + (let [a-robot (robot-name/robot) + its-name (robot-name/robot-name a-robot)] + (is (not= its-name (-> (robot-name/robot) robot-name/robot-name))))) + +(deftest new-name-matches + (let [a-robot (robot-name/robot) + its-original-name (robot-name/robot-name a-robot) + its-new-name (do (robot-name/reset-name a-robot) + (robot-name/robot-name a-robot))] + (is (re-seq #"[A-Z]{2}\d{3}" its-new-name)))) + +(deftest new-name-different + (let [a-robot (robot-name/robot) + its-original-name (robot-name/robot-name a-robot) + its-new-name (do (robot-name/reset-name a-robot) + (robot-name/robot-name a-robot))] + (is (not= its-original-name its-new-name)))) + +(deftest new-name-does-not-change-until-reset + (let [a-robot (robot-name/robot) + its-original-name (robot-name/robot-name a-robot) + its-new-name (do (robot-name/reset-name a-robot) + (robot-name/robot-name a-robot))] + (is (= its-new-name (robot-name/robot-name a-robot))))) + +(deftest new-names-different-each-time + (let [a-robot (robot-name/robot) + its-original-name (robot-name/robot-name a-robot) + its-new-name (do (robot-name/reset-name a-robot) + (robot-name/robot-name a-robot))] + (is (not= its-new-name (do (robot-name/reset-name a-robot) + (robot-name/robot-name a-robot))))))