Avatar of 4d47
0
0
Genius
0
1

4d47's solution

to Robot Name in the Clojure Track

Instructions
Test suite
Solution

Manage robot factory settings.

When robots come off the factory floor, they have no name.

The first time you boot them up, 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 their name gets wiped. The next time you ask, it will respond with a new random name.

The names must be random: they should not follow a predictable sequence. Random names means a risk of collisions. Your solution must ensure that every existing robot has a unique name.

Source

A debugging session with Paul Blackwell at gSchool. http://gschool.it

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

robot_name_test.clj

(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)]
    (testing "robot-name"
      (is (re-seq #"[A-Z]{2}\d{3}" its-name)
          "name matches expected pattern")
      (is (= its-name (robot-name/robot-name a-robot))
          "name doesn't change until you reset it")
      (is (not= its-name (-> (robot-name/robot) robot-name/robot-name))
          "different robots have different names"))))

(deftest reset-name
  (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))]

    (testing "reset-name"
      (is (re-seq #"[A-Z]{2}\d{3}" its-new-name)
          "new name matches expected pattern")
      (is (not= its-original-name its-new-name)
          "new name is different from old name")
      (is (= its-new-name (robot-name/robot-name a-robot))
          "new name doesn't change until you reset it")
      (is (not= its-new-name (do (robot-name/reset-name a-robot)
                                 (robot-name/robot-name a-robot)))
          "new names are different each time"))))
(ns robot-name)

(defn- char-range [start end]
  (map char (range (int start) (inc (int end)))))

(defn- gen-name []
  (apply str
         (concat
           (take 2 (repeatedly #(rand-nth (char-range \A \Z))))
           (take 3 (repeatedly #(rand-nth (char-range \0 \9)))))))

(defn reset-name [r]
  (swap! r #(assoc % :name (gen-name))))

(defn robot-name [r]
  (:name @r))

(defn robot []
  (reset-name (atom {})))

What can you learn from this solution?

A huge amount can be learnt from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

  • What compromises have been made?
  • Are there new concepts here that I could read more about to develop my understanding?

Community comments

See what others have said about this solution
4 months ago
4d47 says

Change from Ref to Atom, (don't think I need the data to be shared) but frankly still confused about the Var vs Ref vs Agent vs Atom. Need more reading I guess.