Slash grid problem.
This commit is contained in:
parent
fba727783c
commit
cbc0427bc4
222
dotfiles/lib/python/slash_grid.py
Executable file
222
dotfiles/lib/python/slash_grid.py
Executable file
@ -0,0 +1,222 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
class SlashGrid(object):
|
||||||
|
|
||||||
|
def __init__(self, slash_array):
|
||||||
|
self.slash_array = slash_array
|
||||||
|
self.nodes = [
|
||||||
|
[Node(row_index, column_index, self) for column_index, value in enumerate(row)]
|
||||||
|
for row_index, row in enumerate(slash_array)
|
||||||
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def width(self):
|
||||||
|
return len(self.nodes[0])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def height(self):
|
||||||
|
return len(self.nodes)
|
||||||
|
|
||||||
|
def run(self, in_between_searches=lambda x: x):
|
||||||
|
count = 0
|
||||||
|
for node_row in self.nodes:
|
||||||
|
for node in node_row:
|
||||||
|
if not node.top_visited:
|
||||||
|
in_between_searches(self)
|
||||||
|
count += 1
|
||||||
|
node.search('top', tag=count)
|
||||||
|
if not node.bottom_visited:
|
||||||
|
in_between_searches(self)
|
||||||
|
count += 1
|
||||||
|
node.search('bottom', tag=count)
|
||||||
|
in_between_searches(self)
|
||||||
|
return count
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '\n'.join(self.grid_row_string(row) for row in self.nodes)
|
||||||
|
|
||||||
|
def grid_row_string(self, row):
|
||||||
|
node_strings = [
|
||||||
|
node.string_lines for node in row
|
||||||
|
]
|
||||||
|
return '\n'.join(''.join(string_collection) for string_collection in zip(*node_strings))
|
||||||
|
|
||||||
|
|
||||||
|
class OutOfBoundsError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Node(object):
|
||||||
|
|
||||||
|
_right_top = ('right', 'top')
|
||||||
|
_right_bottom = ('right', 'bottom')
|
||||||
|
_left_top = ('left', 'top')
|
||||||
|
_left_bottom = ('left', 'bottom')
|
||||||
|
|
||||||
|
_directions_map = {
|
||||||
|
True: (_left_top, _right_bottom),
|
||||||
|
False: (_left_bottom, _right_top)
|
||||||
|
}
|
||||||
|
|
||||||
|
_opposites = {
|
||||||
|
'left': 'right',
|
||||||
|
'right': 'left',
|
||||||
|
'top': 'bottom',
|
||||||
|
'bottom': 'top'
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, row_index, column_index, grid):
|
||||||
|
self.row_index = row_index
|
||||||
|
self.column_index = column_index
|
||||||
|
self.grid = grid
|
||||||
|
self.top_visited = False
|
||||||
|
self.bottom_visited = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def string_lines(self):
|
||||||
|
if self.forward:
|
||||||
|
return [''.join([self.string_for_visited(self.top_visited), '/']),
|
||||||
|
''.join(['/', self.string_for_visited(self.bottom_visited)])]
|
||||||
|
else:
|
||||||
|
return [''.join(['\\', self.string_for_visited(self.top_visited)]),
|
||||||
|
''.join([self.string_for_visited(self.bottom_visited), '\\'])]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def string_for_visited(visited):
|
||||||
|
if visited is True:
|
||||||
|
return 'X'
|
||||||
|
elif visited is False:
|
||||||
|
return ' '
|
||||||
|
else:
|
||||||
|
string = str(visited)
|
||||||
|
if isinstance(visited, int):
|
||||||
|
return chr(65 + visited)
|
||||||
|
if len(string) > 1:
|
||||||
|
return '`'
|
||||||
|
else:
|
||||||
|
return string
|
||||||
|
|
||||||
|
@property
|
||||||
|
def forward(self):
|
||||||
|
return self.grid.slash_array[self.row_index][self.column_index]
|
||||||
|
|
||||||
|
def directions_from(self, edge):
|
||||||
|
for direction_pair in self._directions_map[self.forward]:
|
||||||
|
if edge in direction_pair:
|
||||||
|
return direction_pair
|
||||||
|
else:
|
||||||
|
raise Exception()
|
||||||
|
|
||||||
|
def opposite(self, edge):
|
||||||
|
return self._opposites[edge]
|
||||||
|
|
||||||
|
def edge_visited(self, edge):
|
||||||
|
return getattr(self, self.edge_visited_string(edge))
|
||||||
|
|
||||||
|
def edge_visited_string(self, edge):
|
||||||
|
return '{0}_visited'.format(edge)
|
||||||
|
|
||||||
|
def visit_edge(self, edge, tag):
|
||||||
|
was_unvisited = not self.edge_visited(edge)
|
||||||
|
if was_unvisited:
|
||||||
|
setattr(self, self.edge_visited_string(edge), tag)
|
||||||
|
return was_unvisited
|
||||||
|
|
||||||
|
def search(self, edge, tag=True):
|
||||||
|
was_unvisited = self.visit_edge(edge, tag)
|
||||||
|
if not was_unvisited:
|
||||||
|
return
|
||||||
|
directions = self.directions_from(edge)
|
||||||
|
for travel_edge in directions:
|
||||||
|
try:
|
||||||
|
getattr(self, travel_edge).search(self.opposite(travel_edge), tag=tag)
|
||||||
|
except OutOfBoundsError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def left_visited(self):
|
||||||
|
if self.forward:
|
||||||
|
return self.top_visited
|
||||||
|
else:
|
||||||
|
return self.bottom_visited
|
||||||
|
|
||||||
|
@property
|
||||||
|
def right_visited(self):
|
||||||
|
if self.forward:
|
||||||
|
return self.bottom_visited
|
||||||
|
else:
|
||||||
|
return self.top_visited
|
||||||
|
|
||||||
|
@right_visited.setter
|
||||||
|
def right_visited(self, value):
|
||||||
|
if self.forward:
|
||||||
|
self.bottom_visited = value
|
||||||
|
else:
|
||||||
|
self.top_visited = value
|
||||||
|
|
||||||
|
|
||||||
|
@left_visited.setter
|
||||||
|
def left_visited(self, value):
|
||||||
|
if self.forward:
|
||||||
|
self.top_visited = value
|
||||||
|
else:
|
||||||
|
self.bottom_visited = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def left(self):
|
||||||
|
if self.column_index <= 0:
|
||||||
|
raise OutOfBoundsError()
|
||||||
|
return self.grid.nodes[self.row_index][self.column_index-1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def right(self):
|
||||||
|
if self.column_index > self.grid.width - 2:
|
||||||
|
raise OutOfBoundsError()
|
||||||
|
return self.grid.nodes[self.row_index][self.column_index + 1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def top(self):
|
||||||
|
if self.row_index <= 0:
|
||||||
|
raise OutOfBoundsError()
|
||||||
|
return self.grid.nodes[self.row_index - 1][self.column_index]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bottom(self):
|
||||||
|
if self.row_index > self.grid.height-2:
|
||||||
|
raise OutOfBoundsError()
|
||||||
|
return self.grid.nodes[self.row_index + 1][self.column_index]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
def print_grid(grid):
|
||||||
|
print "X"*100
|
||||||
|
print grid
|
||||||
|
|
||||||
|
def square(size, in_between_searches=lambda x: x):
|
||||||
|
import random
|
||||||
|
sg = SlashGrid([[bool(random.randint(0, 1)) for _ in range(size)] for _ in range(size)])
|
||||||
|
size = sg.run(in_between_searches)
|
||||||
|
return size
|
||||||
|
# SlashGrid([
|
||||||
|
# [True, False, True],
|
||||||
|
# [False, True, True]
|
||||||
|
# ]).run(print_grid)
|
||||||
|
# SlashGrid([
|
||||||
|
# [True, True, True],
|
||||||
|
# [False, False, False],
|
||||||
|
# [True, False, True]
|
||||||
|
# ]).run(print_grid)
|
||||||
|
# SlashGrid([
|
||||||
|
# [True, True, True, False, True],
|
||||||
|
# [False, False, False, True, False],
|
||||||
|
# [True, False, True, False, False],
|
||||||
|
# [True, True, True, False, True],
|
||||||
|
# ]).run(print_grid)
|
||||||
|
# SlashGrid([
|
||||||
|
# [True, True, True, False, True, False],
|
||||||
|
# [False, False, True, False, False, False],
|
||||||
|
# [True, True, True, False, False, False],
|
||||||
|
# [True, False, False, True, True, True],
|
||||||
|
# [True, False, False, True, False, False],
|
||||||
|
# [True, True, True, False, True, False]
|
||||||
|
# ]).run(print_grid)
|
||||||
|
print square(20, in_between_searches=print_grid)
|
Loading…
Reference in New Issue
Block a user