A squad of robotic rovers are to be landed by NASA on a plateau on Mars. This
plateau, which is flat and curiously rectangular, must be navigated by the
rovers so that their on-board cameras can get a complete view of the surrounding
terrain to send back to Earth. A rover's position and location are represented
by a combination of x and y co-ordinates and a letter representing one of the
four cardinal compass directions. The plateau is divided up into a grid to
simplify navigation. An example position might be 0, 0, N, which means the rover
is in the bottom left corner and facing North. In order to control a rover, NASA
sends a simple string of letters. The possible letters are L
, R
and M
. L
and R
makes the rover spin 90 degrees left or right respectively, without
moving from its current spot. 'M' means move forward one grid point, and
maintain the same heading. Assume that the square directly North from (x, y)
is (x, y+1)
.
The first line of input is the upper-right coordinates of the plateau, the
lower-left coordinates are assumed to be 0, 0
. The rest of the input is
information pertaining to the rovers that have been deployed. Each rover has two
lines of input. The first line gives the rover's position, and the second line
is a series of instructions telling the rover how to explore the plateau. The
position is made up of two integers and a letter separated by spaces,
corresponding to the x and y co-ordinates and the rover's orientation. Each
rover will be finished sequentially, which means that the second rover won't
start to move until the first one has finished moving. The output for each rover
should be its final co-ordinates and heading.
Consider the following test input:
5 5
1 2 N
LMLMLMLMM
3 3 E
MMRMMRMRRM
Here is the expected output:
1 3 N
5 1 E
If the program find a rover out of bounds, it will abort.
- Python 3.8+
argparse
CLI option parsingre
regular expressionsdataclass
less verbose classes
- Optional Dependencies (for Development and Testing)
-
Pytest
Running test.
-
Coverage
Checking coverage of tests
-
IPython
Better interactive shell
-
Pdb++
Drop in replacement for
pdb
, specially useful when debugging testspy.test --pdb
-
Github Actions
- A Continuous Integration pipeline has been set up to run the tests in Python 3.8, 3.9 and 3.10 here. It also creates Python wheels under the artifact tabs.
- A separate pipeline builds a Docker image that contains the python program as entrypoint
-
The project can be run with Python 3.8 and above. It doesn't require any external library. Running the tests and packing it as a Python wheel require poetry.
This method doesn't require to install anything, just run make run
. It will run the code
in interactive mode. Note that given the limitations of passing arguments to make
the file mode
is not supported.
Once installed though pip, the script mars_rover
should be available in your path.
This program can either run interactively -i
or passing a file as input -I
.
The wheel for pip installation is available in Github artifacts. Please note that this is not PyPI and requires unzipping the file first, and the download is available only for 90 days. Alternatively a Docker image has been published to Github Container Registry.
# Running the command without arguments shows the usage
usage: Mars Rover [-h] [-I INPUT_FILE] [-i] [-l LOG_LEVEL]
This software simulates the movements of a Mars Rover based on L(eft), R(ight) andM(ove forward) text characters. It
simulates the rovers sequentially. Use Ctrl+D to finalize the input.
optional arguments:
-h, --help show this help message and exit
-I INPUT_FILE, --input-file INPUT_FILE
-i, --stdin Read input from stdin
-l LOG_LEVEL, --log-level LOG_LEVEL
Set the logging level
Note that an end of file is expected at the end, use Ctrl+E
in Unix based OSs to produce it
$ mars_rover -i
10 10
5 5 N
MRMLMMRL
6 8 N
mars_rover -I src/tests/case_01/input.txt
Note that this approach requires some interactive shell like IPython
Install the Python wheel, and run it from the terminal as follows:
from mars_rover.entities import Plateau, Rover
p = Plateau(5, 5)
r = Rover((1, 1), "N")
r.simulate("LLMRM", p)
print(r)
Python wheels are the newest standard for Python distribution. Although this project is not published in Python official package index PyPI, the CI pipeline produces wheels as artifacts. To grab the latest build
- Go to Github Actions for the project here
- Locate the zip compressed wheel at the bottom of the page.
- Download the file and unzip it.
- Install it with
python -m pip install path/to/mars_rover-0.1.0-py3-none-any.whl
If Docker is available in your environment, this repository automatically pushes a docker image to Github Container Registry.
To run the program inside docker -t
(tty allocation) and -i
(interactive) flags must be provided.
docker run --rm -ti ghcr.io/d3f0/mars_rover:latest -i
The program uses argparse
to parse command line invocations. It works with streams,
or file-like objects as input, so there's no interaction.
The input parsing is done with the re
library for regular expressions. When an occurs
the shorthand sys.exit()
is used to inform the user what went wrong.