refactor part 1
This commit is contained in:
124
day10/day10.py
124
day10/day10.py
@@ -50,25 +50,26 @@ class Tile(object):
|
|||||||
self.links = [S, E]
|
self.links = [S, E]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.val
|
return f'{self.val} x: {self.x} y: {self.y}'
|
||||||
|
|
||||||
def opposite_end(self, d: Direction) -> Direction:
|
def __eq__(self, obj) -> bool:
|
||||||
entry = d.opposite()
|
return self.x == obj.x and self.y == obj.y
|
||||||
if not entry in self.links:
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash((self.x, self.y))
|
||||||
|
|
||||||
|
def opposite_pipe_end(self, d: Direction) -> Direction:
|
||||||
|
if not d in self.links:
|
||||||
return None
|
return None
|
||||||
if entry == self.links[0]:
|
if d == self.links[0]:
|
||||||
return self.links[1]
|
return self.links[1]
|
||||||
else:
|
else:
|
||||||
return self.links[0]
|
return self.links[0]
|
||||||
|
|
||||||
def has_link_from(self, d: Direction) -> bool:
|
def has_link_from(self, d: Direction) -> bool:
|
||||||
return (d.opposite() in self.links)
|
return (d in self.links)
|
||||||
|
|
||||||
|
|
||||||
def is_pipe(self):
|
|
||||||
return self.val != '.'
|
|
||||||
|
|
||||||
|
|
||||||
class Field(object):
|
class Field(object):
|
||||||
def __init__(self, lines: list[str]):
|
def __init__(self, lines: list[str]):
|
||||||
self.grid = [list(l) for l in lines]
|
self.grid = [list(l) for l in lines]
|
||||||
@@ -82,77 +83,94 @@ class Field(object):
|
|||||||
out += ''.join([str(tile) for tile in row]) + '\n'
|
out += ''.join([str(tile) for tile in row]) + '\n'
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def get(self, x, y: int) -> Tile:
|
def _get(self, x, y: int) -> Tile:
|
||||||
if y >= len(self.grid) or x >= len(self.grid):
|
if y < 0 or x < 0 or y >= len(self.grid) or x >= len(self.grid):
|
||||||
return None
|
return None
|
||||||
return self.grid[y][x]
|
return self.grid[y][x]
|
||||||
|
|
||||||
|
def get_adjacent(self, t: Tile, d: Direction) -> Tile:
|
||||||
|
x, y = t.x, t.y
|
||||||
|
if d == E:
|
||||||
|
x += 1
|
||||||
|
elif d == S:
|
||||||
|
y += 1
|
||||||
|
elif d == W:
|
||||||
|
x -= 1
|
||||||
|
elif d == N:
|
||||||
|
y -= 1
|
||||||
|
return self._get(x, y)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Walker(Field):
|
class Walker(Field):
|
||||||
def __init__(self, lines):
|
def __init__(self, lines):
|
||||||
super().__init__(lines)
|
super().__init__(lines)
|
||||||
|
self.loop = []
|
||||||
|
self.visited = set()
|
||||||
|
|
||||||
def _get_start(self) -> Tile:
|
def _get_start(self) -> Tile:
|
||||||
for y in range(len(self.grid)):
|
for y in range(len(self.grid)):
|
||||||
for x in range(len(self.grid[0])):
|
for x in range(len(self.grid[0])):
|
||||||
t = self.get(x, y)
|
t = self._get(x, y)
|
||||||
if t.val == START:
|
if t.val == START:
|
||||||
return t
|
return t
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _walk_to_start(self, t: Tile, direction: Direction) -> (bool, int):
|
def _find_loop(self):
|
||||||
self.visited = set()
|
start = self._get_start()
|
||||||
steps = 0
|
for d in [N, E, S, W]:
|
||||||
while True:
|
curr = start
|
||||||
x, y = t.x, t.y
|
dir = d
|
||||||
self.visited.add((x, y))
|
self.loop = []
|
||||||
if direction == E:
|
while True:
|
||||||
x += 1
|
self.loop.append(curr)
|
||||||
elif direction == S:
|
nxt = self.get_adjacent(curr, dir)
|
||||||
y += 1
|
if not nxt or not nxt.has_link_from(dir.opposite()):
|
||||||
elif direction == W:
|
break
|
||||||
x -= 1
|
if nxt.val == START:
|
||||||
elif direction == N:
|
return
|
||||||
y -= 1
|
curr = nxt
|
||||||
nxt = self.get(x, y)
|
dir = nxt.opposite_pipe_end(dir.opposite())
|
||||||
if (not nxt):
|
|
||||||
break
|
|
||||||
|
|
||||||
steps += 1
|
|
||||||
if nxt.val == START:
|
|
||||||
return True, steps
|
|
||||||
if not nxt.has_link_from(direction):
|
|
||||||
break
|
|
||||||
|
|
||||||
t = nxt
|
|
||||||
d = nxt.opposite_end(direction)
|
|
||||||
direction = d
|
|
||||||
return False, steps
|
|
||||||
|
|
||||||
|
|
||||||
def find_max_steps_in_loop(self) -> int:
|
def find_max_steps_in_loop(self) -> int:
|
||||||
start = self._get_start()
|
self._find_loop()
|
||||||
for direction in [N, E, S, W]:
|
return len(self.loop) // 2
|
||||||
found, steps = self._walk_to_start(start, direction)
|
|
||||||
if found:
|
|
||||||
return steps // 2
|
|
||||||
|
|
||||||
def find_captured_by_loop(self) -> int:
|
def find_captured_by_loop(self) -> int:
|
||||||
if not self.visited:
|
if not self.loop:
|
||||||
self.find_max_steps_in_loop()
|
# this fills self.loop slice
|
||||||
pass
|
# with loop tiles
|
||||||
|
self._find_loop()
|
||||||
|
self.visited = set(self.loop)
|
||||||
|
inside_loop = set()
|
||||||
|
for t in self.loop:
|
||||||
|
for d in [N, E, S, W]:
|
||||||
|
newt = self.get_adjacent(t, d)
|
||||||
|
if not newt or newt in self.visited:
|
||||||
|
continue
|
||||||
|
if self._is_inside_loop(newt):
|
||||||
|
inside_loop.add(newt)
|
||||||
|
self.visited.add(newt)
|
||||||
|
return len(inside_loop)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_inside_loop(self, t: Tile) -> bool:
|
||||||
|
# TODO
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
r = tools.Reader('test_input.txt')
|
r = tools.Reader('test_input.txt')
|
||||||
lines = r.read()
|
lines = r.read()
|
||||||
|
|
||||||
w = Walker(lines)
|
w = Walker(lines)
|
||||||
print(w)
|
|
||||||
steps = w.find_max_steps_in_loop()
|
steps = w.find_max_steps_in_loop()
|
||||||
print(steps)
|
print(steps)
|
||||||
print(w.visited)
|
n = w.find_captured_by_loop()
|
||||||
|
print(n)
|
||||||
|
|
||||||
r = tools.Reader('input.txt')
|
r = tools.Reader('input.txt')
|
||||||
lines = r.read()
|
lines = r.read()
|
||||||
@@ -160,5 +178,5 @@ if __name__ == '__main__':
|
|||||||
w = Walker(lines)
|
w = Walker(lines)
|
||||||
steps = w.find_max_steps_in_loop()
|
steps = w.find_max_steps_in_loop()
|
||||||
print(steps)
|
print(steps)
|
||||||
# print(w.visited)
|
# print(w.loop)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user