🎉 Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io 🎉
Avatar of SergiiVlasiuk

SergiiVlasiuk's solution

to Robot Name in the Scala Track

Published at Aug 31 2019 · 0 comments
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.

Hints

Make sure your solution is general enough to be easily scalable for longer names containing more letters and digits. This usually makes for better code quality, too.

Suggestion (this is not explicitly tested): To make sure you always have a unique name you could implement your own cache or use a Stream with its built-in cache.

The Scala exercises assume an SBT project scheme. The exercise solution source should be placed within the exercise directory/src/main/scala. The exercise unit tests can be found within the exercise directory/src/test/scala.

To run the tests simply run the command sbt test in the exercise directory.

For more detailed info about the Scala track see the help page.

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.

RobotNameTest.scala

import org.scalatest._

import collection.mutable

/** @version created manually **/
class RobotNameSpecs extends FunSpec with Matchers {
  val nameRegex = """[A-Z]{2}\d{3}"""

  it ("has a name") {
    new Robot().name should fullyMatch regex nameRegex
  }

  it ("does not change its name") {
    pending
    val robot = new Robot
    val name = robot.name
    robot.name should be (name)
  }

  it ("does not have the same name as other robots") {
    pending
    new Robot().name should not be new Robot().name
  }

  it ("can have its name reset") {
    pending
    val robot = new Robot
    val name = robot.name
    robot.reset()
    val name2 = robot.name
    name should not equal name2
    name2 should fullyMatch regex nameRegex
  }

  // Making this test pass is an optional extra exercise, should you want more of a challenge.
  // It's ignored by default, to make it run, simply change "ignore" below to "it".
  // There are 26^2 * 1,000 = 676,000 possible robot names - you have to ensure that none are repeated.
  // The Robot code needs to be efficient enough to allow all 676,000 unique names to be generated.
  ignore("a large number of new instances have unique names") {
    val alreadySet = mutable.HashSet.empty[String]
    for(_ <- 0 until 676000 - 6) { // as 6 robot names are generated in the tests above!!
      val name = new Robot().name
      if (alreadySet contains name) {
        fail(s"$name is repeated")
      }
      alreadySet += name
    }
  }
}
object Robot {
  private val iterator = Stream from(0) iterator
  private val first = 'A' toInt
  private val dif: Int = 'Z' - 'A' + 1

  private def handleDigits(plus: Int): String = (plus + 1000).toString takeRight 3

  private def handleChars(plus: Int): String = s"${(plus / dif + first).toChar}${(plus % dif + first).toChar}"

  def generateNext: String = {
    val next = iterator.next()
    s"${handleChars(next)}${handleDigits(next / 1000)}"
  }
}

import Robot.generateNext

class Robot {
  private var robotName: String = generateNext

  def name: String = robotName

  def reset(): Unit = robotName = generateNext
}

Community comments

Find this solution interesting? Ask the author a question to learn more.

What can you learn from this solution?

A huge amount can be learned 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 you could read more about to improve your understanding?