summaryrefslogtreecommitdiff
path: root/translation.py
blob: 32d202870920af6761978ceea42d382b1082a844 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import sys
import numpy as np
import functools

sys.setrecursionlimit(100000)

# Part 1
# cubes←⍎¨⊃⎕NGET'input'1
cubes = [eval(f"({line})") for line in open("input").readlines()]

# movements←{⍵,-⍵}↓(3 3⍴4↑1)
movements = (lambda w: np.vstack([w, -w]))(np.identity(3, dtype=int))

# sides←,cubes∘.+movements
sides = [tuple(c + m) for c in cubes for m in movements]

# ≢sides~cubes
print(sum(1 for side in sides if side not in cubes))

# Part 2
# mins←(↑⌊/cubes)-1 1 1
mins = tuple(min(c) - 1 for c in zip(*cubes))
# maxs←(↑⌈/cubes)+1 1 1
maxs = tuple(max(c) + 1 for c in zip(*cubes))
# in_boundary←{0≡+/((⍵<mins),(⍵>maxs))}
in_boundary = lambda c: 0 == functools.reduce(
    lambda a, b: a + b,
    (int(c[i] < mins[i] or c[i] > maxs[i]) for i in range(3)),
    0,
)
# count←0
count = 0


def rec(left, right):
    global count
    # 0=≢⍵:count
    if not right:
        return count
    # head←1↑⍵ ⋄ tail←1↓⍵
    head, tail = right[0], right[1:]
    # neighbors←movements+¨head
    neighbors = [tuple(head + m) for m in movements]
    # next←{(in_boundary¨⍵)/⍵}neighbors
    next = set(filter(in_boundary, neighbors))
    # count⊢←count+(+/{(↓⍵)∊cubes}¨neighbors)
    count += sum((n in cubes) for n in neighbors)
    # (⍺,head)∇((tail∪next)~⍺)
    return rec(left | set([head]), list((set(tail) | next) - left))


# cubes{...}↓maxs
print(rec(set(cubes), [maxs]))