Skip to content

Commit

Permalink
Correct answer up to 6x2
Browse files Browse the repository at this point in the history
  • Loading branch information
nhardy committed Sep 27, 2017
1 parent 1d48af4 commit d2ce3f1
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 40 deletions.
80 changes: 43 additions & 37 deletions main.py
Expand Up @@ -59,6 +59,12 @@ def __init__(self, name: str, locations: Tuple[Tuple[bool]], rotations: int):
self.locations = locations
self._rotations = rotations

def first_filled_y(self) -> int:
for x_pos in range(len(self.locations[0])):
for y_pos in range(len(self.locations)):
if self.locations[y_pos][x_pos]:
return y_pos

def get_rotations(self) -> List['Piece']:
"""
Returns all the rotations for the current Piece
Expand All @@ -82,6 +88,14 @@ class Grid:
It is important to note that all properties are immuntable.
"""

@classmethod
def filled(cls: 'Grid', width: int, length: int) -> 'Grid':
"""
Returns a filled Grid of the given size
"""

return cls(width, length, tuple(tuple(True for _ in range(length)) for _ in range(width)))

def __init__(self, width: int, length: int, cells: Tuple[Tuple[bool, ...], ...]=None):
self._width = width
self._length = length
Expand All @@ -100,11 +114,11 @@ def width(self):
def length(self):
return self._length

def first_empty(self):
for _, row in enumerate(self._cells):
for x_pos, cell in enumerate(row):
if not cell:
return x_pos
def first_empty(self) -> Optional[Tuple[int, int]]:
for x_pos in range(self._length):
for y_pos in range(self._width):
if not self._cells[y_pos][x_pos]:
return (x_pos, y_pos)

def place(self, piece: Piece, coords: Tuple[int, int]) -> Optional['Grid']:
"""
Expand All @@ -115,7 +129,7 @@ def place(self, piece: Piece, coords: Tuple[int, int]) -> Optional['Grid']:
x_pos, y_pos = coords
piece_locations = piece.locations

if len(piece_locations) + y_pos > self._width:
if y_pos < 0 or len(piece_locations) + y_pos > self._width:
return None
if len(piece_locations[0]) + x_pos > self._length:
return None
Expand All @@ -128,18 +142,13 @@ def place(self, piece: Piece, coords: Tuple[int, int]) -> Optional['Grid']:
cell_y_pos = y_pos + p_y_pos
cell_x_pos = x_pos + p_x_pos

print('X, Y', (cell_x_pos, cell_y_pos), self._cells[cell_y_pos][cell_x_pos])

# If both the cell of the piece and the cell of the
# Grid are filled, we cannot procede
if self._cells[cell_y_pos][cell_x_pos]:
return None

changes.add((cell_x_pos, cell_y_pos))

print('Current Grid:')
print(self)

return Grid(self._width, self._length, tuple(
tuple(
cell or (False if (cell_x_pos, cell_y_pos) not in changes else True) for cell_x_pos, cell in enumerate(row)
Expand All @@ -156,9 +165,12 @@ def __hash__(self) -> int:

return total

def __eq__(self, other: Type['Grid']):
return self._cells == other._cells

def __str__(self):
return '\n'.join([
''.join(['!' if cell else '?' for cell in row]) for row in self._cells
''.join(['x' if cell else '?' for cell in row]) for row in self._cells
])

ALL_PIECE_ROTATIONS = Piece.get_all_piece_rotations()
Expand All @@ -169,33 +181,25 @@ def possibilities(grid: Grid, cache: dict):
the remainder of the Grid
"""

first_empty = grid.first_empty()

if first_empty is None:
cache[grid] = 0
return 0

total = 0
first_empty = grid.first_empty()

for y_pos in range(grid.width):
for x_pos in range(first_empty, min(first_empty + 4, grid.length)):
for piece in ALL_PIECE_ROTATIONS:
new_grid = grid.place(piece, (x_pos, y_pos))
if new_grid is not None:
subtotal = None
if new_grid in cache:
print('New grid')
print(new_grid)
print('Cache hit', cache[new_grid])
subtotal = cache[new_grid]
else:
print('Cache miss')
subtotal = possibilities(new_grid, cache)
if subtotal is not None:
print('Counting', piece, 'added at', (x_pos, y_pos), subtotal)
total += 1 + subtotal

cache[grid] = total if total != 0 else None
if first_empty is not None:
x_pos, y_pos = first_empty

for piece in ALL_PIECE_ROTATIONS:
first_filled_y = piece.first_filled_y()
new_grid = grid.place(piece, (x_pos, y_pos - first_filled_y))
if new_grid is not None:
subtotal = None
if new_grid in cache:
subtotal = cache[new_grid]
else:
subtotal = possibilities(new_grid, cache)
if subtotal is not None:
total += subtotal

cache[grid] = total
return total

def result(width: int, length: int) -> int:
Expand All @@ -214,6 +218,8 @@ def result(width: int, length: int) -> int:
# can simply add the "No. of Combinations" instead of traversing
# further, if that value had already been calculated.
grid_states = {}
filled_grid = Grid.filled(width, length)
grid_states[filled_grid] = 1
empty_grid = Grid(width, length)

# The Final result will be stored in the empty Grid state
Expand Down
12 changes: 9 additions & 3 deletions test.txt
Expand Up @@ -7,6 +7,12 @@
# 4 2
1 8
# 1
# # Something
# 6 10
# # over 9000
6 2
# 9
6 4
# 2003
6 6
# 178939
6 8
# 22483347
6 10

0 comments on commit d2ce3f1

Please sign in to comment.