Solve first 70% problem 161.
This commit is contained in:
@@ -35,7 +35,7 @@ def euler_111():
|
||||
for p in get_permutations(base, 2):
|
||||
if is_prime(p):
|
||||
subresult += p
|
||||
assert subresult > 0, "More than to permutations required to yield prime"
|
||||
assert subresult > 0, "More than two permutations required to yield prime"
|
||||
result += subresult
|
||||
return result
|
||||
|
||||
|
||||
108
python/e161.py
Normal file
108
python/e161.py
Normal file
@@ -0,0 +1,108 @@
|
||||
from copy import copy
|
||||
from typing import Optional, Tuple
|
||||
|
||||
|
||||
CACHE = {}
|
||||
EMPTY = '⬛'
|
||||
FIELDS = ['🔴', '🟠', '🟡', '🟢', '🔵', '🟣', '⚪', '🟤', '⭐']
|
||||
|
||||
|
||||
# We use [row, col] indexing.
|
||||
BLOCKS = [
|
||||
((0, 0), (0, 1), (0, 2)), # dark blue
|
||||
((0, 0), (1, 0), (2, 0)), # black
|
||||
((0, 0), (0, 1), (1, 0)), # red
|
||||
((0, 0), (0, 1), (1, 1)), # green
|
||||
((0, 0), (1, 0), (1, 1)), # blue
|
||||
((0, 0), (1, 0), (1, -1)), # orange
|
||||
]
|
||||
|
||||
|
||||
class Field:
|
||||
|
||||
def __init__(self, N_COLS, N_ROWS):
|
||||
self.N_COLS = N_COLS
|
||||
self.N_ROWS = N_ROWS
|
||||
self.state = 0
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.state)
|
||||
|
||||
def get_first_empty(self) -> Optional[Tuple[int, int]]:
|
||||
for row in range(self.N_ROWS):
|
||||
for col in range(self.N_COLS):
|
||||
if self.is_empty(row, col):
|
||||
return (row, col)
|
||||
return None
|
||||
|
||||
def is_empty(self, row: int, col: int) -> bool:
|
||||
index = row * self.N_COLS + col
|
||||
result = not bool(self.state & (1 << index))
|
||||
return result
|
||||
|
||||
def set(self, row: int, col: int):
|
||||
index = row * self.N_COLS + col
|
||||
self.state |= (1 << index)
|
||||
|
||||
def __getitem__(self, row: int):
|
||||
return [self.is_empty(row, col) for col in range(self.N_COLS)]
|
||||
|
||||
def print(self):
|
||||
for row in range(self.N_ROWS):
|
||||
row_str = ""
|
||||
for col in range(self.N_COLS):
|
||||
row_str += '⬛' if self.is_empty(row, col) else '⚪'
|
||||
print(row_str)
|
||||
|
||||
|
||||
def fits(field, block, coord):
|
||||
N_ROWS = field.N_ROWS
|
||||
N_COLS = field.N_COLS
|
||||
|
||||
for rel_coord in block:
|
||||
abs_row = coord[0] + rel_coord[0]
|
||||
abs_col = coord[1] + rel_coord[1]
|
||||
|
||||
if abs_row < 0 or abs_col < 0 or abs_row >= N_ROWS or abs_col >= N_COLS:
|
||||
return None
|
||||
|
||||
if not field.is_empty(abs_row, abs_col):
|
||||
return None
|
||||
|
||||
new_field = copy(field)
|
||||
for rel_coord in block:
|
||||
abs_row = coord[0] + rel_coord[0]
|
||||
abs_col = coord[1] + rel_coord[1]
|
||||
new_field.set(abs_row, abs_col)
|
||||
|
||||
return new_field
|
||||
|
||||
|
||||
def count(field):
|
||||
global CACHE
|
||||
|
||||
if hash(field) in CACHE:
|
||||
return CACHE[hash(field)]
|
||||
|
||||
first_empty = field.get_first_empty()
|
||||
if first_empty is None:
|
||||
return 1
|
||||
|
||||
result = 0
|
||||
for block in BLOCKS:
|
||||
if (new_field := fits(field, block, first_empty)) is not None:
|
||||
result += count(new_field)
|
||||
|
||||
CACHE[hash(field)] = result
|
||||
return result
|
||||
|
||||
|
||||
def euler_161():
|
||||
return count(Field(9, 12))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = euler_161()
|
||||
print("e161.py: " + str(solution))
|
||||
assert(solution == 20574308184277971)
|
||||
|
||||
Reference in New Issue
Block a user