Skip to content

Commit

Permalink
Robot simulator (#178)
Browse files Browse the repository at this point in the history
* Add robot-simulator

* use fold

* create
  • Loading branch information
keiravillekode authored Aug 2, 2024
1 parent 031e0aa commit 999c9d3
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,14 @@
"prerequisites": [],
"difficulty": 4
},
{
"slug": "robot-simulator",
"name": "Robot Simulator",
"uuid": "5faa4ded-1358-4310-84b6-ad3a8d4f03ea",
"practices": [],
"prerequisites": [],
"difficulty": 4
},
{
"slug": "pythagorean-triplet",
"name": "Pythagorean Triplet",
Expand Down
25 changes: 25 additions & 0 deletions exercises/practice/robot-simulator/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -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.
18 changes: 18 additions & 0 deletions exercises/practice/robot-simulator/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"authors": [
"keiravillekode"
],
"files": {
"solution": [
"src/RobotSimulator.idr"
],
"test": [
"test/src/Main.idr"
],
"example": [
"example/RobotSimulator.idr"
]
},
"blurb": "Write a robot simulator.",
"source": "Inspired by an interview question at a famous company."
}
64 changes: 64 additions & 0 deletions exercises/practice/robot-simulator/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -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"
42 changes: 42 additions & 0 deletions exercises/practice/robot-simulator/example/RobotSimulator.idr
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module RobotSimulator

import Data.Vect

public export
data Direction = North | East | South | West

public export
data Instruction = R | L | A

public export
record Robot where
constructor MkRobot
direction : Direction
coordinates : Vect 2 Integer

public export
create : Direction -> Integer -> Integer -> Robot
create direction x y = MkRobot direction [x, y]

public export
move : Robot -> List Instruction -> Robot
move = foldl movement
where movement : Robot -> Instruction -> Robot
movement (MkRobot direction coordinates) R = MkRobot (right direction) coordinates
where right : Direction -> Direction
right North = East
right East = South
right South = West
right West = North
movement (MkRobot direction coordinates) L = MkRobot (left direction) coordinates
where left : Direction -> Direction
left North = West
left East = North
left South = East
left West = South
movement (MkRobot direction coordinates) A = MkRobot direction (advance direction coordinates)
where advance : Direction -> Vect 2 Integer -> Vect 2 Integer
advance North [x, y] = [x, y + 1]
advance East [x, y] = [x + 1, y]
advance South [x, y] = [x, y - 1]
advance West [x, y] = [x - 1, y]
10 changes: 10 additions & 0 deletions exercises/practice/robot-simulator/pack.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[custom.all.robot-simulator]
type = "local"
path = "."
ipkg = "robot-simulator.ipkg"
test = "test/test.ipkg"

[custom.all.robot-simulator-test]
type = "local"
path = "test"
ipkg = "test.ipkg"
3 changes: 3 additions & 0 deletions exercises/practice/robot-simulator/robot-simulator.ipkg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package robot-simulator
modules = RobotSimulator
sourcedir = "src"
23 changes: 23 additions & 0 deletions exercises/practice/robot-simulator/src/RobotSimulator.idr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module RobotSimulator

import Data.Vect

public export
data Direction = North | East | South | West

public export
data Instruction = R | L | A

public export
record Robot where
constructor MkRobot
direction : Direction
coordinates : Vect 2 Integer

public export
create : Direction -> Integer -> Integer -> Robot
create direction x y = ?create_rhs

public export
move : Robot -> List Instruction -> Robot
move robot instructions = ?move_rhs
61 changes: 61 additions & 0 deletions exercises/practice/robot-simulator/test/src/Main.idr
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
module Main

import System
import Tester
import Tester.Runner

import RobotSimulator
import Data.Vect

public export
implementation Eq Direction where
(==) North North = True
(==) East East = True
(==) South South = True
(==) West West = True
(==) _ _ = False

public export
implementation Show Direction where
show North = "North"
show East = "East"
show South = "South"
show West = "West"

public export
implementation Eq Robot where
(==) (MkRobot d1 c1) (MkRobot d2 c2) = (d1 == d2) && (c1 == c2)

public export
implementation Show Robot where
show (MkRobot direction coordinates) = "MkRobot " ++ (show direction) ++ " " ++ (show coordinates)

