|
|
@@ -1,24 +1,15 @@
|
|
|
#!/usr/bin/env python3
|
|
|
import sys
|
|
|
-from itertools import chain, pairwise
|
|
|
|
|
|
UP, DOWN, LEFT, RIGHT = DIRECTIONS = (0, -1), (0, 1), (-1, 0), (1, 0)
|
|
|
-CONNECTIONS = {
|
|
|
- '|': (UP, DOWN),
|
|
|
- '-': (LEFT, RIGHT),
|
|
|
- '7': (LEFT, DOWN),
|
|
|
- 'J': (LEFT, UP),
|
|
|
- 'L': (UP, RIGHT),
|
|
|
- 'F': (RIGHT, DOWN),
|
|
|
- '.': (),
|
|
|
- 'S': (),
|
|
|
-}
|
|
|
+CONN = {'|': (UP, DOWN), '-': (LEFT, RIGHT), '7': (LEFT, DOWN),
|
|
|
+ 'J': (LEFT, UP), 'L': (UP, RIGHT), 'F': (RIGHT, DOWN)}
|
|
|
|
|
|
def parse(inp):
|
|
|
graph = {}
|
|
|
for y, line in enumerate(inp):
|
|
|
for x, char in enumerate(line.rstrip()):
|
|
|
- graph[(x, y)] = [(x + dx, y + dy) for dx, dy in CONNECTIONS[char]]
|
|
|
+ graph[(x, y)] = [(x + dx, y + dy) for dx, dy in CONN.get(char, ())]
|
|
|
if char == 'S':
|
|
|
sx, sy = start = x, y
|
|
|
graph[start] = [(sx + dx, sy + dy) for dx, dy in DIRECTIONS
|
|
|
@@ -33,31 +24,13 @@ def loop(graph, start):
|
|
|
nex = next(nb for nb in graph[nex] if nb != path[-2])
|
|
|
return path
|
|
|
|
|
|
-def find_outside(border):
|
|
|
- maxx, maxy = map(max, zip(*border))
|
|
|
- outside = set(chain(((0, y) for y in range(maxy + 1)),
|
|
|
- ((maxx, y) for y in range(maxy + 1)),
|
|
|
- ((x, 0) for x in range(maxx + 1)),
|
|
|
- ((x, maxy) for x in range(maxx + 1)))) - border
|
|
|
- explore = list(outside)
|
|
|
- while explore:
|
|
|
- x, y = explore.pop()
|
|
|
- for dx, dy in DIRECTIONS:
|
|
|
- nx, ny = nb = x + dx, y + dy
|
|
|
- if 0 <= nx <= maxx and 0 <= ny <= maxy and \
|
|
|
- nb not in outside and nb not in border:
|
|
|
- outside.add(nb)
|
|
|
- explore.append(nb)
|
|
|
- return outside
|
|
|
-
|
|
|
-def area(border):
|
|
|
- scaled = {(2 * x, 2 * y) for x, y in border}
|
|
|
- scaled |= {(ax + bx, ay + by)
|
|
|
- for (ax, ay), (bx, by) in pairwise(chain(border, border[:1]))}
|
|
|
- outside = sum(x % 2 + y % 2 == 0 for x, y in find_outside(scaled))
|
|
|
- maxx, maxy = map(max, zip(*border))
|
|
|
- return (maxx + 1) * (maxy + 1) - outside - len(border)
|
|
|
+def inner(border):
|
|
|
+ b = len(border)
|
|
|
+ x, y = zip(*border)
|
|
|
+ area = abs(sum(x[i] * y[(i + 1) % b] - y[i] * x[(i + 1) % b]
|
|
|
+ for i in range(b))) // 2 # Shoelace formula
|
|
|
+ return area - b // 2 + 1 # Pick's theorem
|
|
|
|
|
|
border = loop(*parse(sys.stdin))
|
|
|
print(len(border) // 2)
|
|
|
-print(area(border))
|
|
|
+print(inner(border))
|