2023-12-01 15:31:20 +00:00
|
|
|
from contextlib import contextmanager
|
|
|
|
from timeit import default_timer
|
|
|
|
from pathlib import Path
|
|
|
|
import cProfile
|
|
|
|
import functools
|
|
|
|
import pstats
|
2023-12-10 16:09:34 +00:00
|
|
|
from itertools import groupby
|
|
|
|
|
|
|
|
def all_equal(iterable):
|
|
|
|
g = groupby(iterable)
|
|
|
|
return next(g, True) and not next(g, False)
|
2023-12-01 15:31:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
def profile(func):
|
|
|
|
@functools.wraps(func)
|
|
|
|
def inner(*args, **kwargs):
|
|
|
|
profiler = cProfile.Profile()
|
|
|
|
profiler.enable()
|
|
|
|
try:
|
|
|
|
retval = func(*args, **kwargs)
|
|
|
|
finally:
|
|
|
|
profiler.disable()
|
|
|
|
with open("profile.out", "w") as profile_file:
|
|
|
|
stats = pstats.Stats(profiler, stream=profile_file)
|
|
|
|
stats.print_stats()
|
|
|
|
return retval
|
|
|
|
|
|
|
|
return inner
|
|
|
|
|
2023-12-10 16:09:34 +00:00
|
|
|
def spl(y):
|
|
|
|
return [int(w) for w in y]
|
2023-12-01 15:31:20 +00:00
|
|
|
|
|
|
|
def minmax(l):
|
|
|
|
return min(l), max(l)
|
|
|
|
|
|
|
|
|
2023-12-03 04:12:04 +00:00
|
|
|
def load_rows(day, part2=False):
|
2023-12-08 18:42:42 +00:00
|
|
|
return [row for row in load(day, part2)]
|
2023-12-01 15:31:20 +00:00
|
|
|
|
|
|
|
|
2023-12-03 04:12:04 +00:00
|
|
|
def load(day, part2=False):
|
|
|
|
if part2:
|
2023-12-08 18:42:42 +00:00
|
|
|
path = Path(get_fname(day) + ".part2")
|
2023-12-03 04:12:04 +00:00
|
|
|
try:
|
|
|
|
return path.read_text().rstrip().split("\n")
|
|
|
|
except FileNotFoundError:
|
|
|
|
# No part 2 file, use first file
|
|
|
|
pass
|
2023-12-01 15:31:20 +00:00
|
|
|
path = Path(get_fname(day))
|
|
|
|
return path.read_text().rstrip().split("\n")
|
|
|
|
|
|
|
|
|
|
|
|
def get_fname(day: int) -> str:
|
|
|
|
import sys
|
|
|
|
|
|
|
|
if sys.argv[-1] == "--sample":
|
2023-12-03 04:12:04 +00:00
|
|
|
return f"samples/day{day:02}.txt"
|
2023-12-01 15:31:20 +00:00
|
|
|
else:
|
2023-12-03 04:12:04 +00:00
|
|
|
return f"full/day{day:02}.txt"
|
2023-12-01 15:31:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
#############
|
|
|
|
def load_char_matrix(f):
|
|
|
|
my_file = []
|
|
|
|
for line in f:
|
|
|
|
my_file.append(line.rstrip())
|
|
|
|
return [list(x) for x in my_file]
|
|
|
|
|
|
|
|
|
|
|
|
def load_file_char_matrix(name):
|
|
|
|
with open(name, "r") as f:
|
|
|
|
return load_char_matrix(f)
|
|
|
|
|
|
|
|
|
|
|
|
def load_int_matrix(f):
|
|
|
|
my_file = []
|
|
|
|
for line in f:
|
|
|
|
my_file.append(line.rstrip())
|
|
|
|
return [list(map(int, x)) for x in my_file]
|
|
|
|
|
|
|
|
|
|
|
|
def load_file_int_matrix(name):
|
|
|
|
with open(name, "r") as f:
|
|
|
|
return load_int_matrix(f)
|
|
|
|
|
|
|
|
|
|
|
|
def load_word_matrix(f):
|
|
|
|
my_file = []
|
|
|
|
for line in f:
|
|
|
|
my_file.append(line.rstrip())
|
|
|
|
return [x.split(" ") for x in my_file]
|
|
|
|
|
|
|
|
|
|
|
|
def load_file_word_matrix(name):
|
|
|
|
with open(name, "r") as f:
|
|
|
|
return load_word_matrix(f)
|
|
|
|
|
|
|
|
|
|
|
|
#############
|
|
|
|
|
|
|
|
|
|
|
|
def rotate(WHAT, times=1):
|
|
|
|
what = WHAT
|
|
|
|
for x in range(times):
|
|
|
|
what = list(zip(*what[::-1]))
|
|
|
|
return what
|
|
|
|
|
|
|
|
|
|
|
|
@contextmanager
|
|
|
|
def elapsed_timer():
|
|
|
|
start = default_timer()
|
|
|
|
elapser = lambda: default_timer() - start
|
|
|
|
yield lambda: elapser()
|
|
|
|
end = default_timer()
|
|
|
|
elapser = lambda: end - start
|
|
|
|
|
|
|
|
|
2023-12-08 18:42:42 +00:00
|
|
|
def render_cubes(maxX, maxY, maxZ, my_cubes):
|
2023-12-01 15:31:20 +00:00
|
|
|
from mpl_toolkits.mplot3d import Axes3D
|
|
|
|
import numpy as np
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
|
2023-12-08 18:42:42 +00:00
|
|
|
|
|
|
|
def cuboid_data(o, size=(1, 1, 1)):
|
|
|
|
X = [
|
|
|
|
[[0, 1, 0], [0, 0, 0], [1, 0, 0], [1, 1, 0]],
|
|
|
|
[[0, 0, 0], [0, 0, 1], [1, 0, 1], [1, 0, 0]],
|
|
|
|
[[1, 0, 1], [1, 0, 0], [1, 1, 0], [1, 1, 1]],
|
|
|
|
[[0, 0, 1], [0, 0, 0], [0, 1, 0], [0, 1, 1]],
|
|
|
|
[[0, 1, 0], [0, 1, 1], [1, 1, 1], [1, 1, 0]],
|
|
|
|
[[0, 1, 1], [0, 0, 1], [1, 0, 1], [1, 1, 1]],
|
|
|
|
]
|
2023-12-01 15:31:20 +00:00
|
|
|
X = np.array(X).astype(float)
|
|
|
|
for i in range(3):
|
2023-12-08 18:42:42 +00:00
|
|
|
X[:, :, i] *= size[i]
|
2023-12-01 15:31:20 +00:00
|
|
|
X += np.array(o)
|
|
|
|
return X
|
2023-12-08 18:42:42 +00:00
|
|
|
|
|
|
|
def plotCubeAt(positions, sizes=None, colors=None, **kwargs):
|
|
|
|
if not isinstance(colors, (list, np.ndarray)):
|
|
|
|
colors = ["C0"] * len(positions)
|
|
|
|
if not isinstance(sizes, (list, np.ndarray)):
|
|
|
|
sizes = [(1, 1, 1)] * len(positions)
|
2023-12-01 15:31:20 +00:00
|
|
|
g = []
|
2023-12-08 18:42:42 +00:00
|
|
|
for p, s, c in zip(positions, sizes, colors):
|
|
|
|
g.append(cuboid_data(p, size=s))
|
|
|
|
return Poly3DCollection(
|
|
|
|
np.concatenate(g), facecolors=np.repeat(colors, 6, axis=0), **kwargs
|
|
|
|
)
|
|
|
|
|
2023-12-01 15:31:20 +00:00
|
|
|
N1 = maxX
|
|
|
|
N2 = maxY
|
|
|
|
N3 = maxZ
|
2023-12-08 18:42:42 +00:00
|
|
|
ma = np.random.choice([0, 1], size=(N1, N2, N3), p=[0.99, 0.01])
|
|
|
|
x, y, z = np.indices((N1, N2, N3)) - 0.5
|
|
|
|
# positions = np.c_[x[ma==1],y[ma==1],z[ma==1]]
|
2023-12-01 15:31:20 +00:00
|
|
|
positions = np.c_[my_cubes]
|
2023-12-08 18:42:42 +00:00
|
|
|
colors = np.random.rand(len(positions), 3)
|
|
|
|
|
2023-12-01 15:31:20 +00:00
|
|
|
fig = plt.figure()
|
2023-12-08 18:42:42 +00:00
|
|
|
ax = fig.add_subplot(projection="3d")
|
|
|
|
ax.set_aspect("equal")
|
|
|
|
|
|
|
|
pc = plotCubeAt(positions, colors=colors, edgecolor="k")
|
2023-12-01 15:31:20 +00:00
|
|
|
ax.add_collection3d(pc)
|
|
|
|
|
2023-12-08 18:42:42 +00:00
|
|
|
ax.set_xlim([0, maxX])
|
|
|
|
ax.set_ylim([0, maxY])
|
|
|
|
ax.set_zlim([0, maxZ])
|
|
|
|
# plotMatrix(ax, ma)
|
|
|
|
# ax.voxels(ma, edgecolor="k")
|
2023-12-01 15:31:20 +00:00
|
|
|
|
2023-12-08 18:42:42 +00:00
|
|
|
plt.show()
|