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.
The test suite only generates ~100 names by default. There are ~700k valid names, so it will only give a small chance of collisions. Consider testing your solution for collisions in some other way in addition to the test suite.
This exercise continues our exploration of Julia's type system, this time with mutable types, and introduces us to random number generation.
We will imagine that resetting the robot to the factory settings is like a surgery: it makes changes to the subject, but doesn't replace it. We could also have modeled the problem such that resetting a robot creates a new robot, but not every problem can be modeled solely with immutable data structures (even purely functional languages deal with mutability inside their runtimes!).
In Julia, functions that mutate their arguments have a suffix ! by convention.
So our method for doing this will be called reset!.
This is only a convention, but almost all published Julia code follows it and you might come to agree that it's quite helpful!
You will need to define a method for generating unique names, a structure to describe robots, a method for resetting a robot, and a method for getting the name of a robot.
You might find it helpful to design your program first to just emit a random name for a robot (without worrying about collisions) and then later to think about and design a scheme that will avoid ever issuing duplicate names. In your design, be thoughtful about how the run time of name generation changes as names run out. What guarantees do you want to offer the caller?
A debugging session with Paul Blackwell at gSchool. http://gschool.it
This exercise has been tested on Julia versions >=1.0.
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
In [ ]:
# submit
mutable struct Robot
end
function reset!(instance::Robot)
end
function name(instance::Robot)
end
In [ ]:
using Test
import Random
# include("robot-name.jl")
# Random names means a risk of collisions.
const history = Set{String}()
isname(x) = occursin(r"^[A-Z]{2}[0-9]{3}$", x)
@testset "one robot" begin
global r1 = Robot()
push!(history, name(r1))
@testset "name of robot is valid" begin
@test isname(name(r1))
end
@testset "names of robot instance are valid and unique in history" begin
# @testset sets the same seed every time for reproducibility, but we're
# undoing that deliberately with Random.seed!() to increase the chance
# of seeing collisions.
Random.seed!()
for i in 1:100
reset!(r1)
@test isname(name(r1))
@test !in(name(r1), history)
push!(history, name(r1))
end
end
end
@testset "two robots" begin
global r2 = Robot()
global r3 = Robot()
@testset "names of robots are valid" begin
@test isname(name(r2))
@test isname(name(r3))
end
@testset "names of robots are not equal" begin
@test name(r2) != name(r3)
end
@testset "names of both robots are unique in history" begin
@test !in(name(r2), history)
@test !in(name(r3), history)
end
push!(history, name(r2))
push!(history, name(r3))
end
@testset "many robots" begin
Random.seed!()
robots = Robot[]
for i in 1:100
push!(robots, Robot())
@testset "name of robot is valid and unique in history" begin
@test isname(name(robots[i]))
@test !in(name(robots[i]), history)
end
push!(history, name(robots[i]))
end
@testset "fresh names of reset robots are valid and unique in history" begin
Random.seed!()
for r in robots
reset!(r)
@test isname(name(r))
@test !in(name(r), history)
push!(history, name(r))
end
end
end
In [ ]:
# using Pkg; Pkg.add("Exercism")
# using Exercism
# Exercism.create_submission("robot-name")