| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- #!/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': (),
- }
- 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]]
- if char == 'S':
- sx, sy = start = x, y
- graph[start] = [(sx + dx, sy + dy) for dx, dy in DIRECTIONS
- if start in graph.get((sx + dx, sy + dy), [])]
- return graph, start
- def loop(graph, start):
- path = [start]
- nex = graph[start][0]
- while nex != start:
- path.append(nex)
- 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)
- border = loop(*parse(sys.stdin))
- print(len(border) // 2)
- print(area(border))
|