Roderic Day 1 anno fa
parent
commit
7c62da0e53
3 ha cambiato i file con 91 aggiunte e 48 eliminazioni
  1. +1
    -1
      VERSION
  2. +32
    -47
      y2023/p17.py
  3. +58
    -0
      y2023/p18.py

+ 1
- 1
VERSION Vedi File

@@ -1 +1 @@
🪽
💧

+ 32
- 47
y2023/p17.py Vedi File

@@ -1,55 +1,40 @@
import random
import heapq


def solve(ns):
heap = [(0, None, 0, d) for d in [1, 1j]]
exhausted = set()
while True:
old_cost, _, old_pos, old_dir = heapq.heappop(heap)

if old_pos == end:
break

key = old_pos, old_dir
if key in exhausted:
continue
exhausted.add(key)

for n in ns:
new_pos = old_pos + old_dir * n
if new_pos not in graph:
break
new_cost = old_cost + sum(graph[old_pos + i * old_dir] for i in range(1, n + 1))

heapq.heappush(heap, (new_cost, random.random(), new_pos, old_dir * 1j))
heapq.heappush(heap, (new_cost, random.random(), new_pos, old_dir / 1j))
return old_cost


text = open(0).read()
graph = {
complex(x, y): int({'.': 1, '#': 10000}.get(val, val))
complex(x, y): int(val)
for y, row in enumerate(text.splitlines())
for x, val in enumerate(row)
}
xmax = max(int(p.real) for p in graph)
ymax = max(int(p.imag) for p in graph)
end = complex(xmax, ymax)
mapping = {1: '>', -1: '<', 1j: 'v', -1j: '^'}

# a position mapped to the lowest effort taken to reach it
edge = {(0, ''): (0, '')}
exhausted = {}
while end not in exhausted:
pos = min(edge, key=edge.get)
parent = edge.pop(pos)
if pos[0] == end:
break
exhausted[pos] = parent
for step in [1, -1, 1j, -1j]:
# no reverse
if pos[1] and pos[1][-1] == mapping[-step]: continue

# turn condition
bop = pos[1] + mapping[step]
if len(bop) == 4 and len(set(bop)) == 1: continue

adj = pos[0] + step, bop[-3:]

# out of bounds check
if adj[0] not in graph: continue

# some positions are truly dead
if adj in exhausted: continue

score = parent[0] + graph[adj[0]], parent[1] + mapping[step]
if adj not in edge:
edge[adj] = score
else:
edge[adj] = min(edge[adj], score)


def scorer(seq):
pos = 0
out = 0
for char in seq:
pos += {'>': 1, '<': -1, '^': -1j, 'v': 1j}[char]
out += graph[pos]
return out


print(parent[1], scorer(parent[1]))
test = '>>>v>>>^>>>vv>vv>vvv>vvv<vv>'
print(test, scorer(test))
print(solve([1, 2, 3]))
print(solve(list(range(4, 11))))

+ 58
- 0
y2023/p18.py Vedi File

@@ -0,0 +1,58 @@
def render(graph):
xmin, *_, xmax = sorted(int(p.real) for p in walls)
ymin, *_, ymax = sorted(int(p.imag) for p in walls)
for y in range(ymin, ymax + 1):
for x in range(xmin, xmax + 1):
print('#' if complex(x, y) in graph else '.', end='')
print()


text = open(0).read()

walls = {0}
pos = 0
for line in text.splitlines():
d, n, rest = line.split()
n, d = int(rest[1:-1][1:][:5], 16), 'RDLU'[int(rest[-2])]
pos += {'R': 1, 'D': 1j, 'L': -1, 'U': -1j}[d] * int(n)
walls.add(pos)

smallx = {v: i * 2 for i, v in enumerate(sorted({p.real for p in walls}))}
smally = {v: i * 2 for i, v in enumerate(sorted({p.imag for p in walls}))}
walls = {complex(smallx[p.real], smally[p.imag]) for p in walls}


walls = {0}
pos = 0
smallpos = 0
for line in text.splitlines():
d, n, rest = line.split()
n, d = int(rest[1:-1][1:][:5], 16), 'RDLU'[int(rest[-2])]
pos += {'R': 1, 'D': 1j, 'L': -1, 'U': -1j}[d] * int(n)
goal = complex(smallx[pos.real], smally[pos.imag])
dirx = (goal - smallpos).real or (goal - smallpos).imag
while smallpos != goal:
smallpos += dirx
walls.add(smallpos)


render(walls)
exit()


xmin, *_, xmax = sorted(int(p.real) for p in walls)
ymin, *_, ymax = sorted(int(p.imag) for p in walls)
void = {complex(x, y) for x in range(xmin, xmax + 1) for y in range(ymin, ymax + 1)} - walls

groups = []
while void:
seen = set()
edge = {void.pop()}
while edge:
seen |= edge
edge = {pp + ss for pp in edge for ss in [1, -1, 1j, -1j]} & void - seen
groups.append(seen)
void -= seen

inside = {p for g in groups if not any(p.real in {xmin, xmax} or p.imag in {ymin, ymax} for p in g) for p in g}
print(len(inside | walls))

Loading…
Annulla
Salva