summaryrefslogtreecommitdiff
path: root/oo.py
diff options
context:
space:
mode:
authorJoe Anderson <jandew+dev@gmail.com>2016-02-24 10:11:14 -0800
committerJoe Anderson <jandew+dev@gmail.com>2016-02-24 10:11:14 -0800
commit90fbd75a8943ebbfc9bee05db2cebb1d21793be0 (patch)
treee003462e5160cdedde34e87c6ed5e3be662bd1e7 /oo.py
parent6127f0006336e2de2a3082069acedf63226ea6a0 (diff)
downloadoo-90fbd75a8943ebbfc9bee05db2cebb1d21793be0.tar.gz
oo-90fbd75a8943ebbfc9bee05db2cebb1d21793be0.zip
add edges into ooPuzzle, create set_data methods
Diffstat (limited to 'oo.py')
-rw-r--r--oo.py146
1 files changed, 103 insertions, 43 deletions
diff --git a/oo.py b/oo.py
index ebfceda..ae50189 100644
--- a/oo.py
+++ b/oo.py
@@ -19,8 +19,9 @@ class ooPuzzle:
get_edge_pair
INITIALIZATION
- set_pieces_from_game_id
- set_pieces_from_edges
+ set_data_from_game_id
+ set_data_from_edges
+ set_data_from_pieces
The following are all the user interface methods.
For more description, see their documentation.
@@ -65,6 +66,24 @@ class ooPuzzle:
if toroidal: in range(2**( 2*X*Y ))
if not toroidal: in range(2**( (X-1)*Y + X*(Y-1) ))
+ A solution is stored in vert_edges and horiz_edges knowing this:
+ Adjacent edges in a solution must be
+ either both filled or both unfilled,
+ and so a bit of data is assigned to each pair.
+
+ vert_edges is the dictionary for vertical pairs
+ key: (x, row)
+ x: the usual x-coordinate of the piece
+ row: the y-coordinate or y+1, depending on whether
+ you want the pair above or below the piece
+ : row == 0 and row == self.Y are border edges
+ so it's good to think of row as 1-indexed
+
+ horiz_edges is the dictionary for horizontal pairs
+ key: (col, y)
+ col: the x-coord or x+1, same as row but left or right
+ y: the usual y-coord
+
pieces is a dictionary mapping:
each position of form (x in range(self.X),
y in range(self.Y))
@@ -96,6 +115,8 @@ class ooPuzzle:
self.game_id = game_id
self.toroidal = toroidal
+ self.horiz_edges = {}
+ self.vert_edges = {}
self.pieces = {}
self.orients = {}
self.set_data_from_game_id(random_game_id = (game_id == None))
@@ -287,42 +308,86 @@ class ooPuzzle:
#
####
- def set_pieces_from_edges(self, horiz_edges, vert_edges):
- """Convert edge dictionaries into a puzzle state.
+ def set_data_from_edges(self, data='pieces and game_id'):
+ """Update pieces and/or game_id from edges.
- Adjacent edges in a solution must be
- either both filled or both unfilled,
- and so a bit of data is assigned to each pair.
-
- vert_edges is the dictionary for vertical pairs
- key: (x, row)
- x: the usual x-coordinate of the piece
- row: the y-coordinate or y+1, depending on whether
- you want the pair above or below the piece
- : row == 0 and row == self.Y are border edges
- so it's good to think of row as 1-indexed
+ data is an input in case you want to suppress calculation
+ It should be one of ['pieces', 'game_id', 'pieces and game_id']
+ """
+ if 'pieces' in data:
+
+ for x in range(self.X):
+ for y in range(self.Y):
+
+ left = self.horiz_edges[x , y]
+ right = self.horiz_edges[x+1, y]
+ up = self.vert_edges[x, y ]
+ down = self.vert_edges[x, y+1]
+
+ piece, orient = \
+ self.EDGES_TO_PIECE_ORIENT[left, up, right, down]
+
+ self.pieces [x, y] = piece
+ self.orients[x, y] = orient
+
+ if 'game_id' in data:
+
+ game_id = 0
+ exp = 0
+
+ # compute:
+ # n_horiz, the number of horizontal edge pairs
+ # n_vert, the number of vertical edge pairs
+
+ shift = -int(not self.toroidal)
+ n_col = self.X + shift
+ n_row = self.Y + shift
+ n_horiz = n_col * self.Y
+ n_vert = self.X * n_row
+
+ # get the edges determined by game_id
+
+ for i in range(n_vert):
+ row, x = divmod(i, self.X)
+ bit = self.vert_edges[x, row+1]
+ game_id += 2**exp * bit
+ exp += 1
+
+ for i in range(n_horiz):
+ col, y = divmod(i, self.Y)
+ bit = self.horiz_edges[col+1, y]
+ game_id += 2**exp * bit
+ exp += 1
+
+ self.game_id = game_id
+
+ def set_data_from_pieces(self):
+ """Update edges and game_id with current pieces.
- horiz_edges is the dictionary for horizontal pairs
- key: (col, y)
- col: the x-coord or x+1, same as row but left or right
- y: the usual y-coord
+ pieces must be in a solution state, i.e.,
+ self.is_solved() must return True
"""
- for x in range(self.X):
- for y in range(self.Y):
+ if not self.is_solved():
+ raise ValueError("puzzle is not in a solved state")
- left = horiz_edges[x , y]
- right = horiz_edges[x+1, y]
- up = vert_edges[x, y ]
- down = vert_edges[x, y+1]
+ for x, y in self.pieces:
- piece, orient = \
- self.EDGES_TO_PIECE_ORIENT[left, up, right, down]
- self.pieces [x, y] = piece
- self.orients[x, y] = orient
+ piece = self.pieces [x, y]
+ orient = self.orients[x, y]
- def set_pieces_from_game_id(self, random_game_id=False):
- """Convert game_id value into a solution puzzle state.
+ left, right, up, down = \
+ self.PIECE_ORIENT_TO_EDGES[piece, orient]
+ self.horiz_edges[x , y] = left
+ self.horiz_edges[x+1, y] = right
+ self.vert_edges[x, y ] = up
+ self.vert_edges[x, y+1] = down
+
+ set_data_from_edges(data='game_id')
+
+ def set_data_from_game_id(self, random_game_id=False):
+ """Update edges and pieces with current game_id.
+
if random_game_id,
then a random game_id is chosen from the appropriate range,
and pieces are set from that
@@ -343,19 +408,14 @@ class ooPuzzle:
if random_game_id:
self.game_id = random.randrange(0, 2**(n_horiz + n_vert))
- # prepare to record edges for self.set_pieces_from_edges
-
- vert_edges = {}
- horiz_edges = {}
-
# set the right and bottom border edges
# if toroidal, these will be overwritten in the next step
for x in range(self.X):
- vert_edges[x, self.Y] = 0
+ self.vert_edges[x, self.Y] = 0
for y in range(self.Y):
- horiz_edges[self.X, y] = 0
+ self.horiz_edges[self.X, y] = 0
# set the edges determined by game_id
@@ -364,24 +424,24 @@ class ooPuzzle:
for i in range(n_vert):
row, x = divmod(i, self.X)
game_id, bit = divmod(game_id, 2)
- vert_edges[x, row+1] = bit
+ self.vert_edges[x, row+1] = bit
for i in range(n_horiz):
col, y = divmod(i, self.Y)
game_id, bit = divmod(game_id, 2)
- horiz_edges[col+1, y] = bit
+ self.horiz_edges[col+1, y] = bit
# make the left and top border edges match the opposite sides
for y in range(self.Y):
- horiz_edges[0, y] = horiz_edges[self.X, y]
+ self.horiz_edges[0, y] = self.horiz_edges[self.X, y]
for x in range(self.X):
- vert_edges[x, 0] = vert_edges[x, self.Y]
+ self.vert_edges[x, 0] = self.vert_edges[x, self.Y]
# set the pieces from the edges
- self.set_pieces_from_edges(horiz_edges, vert_edges)
+ self.set_data_from_edges(data='pieces')
####
#