Skip to content

Commit 15e4933

Browse files
committed
✅ Adding Day 10 OG & One-liners!
1 parent 08615c1 commit 15e4933

File tree

3 files changed

+133
-4
lines changed

3 files changed

+133
-4
lines changed

2023/day-10.py

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
'''
2+
2023 Advent of Code - Day 10 (https://adventofcode.com/2023/day/10)
3+
Solution by Sav Bell (https://github.com/savbell)
4+
Challenge: Solve every day in a single line of Python code.
5+
See full progress at https://github.com/savbell/advent-of-code-one-liners
6+
'''
7+
8+
from sys import setrecursionlimit
9+
10+
# Input files not included in repo per copyright & Eric Wastl's request.
11+
# https://www.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs/
12+
# Replace with path to your personal input file if you would like to run the code.
13+
input_file = '2023/day-10.txt'
14+
15+
# To match the format of input files for the Basilisk.
16+
q = { 10: open(input_file).read().strip() }
17+
18+
19+
######################### PART 1: MULTI-LINE SOLUTION #########################
20+
grid = [[x for x in row] for row in q[10].strip().split('\n')]
21+
pipe_map = {'|': [(0, -1), (0, 1)], '-': [(1, 0), (-1, 0)],
22+
'L': [(0, -1), (1, 0)], 'J': [(0, -1), (-1, 0)],
23+
'7': [(0, 1), (-1, 0)], 'F': [(0, 1), (1, 0)],
24+
'.': [], 'S': [(0, -1), (0, 1), (1, 0), (-1, 0)]}
25+
26+
def find_valid_moves(grid, pos, pipe_map, prev_dir=None):
27+
char = grid[pos[1]][pos[0]]
28+
valid_directions = pipe_map[char]
29+
valid_moves = []
30+
for d in valid_directions:
31+
new_pos = (pos[0] + d[0], pos[1] + d[1])
32+
new_char = grid[new_pos[1]][new_pos[0]]
33+
if 0 <= new_pos[0] < len(grid[0]) and 0 <= new_pos[1] < len(grid):
34+
if d == (0, -1) and (0, 1) in pipe_map[new_char] and prev_dir != (0, 1):
35+
valid_moves.append(new_pos)
36+
if d == (0, 1) and (0, -1) in pipe_map[new_char] and prev_dir != (0, -1):
37+
valid_moves.append(new_pos)
38+
if d == (1, 0) and (-1, 0) in pipe_map[new_char] and prev_dir != (-1, 0):
39+
valid_moves.append(new_pos)
40+
if d == (-1, 0) and (1, 0) in pipe_map[new_char] and prev_dir != (1, 0):
41+
valid_moves.append(new_pos)
42+
return valid_moves
43+
44+
def find_start_char(grid, pos, pipe_map):
45+
valid_moves = find_valid_moves(grid, pos, pipe_map)
46+
valid_directions = [(x[0]-pos[0], x[1]-pos[1]) for x in valid_moves]
47+
for k, v in pipe_map.items():
48+
if v == valid_directions:
49+
return k
50+
51+
def solve(grid, pos, pipe_map, visited, prev_dir=None):
52+
move = find_valid_moves(grid, pos, pipe_map, prev_dir)[0]
53+
if move == start_pos and len(visited) > 0:
54+
return visited
55+
visited.add(move)
56+
return solve(grid, move, pipe_map, visited, (move[0]-pos[0], move[1]-pos[1]))
57+
58+
start_pos = [(x, y) for y, row in enumerate(grid) for x, char in enumerate(row) if char == 'S'][0]
59+
grid[start_pos[1]][start_pos[0]] = find_start_char(grid, start_pos, pipe_map)
60+
61+
setrecursionlimit(30000)
62+
print('Day 10 Part 1:',len(solve(grid, start_pos, pipe_map, { start_pos }))//2)
63+
64+
########################## PART 1: ONE-LINE SOLUTION ##########################
65+
print('Day 10 Part 1:',(g:=[[x for x in row] for row in q[10].strip().split('\n')],p:={'|':[(0,-1),(0,1)],'-':[(1,0),(-1,0)],'L':[(0,-1),(1,0)],'J':[(0,-1),(-1,0)],'7':[(0,1),(-1,0)],'F':[(0,1),(1,0)],'.':[],'S':[(0,-1),(0,1),(1,0),(-1,0)]},f:=lambda g,c,p,e=None:(r:=g[c[1]][c[0]],s:=p[r],l:=[],[(o:=(c[0]+d[0],c[1]+d[1]),n:=g[o[1]][o[0]],(0<=o[0]<len(g[0]) and 0<=o[1]<len(g)) and ((d==(0,-1) and (0,1) in p[n] and e!=(0,1)) and l.append(o),(d==(0,1) and (0,-1) in p[n] and e!=(0,-1)) and l.append(o),(d==(1,0) and (-1,0) in p[n] and e!=(-1,0)) and l.append(o),(d==(-1,0) and (1,0) in p[n] and e!=(1,0)) and l.append(o))) for d in s]) and l,w:=lambda g,pos,p:[k for k,v in p.items() if v==[(x[0]-pos[0],x[1]-pos[1]) for x in f(g,pos,p)]][0],y:=lambda g,c,p,v,t=None:(v.add(u) or y(g,u,p,v,(u[0]-c[0],u[1]-c[1]))) if (u:=f(g,c,p,t)[0])!=a or not v else v,a:=[(x,y) for y,r in enumerate(g) for x,c in enumerate(r) if c=='S'][0],g[a[1]].__setitem__(a[0],w(g,a,p))) and len(y(g,a,p,{a}))//2)
66+
67+
68+
######################## PART 2: MULTI-LINE SOLUTION ##########################
69+
grid = [[x for x in row] for row in q[10].strip().split('\n')]
70+
pipe_map = {'|': [(0, -1), (0, 1)], '-': [(1, 0), (-1, 0)],
71+
'L': [(0, -1), (1, 0)], 'J': [(0, -1), (-1, 0)],
72+
'7': [(0, 1), (-1, 0)], 'F': [(0, 1), (1, 0)],
73+
'.': [], 'S': [(0, -1), (0, 1), (1, 0), (-1, 0)]}
74+
75+
def find_valid_moves(grid, pos, pipe_map, prev_dir=None):
76+
char = grid[pos[1]][pos[0]]
77+
valid_directions = pipe_map[char]
78+
valid_moves = []
79+
for d in valid_directions:
80+
new_pos = (pos[0] + d[0], pos[1] + d[1])
81+
new_char = grid[new_pos[1]][new_pos[0]]
82+
if 0 <= new_pos[0] < len(grid[0]) and 0 <= new_pos[1] < len(grid):
83+
if d == (0, -1) and (0, 1) in pipe_map[new_char] and prev_dir != (0, 1):
84+
valid_moves.append(new_pos)
85+
if d == (0, 1) and (0, -1) in pipe_map[new_char] and prev_dir != (0, -1):
86+
valid_moves.append(new_pos)
87+
if d == (1, 0) and (-1, 0) in pipe_map[new_char] and prev_dir != (-1, 0):
88+
valid_moves.append(new_pos)
89+
if d == (-1, 0) and (1, 0) in pipe_map[new_char] and prev_dir != (1, 0):
90+
valid_moves.append(new_pos)
91+
return valid_moves
92+
93+
def find_start_char(grid, pos, pipe_map):
94+
valid_moves = find_valid_moves(grid, pos, pipe_map)
95+
valid_directions = [(x[0]-pos[0], x[1]-pos[1]) for x in valid_moves]
96+
for k, v in pipe_map.items():
97+
if v == valid_directions:
98+
return k
99+
100+
def solve(grid, pos, pipe_map, visited, prev_dir=None):
101+
move = find_valid_moves(grid, pos, pipe_map, prev_dir)[0]
102+
if move == start_pos and len(visited) > 0:
103+
return visited
104+
visited.add(move)
105+
return solve(grid, move, pipe_map, visited, (move[0]-pos[0], move[1]-pos[1]))
106+
107+
start_pos = [(x, y) for y, row in enumerate(grid) for x, char in enumerate(row) if char == 'S'][0]
108+
grid[start_pos[1]][start_pos[0]] = find_start_char(grid, start_pos, pipe_map)
109+
visited = solve(grid, start_pos, pipe_map, { start_pos })
110+
111+
contained = set()
112+
for i in range(len(grid)):
113+
within = 0
114+
for j in range(len(grid[0])):
115+
if (j, i) in visited:
116+
if grid[i][j] in ['|', 'L', 'J']:
117+
within = not within
118+
elif within:
119+
contained.add((j, i))
120+
121+
print('Day 10 Part 2:',len(contained))
122+
123+
########################## PART 2: ONE-LINE SOLUTION ##########################
124+
print('Day 10 Part 2:',(g:=[[x for x in row] for row in q[10].strip().split('\n')],p:={'|':[(0,-1),(0,1)],'-':[(1,0),(-1,0)],'L':[(0,-1),(1,0)],'J':[(0,-1),(-1,0)],'7':[(0,1),(-1,0)],'F':[(0,1),(1,0)],'.':[],'S':[(0,-1),(0,1),(1,0),(-1,0)]},f:=lambda g,c,p,e=None:(r:=g[c[1]][c[0]],s:=p[r],l:=[],[(o:=(c[0]+d[0],c[1]+d[1]),n:=g[o[1]][o[0]],(0<=o[0]<len(g[0]) and 0<=o[1]<len(g)) and ((d==(0,-1) and (0,1) in p[n] and e!=(0,1)) and l.append(o),(d==(0,1) and (0,-1) in p[n] and e!=(0,-1)) and l.append(o),(d==(1,0) and (-1,0) in p[n] and e!=(-1,0)) and l.append(o),(d==(-1,0) and (1,0) in p[n] and e!=(1,0)) and l.append(o))) for d in s]) and l,w:=lambda g,c,p:[k for k,v in p.items() if v==[(x[0]-c[0],x[1]-c[1]) for x in f(g,c,p)]][0],y:=lambda g,c,p,v,t=None:(v.add(u) or y(g,u,p,v,(u[0]-c[0],u[1]-c[1]))) if (u:=f(g,c,p,t)[0])!=a or not v else v,a:=[(x,y) for y,r in enumerate(g) for x,c in enumerate(r) if c=='S'][0],g[a[1]].__setitem__(a[0],w(g,a,p)),(v:=y(g,a,p,{ a }),c:=set(),[((w:=0),[((j,i) in v and (g[i][j] in '|LJ' and (w:=not w)),(j,i) not in v and w and c.add((j,i))) for j in range(len(g[0]))]) for i in range(len(g))])) and len(c))

0 commit comments

Comments
 (0)