Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README39
-rw-r--r--rush_hour.py (renamed from x.py)82
-rw-r--r--setup.cfg2
-rw-r--r--tests/test_sample.doctest23
4 files changed, 143 insertions, 3 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..340cddc
--- /dev/null
+++ b/README
@@ -0,0 +1,39 @@
+rush_hour
+=========
+
+A Python module to solve the Rush Hour game efficiently. It has no external
+dependencies and should work with both Python 2 and Python 3.
+
+See the module documentation (pydoc rush_hour) for details on the API.
+
+
+Running tests
+-------------
+
+There is a basic testset included in the module which is based on doctests.
+The easiest way to run the tests is with the nosetests (or nosetests3)
+command.
+
+
+Copyright
+---------
+
+Copyright (C) 2016 Arthur de Jong
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/x.py b/rush_hour.py
index e82a04e..582213c 100644
--- a/x.py
+++ b/rush_hour.py
@@ -1,3 +1,72 @@
+# rush_hour.py - Module for solving Rush Hour game
+# coding: utf-8
+#
+# Copyright (C) 2016 Arthur de Jong
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+"""Solve Rush Hour puzzle.
+
+This module provides solutions to the Rush Hour game. The module expects the
+board to be input as a list of rows with each cell either being empty
+(denoted by a period (.)) or contain a car (denoted by letters). The letter r
+represents the red car.
+
+The goal of the game is to move cars (only back and forth) so that the red
+car can be moved to the right of the board.
+
+The find_solutions will generate a number of solutions, the shortest
+solutions first.
+
+>>> solution = next(find_solutions([
+... '....AA',
+... '..BBCC',
+... 'rr..EF',
+... 'GGHHEF',
+... '...IEF',
+... '...IJJ']))
+
+A solution consists of a list of moves from the initial board. Each move
+consists of a description of the move (e.g. AL2 indicates that car A will be
+moved 2 spaces to the left) and a new board configuration.
+
+>>> solution[0][0]
+'AL2'
+>>> print('\\n'.join(solution[0][1]))
+..AA..
+..BBCC
+rr..EF
+GGHHEF
+...IEF
+...IJJ
+>>> ','.join(move for move, board in solution)
+'AL2,BL2,CL2,EU2,FU2,HR2,IU1,JL3,ID1,HL2,ED3,FD3,rR4'
+>>> print('\\n'.join(solution[-1][1]))
+..AA..
+BBCC..
+....rr
+GGHHEF
+...IEF
+.JJIEF
+
+"""
def clean_board(board):
@@ -58,10 +127,18 @@ def possible_row_moves(row):
def transpose_board(board):
+ """Turn horizontal rows will be turned into vertical columns."""
return tuple(''.join(x) for x in zip(*board))
def transpose_move(move):
+ """Tanslate horizontal move strings into vertical moves.
+
+ >>> transpose_move('AR2')
+ 'AD2'
+ >>> transpose_move('OL3')
+ 'OU3'
+ """
if move[1] == 'L':
return move[:1] + 'U' + move[2:]
else:
@@ -85,7 +162,8 @@ def possible_moves(board):
for move, newrow in possible_row_moves(board[row]):
yield (
transpose_move(move),
- transpose_board(board[:row] + tuple([newrow]) + board[row + 1:]))
+ transpose_board(
+ board[:row] + tuple([newrow]) + board[row + 1:]))
def is_solution(board):
@@ -95,6 +173,8 @@ def is_solution(board):
def find_solutions(board):
+ """Find solutions to the board. This function will return the shortest
+ found solutions first."""
board = clean_board(board)
visited = set([board])
queue = []
diff --git a/setup.cfg b/setup.cfg
index d44989c..335f266 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -4,7 +4,7 @@ doctest-extension=doctest
doctest-options=+IGNORE_EXCEPTION_DETAIL
with-coverage=true
cover-branches=true
-cover-package=x
+cover-package=rush_hour
cover-erase=true
cover-html=true
cover-html-dir=coverage
diff --git a/tests/test_sample.doctest b/tests/test_sample.doctest
index 5ab8910..350aac7 100644
--- a/tests/test_sample.doctest
+++ b/tests/test_sample.doctest
@@ -1,6 +1,27 @@
test_sample.doctest - simple test for rush hour solution finder
->>> from x import find_solutions
+Copyright (C) 2016 Arthur de Jong
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+>>> from rush_hour import find_solutions
>>> def get_moves(board):