tests : List Test
tests =
[ test "at origin facing north" (assertEq (create North 0 0) (MkRobot North [0, 0]))
, test "at negative position facing south" (assertEq (create South (-1) (-1)) (MkRobot South [-1, -1]))
, test "changes north to east" (assertEq (move (MkRobot North [0, 0]) [R]) (MkRobot East [0, 0]))
, test "changes east to south" (assertEq (move (MkRobot East [0, 0]) [R]) (MkRobot South [0, 0]))
, test "changes south to west" (assertEq (move (MkRobot South [0, 0]) [R]) (MkRobot West [0, 0]))
, test "changes west to north" (assertEq (move (MkRobot West [0, 0]) [R]) (MkRobot North [0, 0]))
, test "changes north to west" (assertEq (move (MkRobot North [0, 0]) [L]) (MkRobot West [0, 0]))
, test "changes west to south" (assertEq (move (MkRobot West [0, 0]) [L]) (MkRobot South [0, 0]))
, test "changes south to east" (assertEq (move (MkRobot South [0, 0]) [L]) (MkRobot East [0, 0]))
, test "changes east to north" (assertEq (move (MkRobot East [0, 0]) [L]) (MkRobot North [0, 0]))
, test "facing north increments Y" (assertEq (move (MkRobot North [0, 0]) [A]) (MkRobot North [0, 1]))
, test "facing south decrements Y" (assertEq (move (MkRobot South [0, 0]) [A]) (MkRobot South [0, -1]))
, test "facing east increments X" (assertEq (move (MkRobot East [0, 0]) [A]) (MkRobot East [1, 0]))
, test "facing west decrements X" (assertEq (move (MkRobot West [0, 0]) [A]) (MkRobot West [-1, 0]))
, test "moving east and north from README" (assertEq (move (MkRobot North [7, 3]) [R, A, A, L, A, L]) (MkRobot West [9, 4]))
, test "moving west and north" (assertEq (move (MkRobot North [0, 0]) [L, A, A, A, R, A, L, A]) (MkRobot West [-4, 1]))
, test "moving west and south" (assertEq (move (MkRobot East [2, -7]) [R, R, A, A, A, A, A, L, A]) (MkRobot South [-3, -8]))
, test "moving east and north" (assertEq (move (MkRobot South [8, 4]) [L, A, A, A, R, R, R, A, L, L, L, L]) (MkRobot North [11, 5]))
]

export
main : IO ()
main = do
success <- runTests tests
if success
then putStrLn "All tests passed"
else exitFailure
6 changes: 6 additions & 0 deletions exercises/practice/robot-simulator/test/test.ipkg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package robot-simulator-test
depends = robot-simulator
, tester
main = Main
executable = "robot-simulator-test"
sourcedir = "src"
53 changes: 53 additions & 0 deletions generators/exercises/robot_simulator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@

HEADER = """import Data.Vect
public export
implementation Eq Direction where
(==) North North = True
(==) East East = True
(==) South South = True
(==) West West = True
(==) _ _ = False
public export
implementation Show Direction where
show North = "North"
show East = "East"
show South = "South"
show West = "West"
public export
implementation Eq Robot where
(==) (MkRobot d1 c1) (MkRobot d2 c2) = (d1 == d2) && (c1 == c2)
public export
implementation Show Robot where
show (MkRobot direction coordinates) = "MkRobot " ++ (show direction) ++ " " ++ (show coordinates)
"""

def header():
return HEADER

def generate_test(case):
def to_robot(data):
direction = data["direction"].title()
x = data["position"]["x"]
y = data["position"]["y"]
return f'(MkRobot {direction} [{x}, {y}])'

property = case["property"]
expected = to_robot(case["expected"])
if property == 'create':
direction = case["input"]["direction"].title()
x = case["input"]["position"]["x"]
if x < 0:
x = f'({x})'
y = case["input"]["position"]["y"]
if y < 0:
y = f'({y})'
return f'assertEq (create {direction} {x} {y}) {expected}'

robot = to_robot(case["input"])
instructions = case["input"]["instructions"]
instructions = str(list(instructions)).replace("'", "")
return f'assertEq ({property} {robot} {instructions}) {expected}'

0 comments on commit 999c9d3

Please sign in to comment.