Coverage for rover/rover.py : 100%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from dataclasses import dataclass, field
2from typing import Tuple
5@dataclass(frozen=True)
6class Coordinates:
7 x: int
8 y: int
9 left: str
10 right: str
13@dataclass
14class Rover:
15 x: int
16 y: int
17 direction: str
18 obstacles: list[list[int]] = field(default_factory=list)
20 valid_commands = ("F", "B", "R", "L")
22 direction_map = {
23 "NORTH": Coordinates(0, 1, "WEST", "EAST"),
24 "EAST": Coordinates(1, 0, "NORTH", "SOUTH"),
25 "SOUTH": Coordinates(0, -1, "EAST", "WEST"),
26 "WEST": Coordinates(-1, 0, "SOUTH", "NORTH"),
27 }
29 def is_valid_command(self, command: str) -> bool:
30 for ch in command:
31 if ch not in self.valid_commands:
32 return False
34 return True
36 def is_obstacle(self, x: int, y: int) -> bool:
37 return [x, y] in self.obstacles
39 def move(self, command: str):
40 if not self.is_valid_command(command):
41 raise ValueError("invalid command. The rover does not move")
43 for ch in command:
44 x, y, direction = self._compute_new_coordinates(ch)
45 if obstacle := self.is_obstacle(x, y):
46 return self._new_coordinates_output(obstacle)
48 self._apply_new_coordinates(x, y, direction)
50 return self._new_coordinates_output()
52 def _new_coordinates_output(self, obstacle: bool = False):
53 if obstacle:
54 return self.x, self.y, self.direction, "STOPPED"
55 return self.x, self.y, self.direction
57 def _compute_new_coordinates(self, command) -> Tuple[int, int, str]:
58 x = self.x
59 y = self.y
60 direction = self.direction
62 if command == "B":
63 x -= self.direction_map[self.direction].x
64 y -= self.direction_map[self.direction].y
65 if command == "F":
66 x += self.direction_map[self.direction].x
67 y += self.direction_map[self.direction].y
68 if command == "R":
69 direction = self.direction_map[self.direction].right
70 if command == "L":
71 direction = self.direction_map[self.direction].left
73 return x, y, direction
75 def _apply_new_coordinates(self, x, y, direction) -> None:
76 self.x = x
77 self.y = y
78 self.direction = direction