diff --git a/config.json b/config.json index b183ee9..67fe3fc 100644 --- a/config.json +++ b/config.json @@ -553,6 +553,14 @@ "prerequisites": [], "difficulty": 6 }, + { + "slug": "robot-simulator", + "name": "Robot Simulator", + "uuid": "6fc65865-1e9b-48d7-a2c6-6f50bea3b094", + "practices": [], + "prerequisites": [], + "difficulty": 6 + }, { "slug": "say", "name": "Say", diff --git a/exercises/practice/robot-simulator/.docs/instructions.md b/exercises/practice/robot-simulator/.docs/instructions.md new file mode 100644 index 0000000..0ac96ce --- /dev/null +++ b/exercises/practice/robot-simulator/.docs/instructions.md @@ -0,0 +1,25 @@ +# Instructions + +Write a robot simulator. + +A robot factory's test facility needs a program to verify robot movements. + +The robots have three possible movements: + +- turn right +- turn left +- advance + +Robots are placed on a hypothetical infinite grid, facing a particular direction (north, east, south, or west) at a set of {x,y} coordinates, +e.g., {3,8}, with coordinates increasing to the north and east. + +The robot then receives a number of instructions, at which point the testing facility verifies the robot's new position, and in which direction it is pointing. + +- The letter-string "RAALAL" means: + - Turn right + - Advance twice + - Turn left + - Advance once + - Turn left yet again +- Say a robot starts at {7, 3} facing north. + Then running this stream of instructions should leave it at {9, 4} facing west. diff --git a/exercises/practice/robot-simulator/.meta/config.json b/exercises/practice/robot-simulator/.meta/config.json new file mode 100644 index 0000000..4e4d0e9 --- /dev/null +++ b/exercises/practice/robot-simulator/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "robot_simulator.fut" + ], + "test": [ + "test.fut" + ], + "example": [ + ".meta/example.fut" + ] + }, + "blurb": "Write a robot simulator.", + "source": "Inspired by an interview question at a famous company." +} diff --git a/exercises/practice/robot-simulator/.meta/example.fut b/exercises/practice/robot-simulator/.meta/example.fut new file mode 100644 index 0000000..339143b --- /dev/null +++ b/exercises/practice/robot-simulator/.meta/example.fut @@ -0,0 +1,45 @@ +type position = (i32, i32) + +type direction = #north | #east | #south | #west + +type state = (position, direction) + +def right (s: state): state = + let x = s.0.0 + let y = s.0.1 + in + match (s.1) + case #north -> ((x, y), #east) + case #east -> ((x, y), #south) + case #south -> ((x, y), #west) + case #west -> ((x, y), #north) + +def left (s: state): state = + let x = s.0.0 + let y = s.0.1 + in + match (s.1) + case #north -> ((x, y), #west) + case #east -> ((x, y), #north) + case #south -> ((x, y), #east) + case #west -> ((x, y), #south) + +def advance (s: state): state = + let x = s.0.0 + let y = s.0.1 + in + match (s.1) + case #north -> ((x, y + 1), #north) + case #east -> ((x + 1, y), #east) + case #south -> ((x, y - 1), #south) + case #west -> ((x - 1, y), #west) + +def move (start: state) (instructions: []u8): state = + let s = loop s = start for instruction in instructions do + match (instruction) + case 'R' -> right s + case 'L' -> left s + case 'A' -> advance s + case _ -> assert false s + in + s diff --git a/exercises/practice/robot-simulator/.meta/tests.toml b/exercises/practice/robot-simulator/.meta/tests.toml new file mode 100644 index 0000000..16da03d --- /dev/null +++ b/exercises/practice/robot-simulator/.meta/tests.toml @@ -0,0 +1,64 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[c557c16d-26c1-4e06-827c-f6602cd0785c] +description = "Create robot -> at origin facing north" + +[bf0dffce-f11c-4cdb-8a5e-2c89d8a5a67d] +description = "Create robot -> at negative position facing south" + +[8cbd0086-6392-4680-b9b9-73cf491e67e5] +description = "Rotating clockwise -> changes north to east" + +[8abc87fc-eab2-4276-93b7-9c009e866ba1] +description = "Rotating clockwise -> changes east to south" + +[3cfe1b85-bbf2-4bae-b54d-d73e7e93617a] +description = "Rotating clockwise -> changes south to west" + +[5ea9fb99-3f2c-47bd-86f7-46b7d8c3c716] +description = "Rotating clockwise -> changes west to north" + +[fa0c40f5-6ba3-443d-a4b3-58cbd6cb8d63] +description = "Rotating counter-clockwise -> changes north to west" + +[da33d734-831f-445c-9907-d66d7d2a92e2] +description = "Rotating counter-clockwise -> changes west to south" + +[bd1ca4b9-4548-45f4-b32e-900fc7c19389] +description = "Rotating counter-clockwise -> changes south to east" + +[2de27b67-a25c-4b59-9883-bc03b1b55bba] +description = "Rotating counter-clockwise -> changes east to north" + +[f0dc2388-cddc-4f83-9bed-bcf46b8fc7b8] +description = "Moving forward one -> facing north increments Y" + +[2786cf80-5bbf-44b0-9503-a89a9c5789da] +description = "Moving forward one -> facing south decrements Y" + +[84bf3c8c-241f-434d-883d-69817dbd6a48] +description = "Moving forward one -> facing east increments X" + +[bb69c4a7-3bbf-4f64-b415-666fa72d7b04] +description = "Moving forward one -> facing west decrements X" + +[e34ac672-4ed4-4be3-a0b8-d9af259cbaa1] +description = "Follow series of instructions -> moving east and north from README" + +[f30e4955-4b47-4aa3-8b39-ae98cfbd515b] +description = "Follow series of instructions -> moving west and north" + +[3e466bf6-20ab-4d79-8b51-264165182fca] +description = "Follow series of instructions -> moving west and south" + +[41f0bb96-c617-4e6b-acff-a4b279d44514] +description = "Follow series of instructions -> moving east and north" diff --git a/exercises/practice/robot-simulator/robot_simulator.fut b/exercises/practice/robot-simulator/robot_simulator.fut new file mode 100644 index 0000000..1652d5e --- /dev/null +++ b/exercises/practice/robot-simulator/robot_simulator.fut @@ -0,0 +1,7 @@ +type position = (i32, i32) + +type direction = #north | #east | #south | #west + +type state = (position, direction) + +def move (start: state) (instructions: []u8): state = ??? diff --git a/exercises/practice/robot-simulator/test.fut b/exercises/practice/robot-simulator/test.fut new file mode 100644 index 0000000..1f17baf --- /dev/null +++ b/exercises/practice/robot-simulator/test.fut @@ -0,0 +1,111 @@ +import "robot_simulator" + +-- at origin facing north +-- == +-- input { 0 0 0 "" } +-- output { [0, 0, 0] } + +-- at negative position facing south +-- == +-- input { -1 -1 2 "" } +-- output { [-1, -1, 2] } + +-- changes north to east +-- == +-- input { 0 0 0 "R" } +-- output { [0, 0, 1] } + +-- changes east to south +-- == +-- input { 0 0 1 "R" } +-- output { [0, 0, 2] } + +-- changes south to west +-- == +-- input { 0 0 2 "R" } +-- output { [0, 0, 3] } + +-- changes west to north +-- == +-- input { 0 0 3 "R" } +-- output { [0, 0, 0] } + +-- changes north to west +-- == +-- input { 0 0 0 "L" } +-- output { [0, 0, 3] } + +-- changes west to south +-- == +-- input { 0 0 3 "L" } +-- output { [0, 0, 2] } + +-- changes south to east +-- == +-- input { 0 0 2 "L" } +-- output { [0, 0, 1] } + +-- changes east to north +-- == +-- input { 0 0 1 "L" } +-- output { [0, 0, 0] } + +-- facing north increments Y +-- == +-- input { 0 0 0 "A" } +-- output { [0, 1, 0] } + +-- facing south decrements Y +-- == +-- input { 0 0 2 "A" } +-- output { [0, -1, 2] } + +-- facing east increments X +-- == +-- input { 0 0 1 "A" } +-- output { [1, 0, 1] } + +-- facing west decrements X +-- == +-- input { 0 0 3 "A" } +-- output { [-1, 0, 3] } + +-- moving east and north from README +-- == +-- input { 7 3 0 "RAALAL" } +-- output { [9, 4, 3] } + +-- moving west and north +-- == +-- input { 0 0 0 "LAAARALA" } +-- output { [-4, 1, 3] } + +-- moving west and south +-- == +-- input { 2 -7 1 "RRAAAAALA" } +-- output { [-3, -8, 2] } + +-- moving east and north +-- == +-- input { 8 4 2 "LAAARRRALLLL" } +-- output { [11, 5, 0] } + +local def encode_direction (d: direction): i32 = + match (d) + case #north -> 0 + case #east -> 1 + case #south -> 2 + case #west -> 3 + +local def decode_direction (i: i32): direction = + match (i) + case 0 -> #north + case 1 -> #east + case 2 -> #south + case 3 -> #west + case _ -> assert false #north + +def main (x: i32) (y: i32) (direction: i32) (instructions: []u8): []i32 = + let result = move ((x, y), decode_direction direction) instructions + in + [result.0.0, result.0.1, encode_direction result.1] diff --git a/generators/exercises/robot_simulator.py b/generators/exercises/robot_simulator.py new file mode 100644 index 0000000..52d7e6a --- /dev/null +++ b/generators/exercises/robot_simulator.py @@ -0,0 +1,47 @@ +MAIN = """\ +local def encode_direction (d: direction): i32 = + match (d) + case #north -> 0 + case #east -> 1 + case #south -> 2 + case #west -> 3 + +local def decode_direction (i: i32): direction = + match (i) + case 0 -> #north + case 1 -> #east + case 2 -> #south + case 3 -> #west + case _ -> assert false #north + +def main (x: i32) (y: i32) (direction: i32) (instructions: []u8): []i32 = + let result = move ((x, y), decode_direction direction) instructions + in + [result.0.0, result.0.1, encode_direction result.1] +""" + + +DIRECTIONS = ["north", "east", "south", "west"] + + +def gen_test_case(prop, description, inp, expected, f): + in_x = inp["position"]["x"] + in_y = inp["position"]["y"] + in_d = DIRECTIONS.index(inp["direction"]) + if "instructions" in inp.keys(): + instructions = inp["instructions"] + else: + instructions = "" + + out_x = expected["position"]["x"] + out_y = expected["position"]["y"] + out_d = DIRECTIONS.index(expected["direction"]) + + f.write(f"-- {description}\n") + f.write("-- ==\n") + f.write(f'-- input {{ {in_x} {in_y} {in_d} "{instructions}" }}\n') + f.write(f"-- output {{ [{out_x}, {out_y}, {out_d}] }}\n\n") + + +def gen_main(f): + f.write(MAIN)