day12 not pretty at alllll

This commit is contained in:
Tyrel Souza 2022-12-12 02:41:14 -05:00
parent 75088a6215
commit 491530d857
18 changed files with 588 additions and 236 deletions

View File

@ -1,9 +1,11 @@
import shared import shared
from pprint import pprint as pp from pprint import pprint as pp
def run(SOMETHING): def run(SOMETHING):
pp(SOMETHING) pp(SOMETHING)
def main(): def main():
spl = lambda y: [int(w) for w in y] spl = lambda y: [int(w) for w in y]
rows = [row.rstrip().split() for row in shared.load(3)] rows = [row.rstrip().split() for row in shared.load(3)]

View File

@ -3,6 +3,7 @@ import imageio
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
class Animate: class Animate:
def __init__(self, mx, day="CHANGEME"): def __init__(self, mx, day="CHANGEME"):
self.mx = mx self.mx = mx
@ -14,7 +15,7 @@ class Animate:
def add_frame(self, frame): def add_frame(self, frame):
self.f_count += 1 self.f_count += 1
self.write_frame(frame) self.write_frame(frame)
def write_frame(self, frame): def write_frame(self, frame):
current = np.zeros_like(self.mx) current = np.zeros_like(self.mx)
@ -24,13 +25,17 @@ class Animate:
fig, ax = plt.subplots() fig, ax = plt.subplots()
ax.imshow(current, cmap=plt.cm.gray) ax.imshow(current, cmap=plt.cm.gray)
ax.axis("off") ax.axis("off")
_figpath = (f"gif-{self.day}/{self.f_count:05}.png") _figpath = f"gif-{self.day}/{self.f_count:05}.png"
plt.savefig(_figpath) plt.savefig(_figpath)
plt.close() plt.close()
def animate(self, frameskip=1): def animate(self, frameskip=1):
with imageio.get_writer(f"gif-{self.day}/day{self.day}.gif", mode="I") as writer: with imageio.get_writer(
names = [f"gif-{self.day}/{x:05}.png" for x in range(0,self.f_count, frameskip)] f"gif-{self.day}/day{self.day}.gif", mode="I"
) as writer:
names = [
f"gif-{self.day}/{x:05}.png" for x in range(0, self.f_count, frameskip)
]
print(names) print(names)
for filename in names: for filename in names:
try: try:

View File

@ -6,7 +6,7 @@ def run(rows):
elves = [] elves = []
current_elf = 0 current_elf = 0
for row in rows: for row in rows:
if row == '': if row == "":
elves.append(current_elf) elves.append(current_elf)
current_elf = 0 current_elf = 0
continue continue
@ -15,14 +15,13 @@ def run(rows):
three = 0 three = 0
for x in range(3): for x in range(3):
most = max(elves) most = max(elves)
idx = elves.index(most) idx = elves.index(most)
elves.pop(idx) elves.pop(idx)
three += most three += most
print(three) print(three)
def main(): def main():
with open(shared.get_fname(1), "r") as f: with open(shared.get_fname(1), "r") as f:
rows = [x.rstrip() for x in f.readlines()] rows = [x.rstrip() for x in f.readlines()]

View File

@ -10,31 +10,18 @@ tie = "Y"
win = "Z" win = "Z"
Moves = { Moves = {
"A":rock, "A": rock,
"B":paper, "B": paper,
"C":scissors, "C": scissors,
"X": rock,
"X":rock, "Y": paper,
"Y":paper, "Z": scissors,
"Z":scissors,
} }
Scores = { Scores = {rock: 1, paper: 2, scissors: 3}
rock: 1,
paper: 2,
scissors: 3
}
LosesTo = { LosesTo = {rock: paper, paper: scissors, scissors: rock}
rock: paper, WinsTo = {paper: rock, scissors: paper, rock: scissors}
paper: scissors,
scissors: rock
}
WinsTo = {
paper: rock,
scissors: paper,
rock: scissors
}
def winner(opponent, me): def winner(opponent, me):
@ -42,11 +29,16 @@ def winner(opponent, me):
return 3 + Scores[me] return 3 + Scores[me]
# wins # wins
if (opponent == rock and me == paper) or (opponent == paper and me == scissors) or (opponent == scissors and me == rock): if (
(opponent == rock and me == paper)
or (opponent == paper and me == scissors)
or (opponent == scissors and me == rock)
):
return 6 + Scores[me] return 6 + Scores[me]
return 0 + Scores[me] return 0 + Scores[me]
def which_move(opponent, me): def which_move(opponent, me):
if me == lose: if me == lose:
return WinsTo[Moves[opponent]] return WinsTo[Moves[opponent]]
@ -61,11 +53,12 @@ def run(moves):
for move in moves: for move in moves:
opponent, me = move opponent, me = move
my_move = which_move(opponent, me) my_move = which_move(opponent, me)
o_move = Moves[opponent] o_move = Moves[opponent]
pts = winner(o_move, my_move) pts = winner(o_move, my_move)
score += pts score += pts
print(score) print(score)
def main(): def main():
rows = [row.rstrip().split() for row in shared.load(2)] rows = [row.rstrip().split() for row in shared.load(2)]
run(rows) run(rows)

View File

@ -4,26 +4,33 @@ R = "A"
P = "B" P = "B"
S = "C" S = "C"
X = "X" # lose X = "X" # lose
Y = "Y" # tie Y = "Y" # tie
Z = "Z" # win Z = "Z" # win
Moves = { Moves = {
R: {X:S, Y:R, Z:P}, R: {X: S, Y: R, Z: P},
P: {X:R, Y:P, Z:S}, P: {X: R, Y: P, Z: S},
S: {X:P, Y:S, Z:R}, S: {X: P, Y: S, Z: R},
} }
Scores = { Scores = {
R: 1, P: 2, S: 3, X: 0, Y: 3, Z: 6, R: 1,
P: 2,
S: 3,
X: 0,
Y: 3,
Z: 6,
} }
def run(moves): def run(moves):
score = 0 score = 0
for o, a in moves: for o, a in moves:
score += Scores[Moves[o][a]] + Scores[a] score += Scores[Moves[o][a]] + Scores[a]
print(score) print(score)
def main(): def main():
rows = [row.rstrip().split() for row in shared.load(2)] rows = [row.rstrip().split() for row in shared.load(2)]
run(rows) run(rows)

View File

