Solve 2023:10 "Pipe Maze"
Got completely stuck on part 2. Tried some polygon area calculations, but none provided the correct answer, most likely due to the unorthodox polygon points. I also tried _shoelace method_ without any luck. Had not heard about that one earlier, it was a good learning experience even though I vould not use it here. By the subreddit, several people had had luck using the ray method. > Part 2 using one of my favorite facts from > graphics engineering: lets say you have an > enclosed shape, and you want to color every > pixel inside of it. How do you know if a given > pixel is inside the shape or not? Well, it > turns out: if you shoot a ray in any direction > from the pixel and it crosses the boundary an > _odd number_ of times, it's _inside_. if it crosses > an even number of times, it's outside. Works > for all enclosed shapes, even self-intersecting > and non-convex ones.
This commit is contained in:
parent
741f7b89d8
commit
b681e5cdb7
1 changed files with 77 additions and 26 deletions
|
|
@ -1,44 +1,95 @@
|
|||
import re
|
||||
from collections import Counter, defaultdict, deque
|
||||
from output import answer
|
||||
|
||||
n = 10
|
||||
title = "dddd"
|
||||
title = "Pipe Maze"
|
||||
|
||||
|
||||
D = (-1, 0), (0, 1), (1, 0), (0, -1)
|
||||
|
||||
C = {
|
||||
(-1, 0): ["|", "7", "F"],
|
||||
(0, 1): ["-", "7", "J"],
|
||||
(1, 0): ["|", "L", "J"],
|
||||
(0, -1): ["-", "L", "F"],
|
||||
}
|
||||
|
||||
A = {
|
||||
"S": [0, 1, 2, 3],
|
||||
"-": [1, 3],
|
||||
"|": [0, 2],
|
||||
"F": [1, 2],
|
||||
"L": [0, 1],
|
||||
"7": [2, 3],
|
||||
"J": [0, 3],
|
||||
}
|
||||
|
||||
|
||||
@answer(1, "Answer is {}")
|
||||
def part_1(data):
|
||||
return data
|
||||
def part_1(presolved):
|
||||
return presolved[0]
|
||||
|
||||
|
||||
@answer(2, "Actually, answer is {}")
|
||||
def part_2(data):
|
||||
return data
|
||||
def part_2(presolved):
|
||||
return presolved[1]
|
||||
|
||||
|
||||
# uncomment to solve parts in one go
|
||||
# def presolve(data):
|
||||
# return data
|
||||
def presolve(data):
|
||||
matrix = data.split()
|
||||
w = len(matrix[0])
|
||||
h = len(matrix)
|
||||
q = deque()
|
||||
visited = set()
|
||||
|
||||
for r in range(h):
|
||||
if "S" in matrix[r]:
|
||||
start = (r, matrix[r].index("S"))
|
||||
q.append(start)
|
||||
break
|
||||
|
||||
while q:
|
||||
o = q.popleft()
|
||||
visited.add(o)
|
||||
for di in A[matrix[o[0]][o[1]]]:
|
||||
d = D[di]
|
||||
r = o[0] + d[0]
|
||||
c = o[1] + d[1]
|
||||
if r >= 0 and r < h and c >= 0 and c < w:
|
||||
t = matrix[r][c]
|
||||
p = (r, c)
|
||||
if p not in visited and t != "." and t in C[d]:
|
||||
q.append(p)
|
||||
p1 = len(visited) // 2
|
||||
|
||||
p2 = 0
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
if (y, x) in visited:
|
||||
continue
|
||||
crosses = 0
|
||||
y2, x2 = y, x
|
||||
while y2 < h and x2 < w:
|
||||
c2 = matrix[y2][x2]
|
||||
if (y2, x2) in visited and c2 not in "L7":
|
||||
crosses += 1
|
||||
x2 += 1
|
||||
y2 += 1
|
||||
if crosses % 2 == 1:
|
||||
p2 += 1
|
||||
|
||||
return p1, p2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# use dummy data
|
||||
inp = """
|
||||
replace me
|
||||
""".strip()
|
||||
with open(f"./input/10.txt", "r") as f:
|
||||
inp = f.read()
|
||||
|
||||
# uncomment to instead use stdin
|
||||
# import sys; inp = sys.stdin.read().strip()
|
||||
|
||||
# uncomment to use AoC provided puzzle input
|
||||
# with open(f"./input/10.txt", "r") as f:
|
||||
# inp = f.read()
|
||||
|
||||
# uncomment to do initial data processing shared by part 1-2
|
||||
# inp = presolve(inp)
|
||||
inp = presolve(inp)
|
||||
|
||||
a = part_1(inp)
|
||||
# b = part_2(inp)
|
||||
b = part_2(inp)
|
||||
|
||||
# uncomment and replace 0 with actual output to refactor code
|
||||
# and ensure nonbreaking changes
|
||||
# assert a == 0
|
||||
# assert b == 0
|
||||
assert a == 6846
|
||||
assert b == 325
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue