diff --git a/config.json b/config.json index 3c3f4df4..fda1b406 100644 --- a/config.json +++ b/config.json @@ -765,6 +765,14 @@ "practices": [], "prerequisites": [], "difficulty": 1 + }, + { + "slug": "robot-name", + "name": "Robot Name", + "uuid": "54eb5f14-2b7c-4201-b38d-a25ce2cdae97", + "practices": [], + "prerequisites": [], + "difficulty": 1 } ], "foregone": [ diff --git a/exercises/practice/robot-name/.docs/hints.md b/exercises/practice/robot-name/.docs/hints.md new file mode 100644 index 00000000..64b0ebcb --- /dev/null +++ b/exercises/practice/robot-name/.docs/hints.md @@ -0,0 +1,8 @@ +# Hints + +## General + +- Use the [setarg] predicate to mutate data. +- The [setarg] predicate uses **1-based indexing**, so the first element is at index 1. + +[setarg]: https://www.swi-prolog.org/pldoc/doc_for?object=setarg/3 diff --git a/exercises/practice/robot-name/.docs/instructions.append.md b/exercises/practice/robot-name/.docs/instructions.append.md new file mode 100644 index 00000000..38c37dbc --- /dev/null +++ b/exercises/practice/robot-name/.docs/instructions.append.md @@ -0,0 +1,9 @@ +# Instructions append + +## Mutable data in Prolog + +By default, values in Prolog are _immutable_, which means that values never change (you'll have to introduce a new variable for each new value). +While this is great for the vast majority of use cases, this exercise _does_ require mutating values. +To mutate data in Prolog, you can use the [setarg] predicate. + +[setarg]: https://www.swi-prolog.org/pldoc/doc_for?object=setarg/3 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..46a0315b --- /dev/null +++ b/exercises/practice/robot-name/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "robot_name.pl" + ], + "test": [ + "robot_name_tests.plt" + ], + "example": [ + ".meta/robot_name.example.pl" + ] + }, + "blurb": "Manage robot factory settings.", + "source": "A debugging session with Paul Blackwell at gSchool." +} diff --git a/exercises/practice/robot-name/.meta/robot_name.example.pl b/exercises/practice/robot-name/.meta/robot_name.example.pl new file mode 100644 index 00000000..fe067317 --- /dev/null +++ b/exercises/practice/robot-name/.meta/robot_name.example.pl @@ -0,0 +1,19 @@ +letters(Letters) :- string_chars("ABCDEFGHIJKLMNOPQRSTUVWXZY", Letters). +digits(Digits) :- string_chars("0123456789", Digits). + +generate_name(Name) :- + letters(Letters), + digits(Digits), + random_member(L1, Letters), random_member(L2, Letters), + random_member(D1, Digits), random_member(D2, Digits), random_member(D3, Digits), + string_chars(Name, [L1,L2,D1,D2,D3]). + +create_robot(Robot) :- + generate_name(Name), + Robot = robot(Name). + +robot_name(robot(Name), Name). + +reset_name(Robot) :- + generate_name(Name), + setarg(1, Robot, Name). diff --git a/exercises/practice/robot-name/robot_name.pl b/exercises/practice/robot-name/robot_name.pl new file mode 100644 index 00000000..35b4df09 --- /dev/null +++ b/exercises/practice/robot-name/robot_name.pl @@ -0,0 +1,3 @@ +create_robot(Robot). +robot_name(Robot, Name). +reset_name(Robot). diff --git a/exercises/practice/robot-name/robot_name_tests.plt b/exercises/practice/robot-name/robot_name_tests.plt new file mode 100644 index 00000000..1e0a7b63 --- /dev/null +++ b/exercises/practice/robot-name/robot_name_tests.plt @@ -0,0 +1,41 @@ +pending :- + current_prolog_flag(argv, ['--all'|_]). +pending :- + write('\nA TEST IS PENDING!\n'), + fail. + +:- begin_tests(robot_name). + + test(has_name, condition(true)) :- + create_robot(Robot), + robot_name(Robot, Name), + string_concat(Letters, Digits, Name), + string_length(Letters, 2), + string_length(Digits, 3), + string_chars(Letters, LettersChars), + string_chars(Digits, DigitsChars), + maplist([C]>>char_type(C, upper), LettersChars), + maplist([C]>>char_type(C, digit), DigitsChars), + !. + + test(name_sticks, condition(pending)) :- + create_robot(Robot), + robot_name(Robot, Name1), + robot_name(Robot, Name2), + Name1 == Name2. + + test(different_robots_have_different_names, condition(pending)) :- + create_robot(Robot1), + create_robot(Robot2), + robot_name(Robot1, Name1), + robot_name(Robot2, Name2), + Name1 \== Name2. + + test(reset_name, condition(pending)) :- + create_robot(Robot), + robot_name(Robot, Name1), + reset_name(Robot), + robot_name(Robot, Name2), + Name1 \== Name2. + +:- end_tests(robot_name).