@ -4,17 +4,18 @@ import string
def part1(rucksacks): def part1(rucksacks):
total = 0 total = 0
for comp1,comp2 in [(r[:len(r)//2], r[len(r)//2:]) for r in rucksacks]: for comp1, comp2 in [(r[: len(r) // 2], r[len(r) // 2 :]) for r in rucksacks]:
c1 = set(x for x in comp1) c1 = set(x for x in comp1)
c2 = set(x for x in comp2) c2 = set(x for x in comp2)
match = list(c1.intersection(c2))[0] match = list(c1.intersection(c2))[0]
total += string.ascii_letters.index(match) + 1 total += string.ascii_letters.index(match) + 1
print(total) print(total)
def part2(rucksacks): def part2(rucksacks):
total = 0 total = 0
for idx in range(0, len(rucksacks), 3): for idx in range(0, len(rucksacks), 3):
r1,r2,r3 = rucksacks[idx:idx+3] r1, r2, r3 = rucksacks[idx : idx + 3]
c1 = set(x for x in r1) c1 = set(x for x in r1)
c2 = set(x for x in r2) c2 = set(x for x in r2)
c3 = set(x for x in r3) c3 = set(x for x in r3)
@ -28,5 +29,6 @@ def main():
part1(rows) part1(rows)
part2(rows) part2(rows)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -4,27 +4,27 @@ import shared
def part1(x): def part1(x):
internal = 0 internal = 0
for pair in x: for pair in x:
l,r = pair.split(",") l, r = pair.split(",")
l1,l2 = map(int, l.split("-")) l1, l2 = map(int, l.split("-"))
r1,r2 = map(int, r.split("-")) r1, r2 = map(int, r.split("-"))
if l1 <= r1 and l2 >= r2: if l1 <= r1 and l2 >= r2:
internal += 1 internal += 1
elif r1 <= l1 and r2 >= l2: elif r1 <= l1 and r2 >= l2:
internal += 1 internal += 1
print(internal) print(internal)
def part2(x): def part2(x):
internal = 0 internal = 0
for pair in x: for pair in x:
l,r = pair.split(",") l, r = pair.split(",")
ll = list(sorted(map(int, l.split("-")))) ll = list(sorted(map(int, l.split("-"))))
rl = list(sorted(map(int, r.split("-")))) rl = list(sorted(map(int, r.split("-"))))
set1 = set(range(ll[0], ll[1]+1)) set1 = set(range(ll[0], ll[1] + 1))
set2 = set(range(rl[0], rl[1]+1)) set2 = set(range(rl[0], rl[1] + 1))
if bool(set1 & set2): if bool(set1 & set2):
internal +=1 internal += 1
print(internal) print(internal)

150
2022/python/day05.psg.py Normal file
View File

@ -0,0 +1,150 @@
from pprint import pprint as pp
import PySimpleGUI as sg
from shared import load_rows
from scanf import scanf
from string import ascii_letters
import re
WATCHERS = {}
OUTPUT = []
def load_crates(x):
done_crates = False
crates = []
instructions = []
for row in x:
if done_crates:
instructions.append(row)
else:
if row == "":
done_crates = True
else:
crates.append(row)
crates.pop()
return crates, instructions
def to_lists(crates):
parsed = []
reg = re.compile(r"[\([{})\]]")
for row in crates:
parsed.append([x for x in reg.sub(" ", row)])
parsed = list(zip(*parsed[::-1]))
parsed = list(zip(*parsed[::-1]))
parsed = list(zip(*parsed[::-1]))
cleaned1 = [[x for x in y if x.strip()] for y in parsed if y]
cleaned2 = [x for x in cleaned1 if x != []][::-1]
return cleaned2
def parse_instructions(crates, instructions):
for instruction in instructions:
count, _from, _to = scanf("move %d from %d to %d", instruction)
update_watchers("count", count)
update_output(" ".join(map(str, (count, _from, _to))))
_from -= 1 # 1 based yo
_to -= 1
for x in range(count):
value = crates[_from].pop(0)
crates[_to].insert(0, value)
return crates
def parse_instructions_pt2(crates, instructions):
for instruction in instructions:
count, _from, _to = scanf("move %d from %d to %d", instruction)
_from -= 1 # 1 based yo
_to -= 1
moving = crates[_from][:count]
update_output(" ".join(map(str, (instruction, moving))))
for x in range(count):
crates[_from].pop(0)
for x in reversed(moving):
crates[_to].insert(0, x)
return crates
def part1(x):
crates, instructions = load_crates(x)
crates = to_lists(crates)
crates = parse_instructions(crates, instructions)
update_output("".join([c[0] for c in crates]))
def part2(x):
crates, instructions = load_crates(x)
crates = parse_instructions_pt2(crates, instructions)
update_output("".join([c[0] for c in crates]))
def main():
rows = load_rows(5)
sg_window(rows)
sg.Window("Day5")
sg.theme("DarkAmber")
watch_column = [
[sg.Text("Watch Column")],
[sg.Text("------------")],
[sg.Text("", key="-WATCH-")],
]
output_column = [
[sg.Text("Output Column")],
[sg.Text("------------")],
[sg.Text("", key="-OUTPUT-")],
]
layout = [
[sg.Button("Part1"), sg.Button("Part2"), sg.Button("X")],
[
sg.Column(watch_column),
sg.VSeperator(),
sg.Column(output_column),
],
]
window = sg.Window("App", layout)
def update_output(new):
new = new.split("\n")
global OUTPUT
OUTPUT.extend(new)
if len(OUTPUT) > 40:
OUTPUT = OUTPUT[len(new) :]
window["-OUTPUT-"].update("\n".join(OUTPUT))
def watcher_to_string():
s = ""
for k, v in WATCHERS.items():
s += f"{k}:{v}\n"
return s
def update_watchers(k, v):
WATCHERS[k] = v
window["-WATCH-"].update(watcher_to_string())
def sg_window(rows):
while True:
event, values = window.Read()
if event == "X" or event == sg.WIN_CLOSED:
break
if event == "Part1":
part1(rows)
if event == "Part2":
part2(rows)
window.Close()
# part1(rows)
# part2(rows)
if __name__ == "__main__":
main()

View File

@ -13,41 +13,44 @@ def load_crates(x):
if done_crates: if done_crates:
instructions.append(row) instructions.append(row)
else: else:
if row == '': if row == "":
done_crates = True done_crates = True
else: else:
crates.append(row) crates.append(row)
crates.pop() crates.pop()
return crates, instructions return crates, instructions
def to_lists(crates): def to_lists(crates):
parsed = [] parsed = []
reg = re.compile(r"[\([{})\]]") reg = re.compile(r"[\([{})\]]")
for row in crates: for row in crates:
parsed.append([x for x in reg.sub(" ",row)]) parsed.append([x for x in reg.sub(" ", row)])
parsed = list(zip(*parsed[::-1])) parsed = list(zip(*parsed[::-1]))
parsed = list(zip(*parsed[::-1])) parsed = list(zip(*parsed[::-1]))
parsed = list(zip(*parsed[::-1])) parsed = list(zip(*parsed[::-1]))
cleaned1 = [[x for x in y if x.strip()] for y in parsed if y] cleaned1 = [[x for x in y if x.strip()] for y in parsed if y]
cleaned2 = [x for x in cleaned1 if x != []][::-1] cleaned2 = [x for x in cleaned1 if x != []][::-1]
return cleaned2 return cleaned2
def parse_instructions(crates, instructions): def parse_instructions(crates, instructions):
for instruction in instructions: for instruction in instructions:
count,_from,_to = scanf("move %d from %d to %d", instruction) count, _from, _to = scanf("move %d from %d to %d", instruction)
print(count,_from,_to) print(count, _from, _to)
_from -=1 # 1 based yo _from -= 1 # 1 based yo
_to -=1 _to -= 1
for x in range(count): for x in range(count):
value = crates[_from].pop(0) value = crates[_from].pop(0)
crates[_to].insert(0, value) crates[_to].insert(0, value)
return crates return crates
def parse_instructions_pt2(crates, instructions): def parse_instructions_pt2(crates, instructions):
for instruction in instructions: for instruction in instructions:
count,_from,_to = scanf("move %d from %d to %d", instruction) count, _from, _to = scanf("move %d from %d to %d", instruction)
_from -=1 # 1 based yo _from -= 1 # 1 based yo
_to -=1 _to -= 1
moving = crates[_from][:count] moving = crates[_from][:count]
print(instruction, moving) print(instruction, moving)
for x in range(count): for x in range(count):
@ -56,7 +59,7 @@ def parse_instructions_pt2(crates, instructions):
crates[_to].insert(0, x) crates[_to].insert(0, x)
return crates return crates
def part1(x): def part1(x):
crates, instructions = load_crates(x) crates, instructions = load_crates(x)
@ -64,7 +67,7 @@ def part1(x):
crates = parse_instructions(crates, instructions) crates = parse_instructions(crates, instructions)
print([c[0] for c in crates]) print([c[0] for c in crates])
def part2(x): def part2(x):
crates, instructions = load_crates(x) crates, instructions = load_crates(x)
crates = to_lists(crates) crates = to_lists(crates)
@ -74,7 +77,7 @@ def part2(x):
def main(): def main():
rows = load_rows(5) rows = load_rows(5)
#part1(rows) # part1(rows)
part2(rows) part2(rows)

View File

@ -1,14 +1,17 @@
from shared import load_rows from shared import load_rows
def part1(row, group_size=4): def part1(row, group_size=4):
for x in range(len(row)): for x in range(len(row)):
if (len(set(row[x:x+group_size])) == group_size): if len(set(row[x : x + group_size])) == group_size:
print(x+group_size) print(x + group_size)
break break
def part2(row): def part2(row):
part1(row, 14) part1(row, 14)
def main(): def main():
rows = load_rows(6) rows = load_rows(6)
for row in rows: for row in rows:

View File

@ -8,77 +8,80 @@ from functools import reduce
import operator import operator
PWD = [] PWD = []
FS = { "/": {".":{"size":0, "files":[]}} } FS = {"/": {".": {"size": 0, "files": []}}}
def get_keys(input_dict): def get_keys(input_dict):
for key, value in input_dict.items(): for key, value in input_dict.items():
if isinstance(value, dict): if isinstance(value, dict):
for subkey in get_keys(value): for subkey in get_keys(value):
yield key + ',' + subkey yield key + "," + subkey
else: else:
if key in ("files"): if key in ("files"):
continue continue
yield f"{value}" yield f"{value}"
def getFromDict(mapList): def getFromDict(mapList):
return reduce(operator.getitem, mapList, FS) return reduce(operator.getitem, mapList, FS)
def setInDict(mapList, value): def setInDict(mapList, value):
getFromDict(mapList[:-1])[mapList[-1]] = value getFromDict(mapList[:-1])[mapList[-1]] = value
def addInDict(mapList, filename, value): def addInDict(mapList, filename, value):
try: try:
v = getFromDict(mapList[:-1])[mapList[-1]] v = getFromDict(mapList[:-1])[mapList[-1]]
v += value v += value
getFromDict(mapList[:-1])[mapList[-1]] = v getFromDict(mapList[:-1])[mapList[-1]] = v
except KeyError: except KeyError:
getFromDict(mapList[:-1])["."] = {"size": 0, "files":[]} getFromDict(mapList[:-1])["."] = {"size": 0, "files": []}
v = getFromDict(mapList[:-1])[mapList[-1]] v = getFromDict(mapList[:-1])[mapList[-1]]
v["size"] += 0 # Value v["size"] += 0 # Value
v["files"].append(f"{filename}:{value}") v["files"].append(f"{filename}:{value}")
getFromDict(mapList[:-1])[mapList[-1]] = v getFromDict(mapList[:-1])[mapList[-1]] = v
except TypeError: except TypeError:
v = getFromDict(mapList[:-1])["."] v = getFromDict(mapList[:-1])["."]
v["size"] += 0 # value v["size"] += 0 # value
v["files"].append(f"{filename}:{value}") v["files"].append(f"{filename}:{value}")
getFromDict(mapList[:-1])[mapList[-1]] = v getFromDict(mapList[:-1])[mapList[-1]] = v
def part1(rows): def part1(rows):
build_fs(rows) build_fs(rows)
#calculate_directories() # calculate_directories()
def calculate_directories(): def calculate_directories():
keys = list(get_keys(FS)) keys = list(get_keys(FS))
new_FS = {} new_FS = {}
for key in keys: for key in keys:
pwd = key.split(",") pwd = key.split(",")
size = int(pwd.pop()) # split out size size = int(pwd.pop()) # split out size
pwd.pop() # remove . pwd.pop() # remove .
pwd_key = ",".join(pwd) pwd_key = ",".join(pwd)
parent = ",".join(pwd[:-1]) parent = ",".join(pwd[:-1])
new_FS[pwd_key] = {"size":size, "full_size":size, "parent":parent} new_FS[pwd_key] = {"size": size, "full_size": size, "parent": parent}
print("made") print("made")
#pp(new_FS) # pp(new_FS)
#print("----") # print("----")
#for pwd, directory in new_FS.items(): # for pwd, directory in new_FS.items():
# print(pwd, "\t", directory['parent']) # print(pwd, "\t", directory['parent'])
print(new_FS.keys()) print(new_FS.keys())
print("keys^") print("keys^")
for pwd, directory in new_FS.items(): for pwd, directory in new_FS.items():
parent = directory['parent'] parent = directory["parent"]
if parent: if parent:
print(parent) print(parent)
#print(f"{pwd}:{parent} Adding {directory['size']} to fullsize {new_FS[parent]['full_size']}") # print(f"{pwd}:{parent} Adding {directory['size']} to fullsize {new_FS[parent]['full_size']}")
new_FS[parent]["size"] += directory["size"] new_FS[parent]["size"] += directory["size"]
print("added sizes") print("added sizes")
sizes = [] sizes = []
for k,v in new_FS.items(): for k, v in new_FS.items():
sizes.append(v['size']) sizes.append(v["size"])
total = 0 total = 0
for size in sizes: for size in sizes:
@ -86,7 +89,8 @@ def calculate_directories():
print("+", size) print("+", size)
total += size total += size
print("=" ,total) print("=", total)
def build_fs(rows): def build_fs(rows):
LS_ING = False LS_ING = False
@ -102,7 +106,7 @@ def build_fs(rows):
PWD.pop() PWD.pop()
else: else:
PWD.append(parts[2]) PWD.append(parts[2])
#print(PWD) # print(PWD)
elif parts[1] == "ls": elif parts[1] == "ls":
LS_ING = True LS_ING = True
continue continue
@ -113,6 +117,7 @@ def build_fs(rows):
add_file(parts[1], int(parts[0])) add_file(parts[1], int(parts[0]))
jp(FS) jp(FS)
def jp(d): def jp(d):
output = json.dumps(FS, indent=4) output = json.dumps(FS, indent=4)
output2 = re.sub(r'": \[\s+', '": [', output) output2 = re.sub(r'": \[\s+', '": [', output)
@ -123,26 +128,28 @@ def jp(d):
def add_directory(dirname): def add_directory(dirname):
temp_new_path = PWD + [dirname] temp_new_path = PWD + [dirname]
setInDict(temp_new_path, {".":{"size":0, "files":[]}}) setInDict(temp_new_path, {".": {"size": 0, "files": []}})
def add_file(filename, size): def add_file(filename, size):
#print(".", PWD, filename, size) # print(".", PWD, filename, size)
mapList = PWD + ["."] mapList = PWD + ["."]
addInDict(mapList, filename, size) addInDict(mapList, filename, size)
curr = getFromDict(mapList[:-1]) curr = getFromDict(mapList[:-1])
print(curr) print(curr)
#print(curr) # print(curr)
s = curr["."] s = curr["."]
s["size"] += size s["size"] += size
print(size,s) print(size, s)
tmp = mapList + ["size"] tmp = mapList + ["size"]
setInDict(mapList, s) setInDict(mapList, s)
print("-----") print("-----")
def part2(row): def part2(row):
pass pass
def main(): def main():
rows = load_rows(7) rows = load_rows(7)
part1(rows) part1(rows)

View File

@ -3,16 +3,15 @@ import shared
import matrix import matrix
def part1(mx): def part1(mx):
SIZE=len(mx) SIZE = len(mx)
MAX_IDX = SIZE -1 MAX_IDX = SIZE - 1
data = matrix.matrix_of_size(SIZE, SIZE) data = matrix.matrix_of_size(SIZE, SIZE)
data = matrix.set_matrix_dict(data) data = matrix.set_matrix_dict(data)
for row in range(SIZE): for row in range(SIZE):
for col in range(SIZE): for col in range(SIZE):
data[row][col] = { "l": True, "r": True, "u": True, "d": True } data[row][col] = {"l": True, "r": True, "u": True, "d": True}
for row, _row in enumerate(mx): for row, _row in enumerate(mx):
# Skip outer edges # Skip outer edges
@ -28,7 +27,7 @@ def part1(mx):
trees_u_indexes = list(range(0, row)) trees_u_indexes = list(range(0, row))
trees_l_indexes = list(range(0, col)) trees_l_indexes = list(range(0, col))
trees_d_indexes = list(range(MAX_IDX, row, -1)) trees_d_indexes = list(range(MAX_IDX, row, -1))
trees_r_indexes = list(range(col+1, SIZE)) trees_r_indexes = list(range(col + 1, SIZE))
# Get the trees in the line # Get the trees in the line
trees_u = [mx[y][col] for y in trees_u_indexes] trees_u = [mx[y][col] for y in trees_u_indexes]
@ -45,50 +44,50 @@ def part1(mx):
# if there's anything as tall, or taller than this tree in that line # if there's anything as tall, or taller than this tree in that line
# then it's not visible # then it's not visible
if highest_u >= _val: if highest_u >= _val:
data[row][col]["u"] = False data[row][col]["u"] = False
if highest_l >= _val: if highest_l >= _val:
data[row][col]["l"] = False data[row][col]["l"] = False
if highest_d >= _val: if highest_d >= _val:
data[row][col]["d"] = False data[row][col]["d"] = False
if highest_r >= _val: if highest_r >= _val:
data[row][col]["r"] = False data[row][col]["r"] = False
# count visible # count visible
count = 0 count = 0
for row in range(SIZE): for row in range(SIZE):
for col in range(SIZE): for col in range(SIZE):
u = data[row][col]["u"] u = data[row][col]["u"]
l = data[row][col]["l"] l = data[row][col]["l"]
d = data[row][col]["d"] d = data[row][col]["d"]
r = data[row][col]["r"] r = data[row][col]["r"]
if any((r,l,u,d)): if any((r, l, u, d)):
count += 1 count += 1
print(count) print(count)
def part2(mx): def part2(mx):
SIZE=len(mx) SIZE = len(mx)
MAX_IDX = SIZE -1 MAX_IDX = SIZE - 1
data = matrix.matrix_of_size(SIZE, SIZE) data = matrix.matrix_of_size(SIZE, SIZE)
data = matrix.set_matrix_dict(data) data = matrix.set_matrix_dict(data)
high_score = 0 high_score = 0
for row in range(SIZE): for row in range(SIZE):
for col in range(SIZE): for col in range(SIZE):
data[row][col] = { "value": mx[row][col]} data[row][col] = {"value": mx[row][col]}
for row, _row in enumerate(mx): for row, _row in enumerate(mx):
for col, _val in enumerate(mx[row]): for col, _val in enumerate(mx[row]):
# Get a list of indexes in the current direction to check # Get a list of indexes in the current direction to check
# TODO: slice # TODO: slice
trees_u_indexes = list(range(0, row)) trees_u_indexes = list(range(0, row))
trees_l_indexes = list(range(0,col)) trees_l_indexes = list(range(0, col))
trees_d_indexes = list(range(MAX_IDX, row, -1)) trees_d_indexes = list(range(MAX_IDX, row, -1))
trees_r_indexes = list(range(col+1, SIZE)) trees_r_indexes = list(range(col + 1, SIZE))
# Grab the trees potentially in sight # Grab the trees potentially in sight
trees_u = [mx[y][col] for y in trees_u_indexes] trees_u = [mx[y][col] for y in trees_u_indexes]
@ -103,17 +102,17 @@ def part2(mx):
data[row][col]["r"] = trees_r data[row][col]["r"] = trees_r
# Calculate score # Calculate score
score = 1 # identity yoooo score = 1 # identity yoooo
cell = data[row][col] cell = data[row][col]
val = cell['value'] val = cell["value"]
# Get the score of visible trees in each direction # Get the score of visible trees in each direction
for direction in ("u","l","d","r"): for direction in ("u", "l", "d", "r"):
in_line = cell[direction] in_line = cell[direction]
if not in_line: if not in_line:
# we're on an edge # we're on an edge
score = 0 score = 0
break break
line_score = 0 line_score = 0
for idx, tree in enumerate(in_line): for idx, tree in enumerate(in_line):
# for every tree, check if its as tall or taller, # for every tree, check if its as tall or taller,
@ -126,17 +125,18 @@ def part2(mx):
high_score = score high_score = score
print(high_score) print(high_score)
def part2_with_fixes(mx): def part2_with_fixes(mx):
SIZE=len(mx) SIZE = len(mx)
MAX_IDX = SIZE -1 MAX_IDX = SIZE - 1
data = matrix.matrix_of_size(SIZE, SIZE) data = matrix.matrix_of_size(SIZE, SIZE)
data = matrix.set_matrix_dict(data) data = matrix.set_matrix_dict(data)
high_score = 0 high_score = 0
for row in range(SIZE): for row in range(SIZE):
for col in range(SIZE): for col in range(SIZE):
data[row][col] = { "value": mx[row][col]} data[row][col] = {"value": mx[row][col]}
for row, _row in enumerate(mx): for row, _row in enumerate(mx):
for col, _val in enumerate(mx[row]): for col, _val in enumerate(mx[row]):
@ -148,16 +148,16 @@ def part2_with_fixes(mx):
data[row][col]["r"] = lineofsight["R"] data[row][col]["r"] = lineofsight["R"]
# Calculate score # Calculate score
score = 1 # identity yoooo score = 1 # identity yoooo
val = data[row][col]['value'] val = data[row][col]["value"]
# Get the score of visible trees in each direction # Get the score of visible trees in each direction
for direction in ("u","l","d","r"): for direction in ("u", "l", "d", "r"):
in_line = data[row][col][direction] in_line = data[row][col][direction]
if not in_line: if not in_line:
# we're on an edge # we're on an edge
score = 0 score = 0
break break
line_score = 0 line_score = 0
for idx, tree in enumerate(in_line): for idx, tree in enumerate(in_line):
# for every tree, check if its as tall or taller, # for every tree, check if its as tall or taller,
@ -170,6 +170,7 @@ def part2_with_fixes(mx):
high_score = score high_score = score
print(high_score) print(high_score)
def main(): def main():
mx = matrix.load_matrix_file(shared.get_fname(8)) mx = matrix.load_matrix_file(shared.get_fname(8))
with shared.elapsed_timer() as elapsed: with shared.elapsed_timer() as elapsed:
@ -183,6 +184,5 @@ def main():
print(elapsed()) print(elapsed())
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -5,28 +5,28 @@ import shared
import matrix import matrix
MATRIX_SIZE = 400 MATRIX_SIZE = 400
ATRIX_SIZE = 40 # sample ATRIX_SIZE = 40 # sample
HALF = MATRIX_SIZE // 2 HALF = MATRIX_SIZE // 2
H = [HALF,HALF] H = [HALF, HALF]
T = [HALF,HALF] T = [HALF, HALF]
# returns (x,y) - so remember to take dx,dy lower # returns (x,y) - so remember to take dx,dy lower
DIRS = { DIRS = {
'U': matrix.M_U, # (0, -1) "U": matrix.M_U, # (0, -1)
'D': matrix.M_D, "D": matrix.M_D,
'L': matrix.M_L, "L": matrix.M_L,
'R': matrix.M_R, "R": matrix.M_R,
"UR": matrix.M_UR, # (+1, -1)
'UR': matrix.M_UR, # (+1, -1) "DR": matrix.M_DR,
'DR': matrix.M_DR, "UL": matrix.M_UL,
'UL': matrix.M_UL, "DL": matrix.M_DL,
'DL': matrix.M_DL,
} }
def part1(steps): def part1(steps):
field = matrix.matrix_of_size(MATRIX_SIZE,MATRIX_SIZE) field = matrix.matrix_of_size(MATRIX_SIZE, MATRIX_SIZE)
anim = Animate(field, day="09") anim = Animate(field, day="09")
for direction, amount in steps: for direction, amount in steps:
@ -34,21 +34,21 @@ def part1(steps):
amount = int(amount) amount = int(amount)
for x in range(amount): for x in range(amount):
dx,dy = DIRS[direction] dx, dy = DIRS[direction]
H[0] += dy H[0] += dy
H[1] += dx H[1] += dx
HY,bX = H HY, bX = H
# head is in new position # head is in new position
kY,kX = T kY, kX = T
field[kY][kX] = 1 # 'T' field[kY][kX] = 1 # 'T'
# Check if same # Check if same
if kY == HY and kX == bX: if kY == HY and kX == bX:
continue continue
touching = False touching = False
for _, d in DIRS.items(): for _, d in DIRS.items():
dx,dy = d dx, dy = d
t_y, t_x = H[0]+dy, H[1]+dx t_y, t_x = H[0] + dy, H[1] + dx
if kY == t_y and kX == t_x: if kY == t_y and kX == t_x:
touching = True touching = True
break break
@ -58,66 +58,67 @@ def part1(steps):
# assume the same row/column, no movement needed # assume the same row/column, no movement needed
tY = 0 tY = 0
tX = 0 tX = 0
# if Head X is less than Tail X, move Tail X 1 left # if Head X is less than Tail X, move Tail X 1 left
if bX < kX: if bX < kX:
tX = -1 tX = -1
# if Head X is greater than Tail X, move Tail X 1 left # if Head X is greater than Tail X, move Tail X 1 left
elif bX > kX: elif bX > kX:
tX = 1 tX = 1
# if Head Y is less than Tail Y, move Tail Y 1 up # if Head Y is less than Tail Y, move Tail Y 1 up
if HY < kY: if HY < kY:
tY = -1 tY = -1
# if Head Y is greater than Tail Y, move Tail Y 1 down # if Head Y is greater than Tail Y, move Tail Y 1 down
elif HY > kY: elif HY > kY:
tY = 1 tY = 1
T[0] += tY T[0] += tY
T[1] += tX T[1] += tX
anim.add_frame(field) anim.add_frame(field)
field[T[0]][T[1]] = 1 # mark visited tails field[T[0]][T[1]] = 1 # mark visited tails
print(matrix.sum_matrix(field)) print(matrix.sum_matrix(field))
anim.animate() anim.animate()
def part2(steps): def part2(steps):
field = matrix.matrix_of_size(MATRIX_SIZE,MATRIX_SIZE) field = matrix.matrix_of_size(MATRIX_SIZE, MATRIX_SIZE)
anim = Animate(field, day="09") anim = Animate(field, day="09")
S = [[HALF,HALF],] # HEAD ONLY S = [
[HALF, HALF],
] # HEAD ONLY
_cur_frame = 0 _cur_frame = 0
for x in range(9): for x in range(9):
S.append([HALF,HALF]) S.append([HALF, HALF])
for direction, amount in steps: for direction, amount in steps:
# move HEAD # move HEAD
amount = int(amount) amount = int(amount)
for x in range(amount): for x in range(amount):
HEAD_dx,HEAD_dy = DIRS[direction] HEAD_dx, HEAD_dy = DIRS[direction]
S[0][0] += HEAD_dy S[0][0] += HEAD_dy
S[0][1] += HEAD_dx S[0][1] += HEAD_dx
#print(HEAD_dy,HEAD_dx, S) # print(HEAD_dy,HEAD_dx, S)
# HEAD MOVED one step # HEAD MOVED one step
for knot_idx, _ in enumerate(S): for knot_idx, _ in enumerate(S):
if knot_idx == 0: if knot_idx == 0:
# Skip Head # Skip Head
continue continue
knot = S[knot_idx] knot = S[knot_idx]
kY,kX = knot kY, kX = knot
bY,bX = S[knot_idx-1] bY, bX = S[knot_idx - 1]
# Check if same # Check if same
if kY == bY and kX == bX: if kY == bY and kX == bX:
continue continue
touching = False touching = False
for _, d in DIRS.items(): for _, d in DIRS.items():
dx,dy = d dx, dy = d
t_y, t_x = S[knot_idx-1][0]+dy, S[knot_idx-1][1]+dx t_y, t_x = S[knot_idx - 1][0] + dy, S[knot_idx - 1][1] + dx
if kY == t_y and kX == t_x: if kY == t_y and kX == t_x:
touching = True touching = True
break break
@ -125,36 +126,35 @@ def part2(steps):
continue continue
# assume the same row/column, no movement needed # assume the same row/column, no movement needed
tY, tX = 0,0 tY, tX = 0, 0
# if Head X is less than Tail X, move Tail X 1 left # if Head X is less than Tail X, move Tail X 1 left
if bX < kX: if bX < kX:
tX = -1 tX = -1
# if Head X is greater than Tail X, move Tail X 1 left # if Head X is greater than Tail X, move Tail X 1 left
elif bX > kX: elif bX > kX:
tX = 1 tX = 1
# if Head Y is less than Tail Y, move Tail Y 1 up # if Head Y is less than Tail Y, move Tail Y 1 up
if bY < kY: if bY < kY:
tY = -1 tY = -1
# if Head Y is greater than Tail Y, move Tail Y 1 down # if Head Y is greater than Tail Y, move Tail Y 1 down
elif bY > kY: elif bY > kY:
tY = 1 tY = 1
S[knot_idx][0] += tY S[knot_idx][0] += tY
S[knot_idx][1] += tX S[knot_idx][1] += tX
if _cur_frame % 25 == 0: if _cur_frame % 25 == 0:
anim.add_frame(field) anim.add_frame(field)
_cur_frame += 1 _cur_frame += 1
field[S[-1][0]][S[-1][1]] = 1 # mark visited tails field[S[-1][0]][S[-1][1]] = 1 # mark visited tails
print(matrix.sum_matrix(field)) print(matrix.sum_matrix(field))
anim.animate() anim.animate()
def main(): def main():
rows = [x.split(" ") for x in shared.load_rows(9)] rows = [x.split(" ") for x in shared.load_rows(9)]
#part1(rows) # part1(rows)
part2(rows) part2(rows)

View File

@ -3,9 +3,10 @@ from anim import Animate
import matrix import matrix
cycles = { cycles = {
"noop": 1, "noop": 1,
"addx": 2, "addx": 2,
} }
def part1(x): def part1(x):
X = 1 X = 1
@ -22,23 +23,21 @@ def part1(x):
for x in range(cycles[opcode]): for x in range(cycles[opcode]):
cycle_count += 1 cycle_count += 1
if cycle_count == 20 or ((cycle_count -20) % 40 == 0): if cycle_count == 20 or ((cycle_count - 20) % 40 == 0):
signal_strength.append(cycle_count*X) signal_strength.append(cycle_count * X)
if opcode == "addx": if opcode == "addx":
X += val X += val
print(sum(signal_strength)) print(sum(signal_strength))
def part2(x): def part2(x):
def cycle_to_xy(cycle): def cycle_to_xy(cycle):
x = cycle % 40 x = cycle % 40
y = cycle // 40 y = cycle // 40
return x,y return x, y
screen = matrix.matrix_of_size(40,6) screen = matrix.matrix_of_size(40, 6)
X = 1 X = 1
cycle_count = 0 cycle_count = 0
for step, instruction in enumerate(x): for step, instruction in enumerate(x):
@ -50,8 +49,8 @@ def part2(x):
opcode = instruction opcode = instruction
for x in range(cycles[opcode]): for x in range(cycles[opcode]):
_x,y = cycle_to_xy(cycle_count) _x, y = cycle_to_xy(cycle_count)
criteria = (X-1, X, X+1) criteria = (X - 1, X, X + 1)
cycle_count += 1 cycle_count += 1
if _x in criteria: if _x in criteria:
screen[y][_x] = 1 screen[y][_x] = 1
@ -59,15 +58,16 @@ def part2(x):
if opcode == "addx": if opcode == "addx":
X += val X += val
matrix.ppmx(screen,pad=False, space=False) matrix.ppmx(screen, pad=False, space=False)
anim = Animate(screen, day="10") anim = Animate(screen, day="10")
anim.add_frame(screen) anim.add_frame(screen)
print("wrote gif-10/day10.gif") print("wrote gif-10/day10.gif")
def main(): def main():
rows = [row for row in shared.load(10)] rows = [row for row in shared.load(10)]
part1(rows) part1(rows)
print("%"*40) print("%" * 40)
part2(rows) part2(rows)

View File

@ -29,10 +29,10 @@ def load_monkeys(lines):
try: try:
by = int(line.split(" ")[-1]) by = int(line.split(" ")[-1])
except ValueError: except ValueError:
by = None # know None means by self by = None # know None means by self
if '*' in op: if "*" in op:
operand = operator.mul operand = operator.mul
elif '+' in op: elif "+" in op:
operand = operator.add operand = operator.add
elif line.lstrip().startswith("Test"): elif line.lstrip().startswith("Test"):
div = int(line.split(" ")[-1]) div = int(line.split(" ")[-1])
@ -41,19 +41,14 @@ def load_monkeys(lines):
elif line.lstrip().startswith("If false"): elif line.lstrip().startswith("If false"):
false = int(line.split(" ")[-1]) false = int(line.split(" ")[-1])
monkey = Monkey( monkey = Monkey(
number=count, number=count, items=items, op=operand, by=by, div=div, t=true, f=false
items=items, )
op=operand,
by=by,
div=div,
t=true,
f=false
)
monkeys.append(monkey) monkeys.append(monkey)
count+=1 count += 1
lcm = math.lcm(*[m.div for m in monkeys]) lcm = math.lcm(*[m.div for m in monkeys])
return monkeys, lcm return monkeys, lcm
def part1(lines): def part1(lines):
monkeys, _ = load_monkeys(lines) monkeys, _ = load_monkeys(lines)
@ -78,7 +73,7 @@ def part1(lines):
total = counts[-1] * counts[-2] total = counts[-1] * counts[-2]
print(total) print(total)
def part2(lines): def part2(lines):
monkeys, lcm = load_monkeys(lines) monkeys, lcm = load_monkeys(lines)

116
2022/python/day12.py Normal file
View File

@ -0,0 +1,116 @@
import shared
import matrix
from dijkstar import Graph, find_path, algorithm
#def dj_walk(mx, start, end):
# def next_cost(c, val):
# if val > c+1:
# return 9999
# else:
# return val
#
# start = start[1], start[0]
# end = end[1], end[0]
#
# # Dijkstra from RedBlobGames
# frontier = PriorityQueue()
# frontier.put(start, 0)
# came_from = dict()
# cost_so_far = dict()
# came_from[start] = None
# cost_so_far[start] = 0
# last = None
# while not frontier.empty():
# x, y = frontier.get()
# cur = (x, y)
# if cur == end:
# break
# for _n in matrix.get_neighbors(mx, x=x, y=y, _dict=True):
# nxt = (_n["x"], _n["y"])
# v = _n["value"]
#
# new_cost = next_cost(cost_so_far[cur], v)
# if nxt not in cost_so_far or new_cost < cost_so_far[nxt]:
# cost_so_far[nxt] = new_cost
# priority = new_cost
# frontier.put(nxt, priority)
# came_from[nxt] = cur
# last = cur
# print(len(cost_so_far))
criteria = lambda _cur, _neighbor: _neighbor - _cur <= 1
def build_graph(mx):
graph = Graph()
for y, row in enumerate(mx):
for x, _ in enumerate(row):
neighbors = matrix.valid_neighbors(mx, x=x, y=y, criteria=criteria)
for neighbor in neighbors:
graph.add_edge((y, x), (neighbor['y'],neighbor['x']), 1)
return graph
#SEEN = []
#def walk(mx, y, x, seen=[]):
# print(len(seen))
# valid_next = matrix.valid_neighbors(mx, y, x, criteria=criteria)
# print(valid_next)
# matrix.highlight( mx, red=seen, green=[ *valid_next, ], blue=[ END, ],)
# for next_yx in valid_next:
# if next_yx not in seen:
# seen.append(next_yx)
# _y, _x = next_yx
# walk(mx, _y, _x, seen)
# else:
# seen.append(next_yx)
def elev(yx):
y,x = yx
return mx[y][x]
def part1(mx):
start = matrix.find_in_matrix(mx, "S")
end = matrix.find_in_matrix(mx, "E")
mx[start[0]][start[1]] = "a"
mx[end[0]][end[1]] = "z"
matrix.apply_to_all(mx, lambda x: ord(x) - ord('a'))
#walk(mx, cur[0],cur[0], seen=[(cur[0],cur[1])])
#dj_walk(mx, cur, END)
graph = build_graph(mx)
path = find_path(graph, start, end)
print(len(path.nodes))
def part2(mx):
end = matrix.find_in_matrix(mx, "E")
s = matrix.find_in_matrix(mx, "S")
mx[s[0]][s[1]] = "a"
mx[end[0]][end[1]] = "z"
starts = matrix.find_in_matrix(mx, 'a', one=False)
matrix.apply_to_all(mx, lambda x: ord(x) - ord('a'))
graph = build_graph(mx)
n_counts = []
for start in starts:
#walk(mx, cur[0],cur[0], seen=[(cur[0],cur[1])])
#dj_walk(mx, cur, END)
try:
path = find_path(graph, start, end)
n_counts.append(len(path.nodes)-1)
except algorithm.NoPathError:
pass
print(n_counts)
print(min(n_counts))
def main():
mx = matrix.load_matrix_file(shared.get_fname(12), matrix.split_word_to_chr_list)
#part1(mx)
part2(mx)
if __name__ == "__main__":
main()

View File

@ -1,10 +1,28 @@
from copy import deepcopy
from collections import defaultdict from collections import defaultdict
from typing import List, Dict, Tuple from typing import List, Dict, Tuple
split_word_to_chr_list = lambda y: [w for w in y]
split_word_to_int_list = lambda y: [int(w) for w in y] split_word_to_int_list = lambda y: [int(w) for w in y]
split_line_to_int_list = lambda y: [int(w) for w in y.split(" ") if w] split_line_to_int_list = lambda y: [int(w) for w in y.split(" ") if w]
class colors:
# HEADER = '\033[95m'
BLUE = "\033[94m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
RED = "\033[91m"
ENDC = "\033[0m"
def apply_to_all(mx, func):
for row_num, row in enumerate(mx):
for col_num, val in enumerate(row):
mx[row_num][col_num] = func(val)
def rotate(m, right=True): # -90 def rotate(m, right=True): # -90
""" """
Takes a matrix, and rotates all of the values 90 degrees to the left Takes a matrix, and rotates all of the values 90 degrees to the left
@ -17,7 +35,7 @@ def rotate(m, right=True): # -90
def load_matrix_file(name, func=None): def load_matrix_file(name, func=None):
""" """
Open a file and split all space separated word lists to integers as a matrix Open a file and split all space separated word lists to integers as a matrix
""" """
with open(name, "r") as f: with open(name, "r") as f:
my_file = [] my_file = []
@ -28,13 +46,26 @@ def load_matrix_file(name, func=None):
return [split_word_to_int_list(x) for x in my_file] return [split_word_to_int_list(x) for x in my_file]
def find_in_matrix(mx, what, one=True):
coords = []
for row_num, row in enumerate(mx):
for col_num, val in enumerate(row):
if val == what:
coord = (row_num, col_num)
if one is True:
return coord
else:
coords.append(coord)
return coords
def get_neighbors(matrix, x, y, _dict=False): def get_neighbors(matrix, x, y, _dict=False):
neighbors = [] neighbors = []
# left # left
try: try:
if x - 1 >= 0: if x - 1 >= 0:
if _dict: if _dict:
neighbors.append({'x':x - 1,'y':y,'value':matrix[y][x - 1]}) neighbors.append({"x": x - 1, "y": y, "value": matrix[y][x - 1]})
else: else:
neighbors.append([(x - 1, y), matrix[y][x - 1]]) neighbors.append([(x - 1, y), matrix[y][x - 1]])
except IndexError: except IndexError:
@ -42,7 +73,7 @@ def get_neighbors(matrix, x, y, _dict=False):
# right # right
try: try:
if _dict: if _dict:
neighbors.append({'x':x + 1,'y':y,'value':matrix[y][x + 1]}) neighbors.append({"x": x + 1, "y": y, "value": matrix[y][x + 1]})
else: else:
neighbors.append([(x + 1, y), matrix[y][x + 1]]) neighbors.append([(x + 1, y), matrix[y][x + 1]])
except IndexError: except IndexError:
@ -52,7 +83,7 @@ def get_neighbors(matrix, x, y, _dict=False):
try: try:
if y - 1 >= 0: if y - 1 >= 0:
if _dict: if _dict:
neighbors.append({'x':x,'y':y-1,'value':matrix[y-1][x]}) neighbors.append({"x": x, "y": y - 1, "value": matrix[y - 1][x]})
else: else:
neighbors.append([(x, y - 1), matrix[y - 1][x]]) neighbors.append([(x, y - 1), matrix[y - 1][x]])
except IndexError: except IndexError:
@ -61,7 +92,7 @@ def get_neighbors(matrix, x, y, _dict=False):
# down # down
try: try:
if _dict: if _dict:
neighbors.append({'x':x,'y':y+1,'value':matrix[y+1][x]}) neighbors.append({"x": x, "y": y + 1, "value": matrix[y + 1][x]})
else: else:
neighbors.append([(x, y + 1), matrix[y + 1][x]]) neighbors.append([(x, y + 1), matrix[y + 1][x]])
except IndexError: except IndexError:
@ -69,6 +100,19 @@ def get_neighbors(matrix, x, y, _dict=False):
return neighbors return neighbors
def valid_neighbors(matrix, x, y, criteria=None):
if criteria is None:
raise Exception("Please pass in a lambda for criteria")
cur = matrix[y][x]
neighbors = get_neighbors(matrix, x, y, _dict=True)
valid = []
for neighbor in neighbors:
if criteria(cur, neighbor['value']):
valid.append(neighbor)
return valid
def sum_matrix(mtx): def sum_matrix(mtx):
total = 0 total = 0
for row in mtx: for row in mtx:
@ -80,27 +124,20 @@ M_UL, M_U, M_UR = (-1, -1), (0, -1), (1, -1)
M_L, M_R = (-1, 0), (1, 0) M_L, M_R = (-1, 0), (1, 0)
M_DL, M_D, M_DR = (-1, 1), (0, 1), (1, 1) M_DL, M_D, M_DR = (-1, 1), (0, 1), (1, 1)
def get_neighbor_coords(matrix, c, r, diagonals=True): def get_neighbor_coords(matrix, c, r, diagonals=True):
height = len(matrix) height = len(matrix)
width = len(matrix[0]) width = len(matrix[0])
if diagonals: if diagonals:
coords = ( coords = (M_UL, M_U, M_UR, M_L, M_R, M_DL, M_D, M_DR)
M_UL, M_U, M_UR,
M_L, M_R,
M_DL, M_D, M_DR
)
else: else:
coords = ( coords = (M_U, M_L, M_R, M_D)
M_U,
M_L,M_R,
M_D
)
neighbors = [] neighbors = []
for _c, _r in coords: for _c, _r in coords:
try: try:
value = matrix[r + _r][c + _c] # Try to get a value error value = matrix[r + _r][c + _c] # Try to get a value error
if (r+_r>=0 and c+_c >= 0): if r + _r >= 0 and c + _c >= 0:
neighbors.append( neighbors.append(
[{"c": c + _c, "r": r + _r}, value] [{"c": c + _c, "r": r + _r}, value]
) # woo, no error, this coord is valid ) # woo, no error, this coord is valid
@ -108,37 +145,39 @@ def get_neighbor_coords(matrix, c, r, diagonals=True):
pass # okay we out of bounds boizzzz pass # okay we out of bounds boizzzz
return neighbors return neighbors
def line_of_sight_coords(matrix, row,col) -> Dict[str,List[Tuple[int,int]]]:
"""
Takes a matrix, a row, and a column
calculates the coordinates to the edge for all four cardinal directions
returns a dict with a list of tuple coordes TRAVELING AWAY from the def line_of_sight_coords(matrix, row, col) -> Dict[str, List[Tuple[int, int]]]:
requested coordinate """
Takes a matrix, a row, and a column
calculates the coordinates to the edge for all four cardinal directions
returns a dict with a list of tuple coordes TRAVELING AWAY from the
requested coordinate
""" """
height, width = get_size(matrix) height, width = get_size(matrix)
col_ids = list(range(0, height)) col_ids = list(range(0, height))
row_ids = list(range(0, width)) row_ids = list(range(0, width))
up_ids,down_ids = list(reversed(col_ids[:col])), col_ids[col+1:] up_ids, down_ids = list(reversed(col_ids[:col])), col_ids[col + 1 :]
left_ids,right_ids = list(reversed(row_ids[:row])), row_ids[row+1:] left_ids, right_ids = list(reversed(row_ids[:row])), row_ids[row + 1 :]
left = [(r,col) for r in left_ids] left = [(r, col) for r in left_ids]
right = [(r,col) for r in right_ids] right = [(r, col) for r in right_ids]
up = [(row,c) for c in up_ids] up = [(row, c) for c in up_ids]
down = [(row,c) for c in down_ids] down = [(row, c) for c in down_ids]
return { return {
'U':up, "U": up,
'L':left, "L": left,
'D':down, "D": down,
'R':right, "R": right,
} }
def line_of_sight(mx, row, col): def line_of_sight(mx, row, col):
""" """
renders a line of sight coord calculation, into the values renders a line of sight coord calculation, into the values
""" """
coords = line_of_sight_coords(mx, row, col) coords = line_of_sight_coords(mx, row, col)
los = defaultdict(list) los = defaultdict(list)
@ -148,22 +187,23 @@ def line_of_sight(mx, row, col):
return los return los
def get_size(matrix): def get_size(matrix):
height = len(matrix) height = len(matrix)
width = len(matrix[0]) width = len(matrix[0])
return height, width return height, width
def row_col_from_int(matrix, x): def row_col_from_int(matrix, x):
h,w = get_size(matrix) h, w = get_size(matrix)
col = x % w col = x % w
row = x // h row = x // h
return row,col return row, col
def matrix_of_size(width, height, default=0): def matrix_of_size(width, height, default=0):
return [[default] * width for x in range(height)] return [[default] * width for x in range(height)]
def set_matrix_dict(m): def set_matrix_dict(m):
for x in range(len(m)): for x in range(len(m)):
for y in range(len(m[x])): for y in range(len(m[x])):
@ -173,7 +213,7 @@ def set_matrix_dict(m):
def pmx(*matrices, pad=True, space=True): def pmx(*matrices, pad=True, space=True):
""" """
print a matrix of integers, zero turns to `.` for clarity print a matrix of integers, zero turns to `.` for clarity
""" """
if len(matrices) > 1: if len(matrices) > 1:
matrices = list(zip(*matrices)) matrices = list(zip(*matrices))
@ -195,9 +235,10 @@ def pmx(*matrices, pad=True, space=True):
f = lambda x: f"{int(x)or '.'} " f = lambda x: f"{int(x)or '.'} "
print("".join([f(x) for x in c])) print("".join([f(x) for x in c]))
def ppmx(*matrices, pad=True, space=True): def ppmx(*matrices, pad=True, space=True):
""" """
print a matrix of anything, Falsy values turns to `.` for clarity print a matrix of anything, Falsy values turns to `.` for clarity
""" """
if len(matrices) > 1: if len(matrices) > 1:
matrices = list(zip(*matrices)) matrices = list(zip(*matrices))
@ -218,3 +259,23 @@ def ppmx(*matrices, pad=True, space=True):
if space: if space:
f = lambda x: f"{x or '.'} " f = lambda x: f"{x or '.'} "
print("".join([f(x) for x in c])) print("".join([f(x) for x in c]))
def highlight(matrix, red=[], green=[], blue=[]):
"""
print a matrix of anything, Falsy values turns to `.` for clarity
"""
mx = deepcopy(matrix)
for (y, x) in red:
try:
new = f"{colors.RED}{mx[y][x]}{colors.ENDC}"
mx[y][x] = new
except IndexError:
breakpoint()
for (y, x) in green:
new = f"{colors.GREEN}{mx[y][x]}{colors.ENDC}"
mx[y][x] = new
for (y, x) in blue:
new = f"{colors.BLUE}{mx[y][x]}{colors.ENDC}"
mx[y][x] = new
ppmx(mx, pad=False, space=False)

View File

@ -4,13 +4,16 @@ from pathlib import Path
spl = lambda y: [int(w) for w in y] spl = lambda y: [int(w) for w in y]
def load_rows(day): def load_rows(day):
return [row for row in load(day)] return [row for row in load(day)]
def load(day): def load(day):
path = Path(get_fname(day)) path = Path(get_fname(day))
return path.read_text().rstrip().split("\n") return path.read_text().rstrip().split("\n")
def get_fname(day: int) -> str: def get_fname(day: int) -> str:
import sys import sys
@ -27,6 +30,7 @@ def load_char_matrix(f):
my_file.append(line.rstrip()) my_file.append(line.rstrip())
return [list(x) for x in my_file] return [list(x) for x in my_file]
def load_file_char_matrix(name): def load_file_char_matrix(name):
with open(name, "r") as f: with open(name, "r") as f:
return load_char_matrix(f) return load_char_matrix(f)
@ -38,21 +42,27 @@ def load_int_matrix(f):
my_file.append(line.rstrip()) my_file.append(line.rstrip())
return [list(map(int, x)) for x in my_file] return [list(map(int, x)) for x in my_file]
def load_file_int_matrix(name): def load_file_int_matrix(name):
with open(name, "r") as f: with open(name, "r") as f:
return load_int_matrix(f) return load_int_matrix(f)
def load_word_matrix(f): def load_word_matrix(f):
my_file = [] my_file = []
for line in f: for line in f:
my_file.append(line.rstrip()) my_file.append(line.rstrip())
return [x.split(" ") for x in my_file] return [x.split(" ") for x in my_file]
def load_file_word_matrix(name): def load_file_word_matrix(name):
with open(name, "r") as f: with open(name, "r") as f:
return load_word_matrix(f) return load_word_matrix(f)
############# #############
def rotate(WHAT, times=1): def rotate(WHAT, times=1):
what = WHAT what = WHAT
for x in range(times): for x in range(times):
@ -60,11 +70,10 @@ def rotate(WHAT, times=1):
return what return what
@contextmanager @contextmanager
def elapsed_timer(): def elapsed_timer():
start = default_timer() start = default_timer()
elapser = lambda: default_timer() - start elapser = lambda: default_timer() - start
yield lambda: elapser() yield lambda: elapser()
end = default_timer() end = default_timer()
elapser = lambda: end-start elapser = lambda: end - start