Initial commit
This commit is contained in:
commit
97a4330bc0
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Don't include prompts and inputs as they're not free to copy
|
||||
**/input*
|
||||
**/prompt
|
||||
# Demos are also part of the prompt...
|
||||
**/demo*
|
||||
# ... except when I wrote those myself
|
||||
!**/demog*
|
5
2023/1/obfuscated.py
Normal file
5
2023/1/obfuscated.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
import re
|
||||
d="zero|one|two|three|four|five|six|seven|eight|nine|\\d)"
|
||||
def f(l,p):
|
||||
m=re.search(p,l)[1];return str(d.split("|").index(m)) if m in d else m
|
||||
print(sum(map(lambda l:int(f(l,f"({d}.*")+f(l,".*("+d)),open(0).readlines())))
|
30
2023/1/script.py
Normal file
30
2023/1/script.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
|
||||
digits = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
|
||||
group = "|".join(digits + ["[0-9]"])
|
||||
|
||||
tot = 0
|
||||
with open("lines.txt") as lines:
|
||||
for line in lines.readlines():
|
||||
print()
|
||||
line = line.rstrip()
|
||||
print(line)
|
||||
last = re.search(rf"^.*({group})", line)
|
||||
first = re.search(rf"({group}).*$", line)
|
||||
print(first, last)
|
||||
f = first[1]
|
||||
l = last[1]
|
||||
print(f, l)
|
||||
if f in digits:
|
||||
f = str(digits.index(f))
|
||||
if l in digits:
|
||||
l = str(digits.index(l))
|
||||
print(f, l)
|
||||
numb = int(f + l)
|
||||
tot += numb
|
||||
print(numb)
|
||||
print()
|
||||
|
||||
print(tot)
|
28
2023/2/one.py
Normal file
28
2023/2/one.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
maxs = {"red": 12, "green": 13, "blue": 14}
|
||||
|
||||
gid = 0
|
||||
possible_gid_sum = 0
|
||||
|
||||
with open("input") as lines:
|
||||
for line in lines.readlines():
|
||||
gid += 1
|
||||
line = line.rstrip()
|
||||
game_full, sets = line.split(":")
|
||||
game, gid_str = game_full.split(" ")
|
||||
assert int(gid_str) == gid
|
||||
possible = True
|
||||
for seet in sets.split(";"):
|
||||
gcs = {"red": 0, "green": 0, "blue": 0}
|
||||
for color in seet.split(","):
|
||||
amount_str, color = color.strip().split(" ")
|
||||
amount = int(amount_str)
|
||||
gcs[color] += amount
|
||||
for color, amount in gcs.items():
|
||||
max = maxs[color]
|
||||
if amount > max:
|
||||
possible = False
|
||||
if possible:
|
||||
possible_gid_sum += gid
|
||||
print(gid, possible)
|
||||
|
||||
print(possible_gid_sum)
|
24
2023/2/two.py
Normal file
24
2023/2/two.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
maxs = {"red": 12, "green": 13, "blue": 14}
|
||||
|
||||
gid = 0
|
||||
power_sum = 0
|
||||
|
||||
with open("input") as lines:
|
||||
for line in lines.readlines():
|
||||
gid += 1
|
||||
line = line.rstrip()
|
||||
game_full, sets = line.split(":")
|
||||
game, gid_str = game_full.split(" ")
|
||||
assert int(gid_str) == gid
|
||||
possible = True
|
||||
gcs = {"red": 0, "green": 0, "blue": 0}
|
||||
for seet in sets.split(";"):
|
||||
for color in seet.split(","):
|
||||
amount_str, color = color.strip().split(" ")
|
||||
amount = int(amount_str)
|
||||
gcs[color] = max(amount, gcs[color])
|
||||
power = gcs["red"] * gcs["green"] * gcs["blue"]
|
||||
print(gid, power)
|
||||
power_sum += power
|
||||
|
||||
print(power_sum)
|
16
2023/24/one.py
Normal file
16
2023/24/one.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
hailstones = []
|
||||
|
||||
with open(input_file) as fd:
|
||||
for line in fd.readlines():
|
||||
line = line.rstrip()
|
||||
line.replace("@", ",")
|
||||
hailstone = [int(h) for h in line.split(",")]
|
||||
hailstones.append(hailstone)
|
||||
|
||||
|
41
2023/3/one.py
Normal file
41
2023/3/one.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
height = len(lines)
|
||||
width = len(lines[0])
|
||||
|
||||
sum = 0
|
||||
for i in range(height):
|
||||
line = lines[i]
|
||||
pn_str = ""
|
||||
for j in range(width):
|
||||
c = line[j]
|
||||
# print(19, c)
|
||||
if c.isnumeric():
|
||||
if not pn_str:
|
||||
left = j
|
||||
pn_str += c
|
||||
# print(20, c, pn_str)
|
||||
if pn_str and (j == width - 1 or not line[j + 1].isnumeric()):
|
||||
print(25, pn_str)
|
||||
adj = False
|
||||
for ii in range(max(i - 1, 0), min(i + 1, height - 1) + 1):
|
||||
for jj in range(max(left - 1, 0), min(j + 1, width - 1) + 1):
|
||||
cc = lines[ii][jj]
|
||||
print(ii, jj, cc)
|
||||
if not cc.isnumeric() and cc != ".":
|
||||
print("!")
|
||||
adj = True
|
||||
# print(pn_str, adj)
|
||||
if adj:
|
||||
pn = int(pn_str)
|
||||
sum += pn
|
||||
pn_str = ""
|
||||
|
||||
print(sum)
|
42
2023/3/two.py
Normal file
42
2023/3/two.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
height = len(lines)
|
||||
width = len(lines[0])
|
||||
|
||||
gears = dict()
|
||||
|
||||
sum = 0
|
||||
for i in range(height):
|
||||
line = lines[i]
|
||||
pn_str = ""
|
||||
for j in range(width):
|
||||
c = line[j]
|
||||
# print(19, c)
|
||||
if c.isnumeric():
|
||||
if not pn_str:
|
||||
left = j
|
||||
pn_str += c
|
||||
# print(20, c, pn_str)
|
||||
if pn_str and (j == width - 1 or not line[j + 1].isnumeric()):
|
||||
for ii in range(max(i - 1, 0), min(i + 1, height - 1) + 1):
|
||||
for jj in range(max(left - 1, 0), min(j + 1, width - 1) + 1):
|
||||
cc = lines[ii][jj]
|
||||
# print(ii, jj, cc)
|
||||
if cc == "*":
|
||||
gears.setdefault((ii, jj), list())
|
||||
gears[(ii, jj)].append(int(pn_str))
|
||||
pn_str = ""
|
||||
for gear_numbers in gears.values():
|
||||
if len(gear_numbers) != 2:
|
||||
continue
|
||||
gear_ratio = gear_numbers[0] * gear_numbers[1]
|
||||
sum += gear_ratio
|
||||
|
||||
print(sum)
|
26
2024/1/one.py
Normal file
26
2024/1/one.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
|
||||
listl = []
|
||||
listr = []
|
||||
with open("input") as lines:
|
||||
for line in lines.readlines():
|
||||
line = line.rstrip()
|
||||
print(line)
|
||||
spli = line.split(" ")
|
||||
listl.append(int(spli[0]))
|
||||
listr.append(int(spli[-1]))
|
||||
|
||||
assert len(listl) == len(listr)
|
||||
|
||||
listl.sort()
|
||||
listr.sort()
|
||||
|
||||
dtot = 0
|
||||
|
||||
for i in range(len(listl)):
|
||||
l = listl[i]
|
||||
r = listr[i]
|
||||
d = abs(l-r)
|
||||
dtot += d
|
||||
print(l, r, d)
|
||||
|
||||
print(dtot)
|
25
2024/1/two.py
Normal file
25
2024/1/two.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
listl = []
|
||||
listr = []
|
||||
with open("input") as lines:
|
||||
for line in lines.readlines():
|
||||
line = line.rstrip()
|
||||
print(line)
|
||||
spli = line.split(" ")
|
||||
listl.append(int(spli[0]))
|
||||
listr.append(int(spli[-1]))
|
||||
|
||||
assert len(listl) == len(listr)
|
||||
|
||||
listl.sort()
|
||||
listr.sort()
|
||||
|
||||
dtot = 0
|
||||
|
||||
for i in range(len(listl)):
|
||||
l = listl[i]
|
||||
d = listr.count(l) * l
|
||||
dtot += d
|
||||
print(l, d)
|
||||
|
||||
print(dtot)
|
61
2024/10/one.py
Normal file
61
2024/10/one.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
height = len(lines)
|
||||
width = len(lines[0])
|
||||
|
||||
tmap: list[list[int]] = [[int(a) for a in line] for line in lines]
|
||||
|
||||
directions = [
|
||||
(0, 1),
|
||||
(0, -1),
|
||||
(1, 0),
|
||||
(-1, 0),
|
||||
]
|
||||
|
||||
|
||||
def print_path(path: list[tuple[int, int]]) -> None:
|
||||
viz = [["."] * width for _ in range(height)]
|
||||
for c, pos in enumerate(path):
|
||||
i, j = pos
|
||||
viz[i][j] = str(c)
|
||||
for line in viz:
|
||||
print("".join(line))
|
||||
print()
|
||||
|
||||
|
||||
def score(pos: tuple[int, int], path: list[tuple[int, int]]) -> set[tuple[int, int]]:
|
||||
path = path + [pos]
|
||||
i, j = pos
|
||||
c = tmap[i][j]
|
||||
if c == 9:
|
||||
return {pos}
|
||||
reachable = set()
|
||||
for direction in directions:
|
||||
ii, jj = i + direction[0], j + direction[1]
|
||||
if ii not in range(height) or jj not in range(width):
|
||||
continue
|
||||
cc = tmap[ii][jj]
|
||||
if cc != c + 1:
|
||||
continue
|
||||
reachable |= score((ii, jj), path)
|
||||
return reachable
|
||||
|
||||
|
||||
tscore = 0
|
||||
for i in range(height):
|
||||
for j in range(width):
|
||||
c = tmap[i][j]
|
||||
if c != 0:
|
||||
continue
|
||||
cscore = len(score((i, j), []))
|
||||
# print(i, j, cscore)
|
||||
tscore += cscore
|
||||
|
||||
print(tscore)
|
64
2024/10/two.py
Normal file
64
2024/10/two.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
height = len(lines)
|
||||
width = len(lines[0])
|
||||
|
||||
tmap: list[list[int]] = [[int(a) for a in line] for line in lines]
|
||||
|
||||
directions = [
|
||||
(0, 1),
|
||||
(0, -1),
|
||||
(1, 0),
|
||||
(-1, 0),
|
||||
]
|
||||
|
||||
|
||||
def print_path(path: list[tuple[int, int]]) -> None:
|
||||
viz = [["."] * width for _ in range(height)]
|
||||
for c, pos in enumerate(path):
|
||||
i, j = pos
|
||||
viz[i][j] = str(c)
|
||||
for line in viz:
|
||||
print("".join(line))
|
||||
print()
|
||||
|
||||
|
||||
def score(pos: tuple[int, int], path: list[tuple[int, int]]) -> int:
|
||||
path = path + [pos]
|
||||
i, j = pos
|
||||
c = tmap[i][j]
|
||||
if c == 9:
|
||||
# print_path(path)
|
||||
return 1
|
||||
cscore = 0
|
||||
for direction in directions:
|
||||
ii, jj = i + direction[0], j + direction[1]
|
||||
if ii not in range(height) or jj not in range(width):
|
||||
continue
|
||||
cc = tmap[ii][jj]
|
||||
if cc != c + 1:
|
||||
continue
|
||||
cscore += score((ii, jj), path)
|
||||
return cscore
|
||||
|
||||
|
||||
tscore = 0
|
||||
for i in range(height):
|
||||
for j in range(width):
|
||||
c = tmap[i][j]
|
||||
if c != 0:
|
||||
continue
|
||||
cscore = score((i, j), [])
|
||||
print(i, j, cscore)
|
||||
tscore += cscore
|
||||
# break
|
||||
# break
|
||||
|
||||
print(tscore)
|
30
2024/11/one.py
Normal file
30
2024/11/one.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
height = len(lines)
|
||||
width = len(lines[0])
|
||||
|
||||
stones = [int(stone) for stone in lines[0].split()]
|
||||
|
||||
for _ in range(25):
|
||||
new_stones = []
|
||||
for stone in stones:
|
||||
stone_str = str(stone)
|
||||
if stone == 0:
|
||||
new_stones.append(1)
|
||||
elif len(stone_str) % 2 == 0:
|
||||
mid = int(len(stone_str) / 2)
|
||||
new_stones.append(int(stone_str[:mid]))
|
||||
new_stones.append(int(stone_str[mid:]))
|
||||
else:
|
||||
new_stones.append(stone * 2024)
|
||||
stones = new_stones
|
||||
# print(" ".join(str(stone) for stone in stones))
|
||||
|
||||
print(len(stones))
|
121
2024/11/two.py
Normal file
121
2024/11/two.py
Normal file
|
@ -0,0 +1,121 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import bisect
|
||||
import sys
|
||||
import time
|
||||
import functools
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
start = time.time()
|
||||
|
||||
stones = [int(stone) for stone in lines[0].split()]
|
||||
|
||||
# for i in range(75):
|
||||
# print(i, time.time() - start, len(stones))
|
||||
# # for s, stone in enumerate(stones):
|
||||
# # if stone == 0:
|
||||
# # stones[s] = 1
|
||||
# # continue
|
||||
# # stone_str = str(stone)
|
||||
# # if len(stone_str) % 2 == 0:
|
||||
# # mid = int(len(stone_str) / 2)
|
||||
# # stones[s] = int(stone_str[:mid])
|
||||
# # stones.insert(s, int(stone_str[mid:]))
|
||||
# # else:
|
||||
# # stones[s] *= 2024
|
||||
# new_stones = []
|
||||
# for stone in stones:
|
||||
# stone_str = str(stone)
|
||||
# if stone == 0:
|
||||
# new_stones.append(1)
|
||||
# elif len(stone_str) % 2 == 0:
|
||||
# mid = int(len(stone_str) / 2)
|
||||
# new_stones.append(int(stone_str[:mid]))
|
||||
# new_stones.append(int(stone_str[mid:]))
|
||||
# else:
|
||||
# new_stones.append(stone * 2024)
|
||||
# stones = new_stones
|
||||
|
||||
target = int(sys.argv[2])
|
||||
|
||||
its = [0] * len(stones)
|
||||
|
||||
start_stones = stones.copy()
|
||||
|
||||
|
||||
pow10 = list()
|
||||
for i in range(25):
|
||||
pow10.append(10**i)
|
||||
|
||||
|
||||
def num_digits(a: int) -> int:
|
||||
# for i, p in enumerate(pow10):
|
||||
# if a < p:
|
||||
# # assert len(str(a)) == i
|
||||
# return i
|
||||
# raise NotImplementedError
|
||||
# return bisect.bisect(pow10, a)
|
||||
# # nb = bisect.bisect(pow10, a)
|
||||
num = 0
|
||||
while a > 0:
|
||||
num += 1
|
||||
a //= 10
|
||||
# assert nb == num
|
||||
return num
|
||||
|
||||
|
||||
# lstones = 0
|
||||
# for e, sstone in enumerate(start_stones):
|
||||
# print(f"47 {e}/{len(start_stones)} {time.time() - start}")
|
||||
# stones = [sstone]
|
||||
# while stones:
|
||||
# stone = stones.pop(0)
|
||||
# it = its.pop(0)
|
||||
# lstones += 1
|
||||
# if stone == 0:
|
||||
# stone = 1
|
||||
# it += 1
|
||||
# nd = num_digits(stone)
|
||||
# for i in range(it, target):
|
||||
# print(stone)
|
||||
# if nd % 2 == 0:
|
||||
# mid = nd // 2
|
||||
# left, right = divmod(stone, pow10[mid])
|
||||
# # left, right = divmod(stone, 10**mid)
|
||||
# stone = left
|
||||
# stones.insert(0, right)
|
||||
# its.insert(0, i + 1)
|
||||
# nd = mid
|
||||
# else:
|
||||
# stone *= 2024
|
||||
# nd = num_digits(stone)
|
||||
# # print(f"64 {stone}")
|
||||
|
||||
# @functools.lru_cache(maxsize=1024)
|
||||
@functools.cache
|
||||
def proc(stone: int, target: int) -> int:
|
||||
if target == 0:
|
||||
return 1
|
||||
target -= 1
|
||||
if stone == 0:
|
||||
return proc(1, target)
|
||||
nd = num_digits(stone)
|
||||
if nd % 2 == 0:
|
||||
mid = nd // 2
|
||||
left, right = divmod(stone, pow10[mid])
|
||||
return proc(left, target) + proc(right, target)
|
||||
else:
|
||||
return proc(stone * 2024, target)
|
||||
|
||||
|
||||
lstones = 0
|
||||
for e, stone in enumerate(stones):
|
||||
print(f"47 {e}/{len(stones)} {time.time() - start}")
|
||||
lstones += proc(stone, target)
|
||||
|
||||
print(f"{target=}")
|
||||
print(lstones)
|
83
2024/12/one.py
Normal file
83
2024/12/one.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
height = len(lines)
|
||||
width = len(lines[0])
|
||||
|
||||
visited: set[tuple[int, int]] = set()
|
||||
|
||||
directions = [
|
||||
(0, 1),
|
||||
(0, -1),
|
||||
(1, 0),
|
||||
(-1, 0),
|
||||
]
|
||||
|
||||
|
||||
def get_region(
|
||||
pos: tuple[int, int], region: set[tuple[int, int]]
|
||||
) -> set[tuple[int, int]]:
|
||||
region.add(pos)
|
||||
i, j = pos
|
||||
ochar = lines[i][j]
|
||||
for direction in directions:
|
||||
i, j = pos[0] + direction[0], pos[1] + direction[1]
|
||||
if i not in range(height) or j not in range(width):
|
||||
continue
|
||||
if (i, j) in region:
|
||||
continue
|
||||
char = lines[i][j]
|
||||
if char != ochar:
|
||||
continue
|
||||
region |= get_region((i, j), region)
|
||||
return region
|
||||
|
||||
|
||||
def get_perimeter(region: set[tuple[int, int]]) -> int:
|
||||
peri = 0
|
||||
for axis in (0, 1):
|
||||
oaxis = 0 if axis else 1
|
||||
iss = set([pos[axis] for pos in region])
|
||||
print(47, iss, peri)
|
||||
for i in iss:
|
||||
line = [pos[oaxis] for pos in region if pos[axis] == i]
|
||||
line.sort()
|
||||
last_j = None
|
||||
for j in line:
|
||||
if last_j is None:
|
||||
peri += 1
|
||||
elif last_j == j - 1:
|
||||
pass
|
||||
else:
|
||||
peri += 2
|
||||
last_j = j
|
||||
if last_j is not None:
|
||||
peri += 1
|
||||
print(62, i, peri, line)
|
||||
return peri
|
||||
|
||||
|
||||
tprice = 0
|
||||
for i in range(height):
|
||||
for j in range(width):
|
||||
pos = i, j
|
||||
if pos in visited:
|
||||
continue
|
||||
region = get_region(pos, set())
|
||||
visited |= region
|
||||
|
||||
area = len(region)
|
||||
peri = get_perimeter(region)
|
||||
price = area * peri
|
||||
tprice += price
|
||||
|
||||
char = lines[i][j]
|
||||
print(f"{char}: {area} × {peri} = {price}$")
|
||||
|
||||
print(tprice)
|
5
2024/12/reddit_test
Normal file
5
2024/12/reddit_test
Normal file
|
@ -0,0 +1,5 @@
|
|||
AAXXX
|
||||
AAXAX
|
||||
AAAAX
|
||||
AAXAX
|
||||
AAXXX
|
136
2024/12/two.py
Normal file
136
2024/12/two.py
Normal file
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
height = len(lines)
|
||||
width = len(lines[0])
|
||||
|
||||
visited: set[tuple[int, int]] = set()
|
||||
|
||||
directions = [
|
||||
(0, 1),
|
||||
(0, -1),
|
||||
(1, 0),
|
||||
(-1, 0),
|
||||
]
|
||||
|
||||
|
||||
def get_region(
|
||||
pos: tuple[int, int], region: set[tuple[int, int]]
|
||||
) -> set[tuple[int, int]]:
|
||||
region.add(pos)
|
||||
i, j = pos
|
||||
ochar = lines[i][j]
|
||||
for direction in directions:
|
||||
i, j = pos[0] + direction[0], pos[1] + direction[1]
|
||||
if i not in range(height) or j not in range(width):
|
||||
continue
|
||||
if (i, j) in region:
|
||||
continue
|
||||
char = lines[i][j]
|
||||
if char != ochar:
|
||||
continue
|
||||
region |= get_region((i, j), region)
|
||||
return region
|
||||
|
||||
|
||||
# def get_sides(region: set[tuple[int, int]]) -> int:
|
||||
# peri = 0
|
||||
# for axis in (0, 1):
|
||||
# oaxis = 0 if axis else 1
|
||||
# iss = set([pos[axis] for pos in region])
|
||||
# sta: set[int] = set()
|
||||
# sto: set[int] = set()
|
||||
# for i in iss:
|
||||
# line = [pos[oaxis] for pos in region if pos[axis] == i]
|
||||
# line.sort()
|
||||
# last_j = None
|
||||
# for j in line:
|
||||
# if last_j is None:
|
||||
# sta.add(j)
|
||||
# elif last_j == j - 1:
|
||||
# pass
|
||||
# else:
|
||||
# sta.add(j)
|
||||
# sto.add(last_j)
|
||||
# last_j = j
|
||||
# if last_j is not None:
|
||||
# sto.add(last_j)
|
||||
# peri += len(sta) + len(sto)
|
||||
# return peri
|
||||
|
||||
def get_perimeter(region: set[tuple[int, int]]) -> int:
|
||||
peri = 0
|
||||
for axis in (0, 1):
|
||||
oaxis = 0 if axis else 1
|
||||
iss = set([pos[axis] for pos in region])
|
||||
for dire in (-1, 1):
|
||||
print(47, axis, dire, iss, peri)
|
||||
for i in iss:
|
||||
oi = i + dire
|
||||
line = [pos[oaxis] for pos in region if pos[axis] == i]
|
||||
line.sort()
|
||||
# last_j = None
|
||||
for j in line:
|
||||
if not axis:
|
||||
opos = oi, j
|
||||
else:
|
||||
opos = j, oi
|
||||
if opos in region:
|
||||
continue
|
||||
peri += 1
|
||||
return peri
|
||||
|
||||
|
||||
def get_sides(region: set[tuple[int, int]]) -> int:
|
||||
peri = 0
|
||||
for axis in (0, 1):
|
||||
oaxis = 0 if axis else 1
|
||||
iss = set([pos[axis] for pos in region])
|
||||
for dire in (-1, 1):
|
||||
print(47, axis, dire, iss, peri)
|
||||
for i in iss:
|
||||
oi = i + dire
|
||||
line = [pos[oaxis] for pos in region if pos[axis] == i]
|
||||
line.sort()
|
||||
last_j = None
|
||||
for j in line:
|
||||
if not axis:
|
||||
opos = oi, j
|
||||
else:
|
||||
opos = j, oi
|
||||
if opos in region:
|
||||
last_j = None
|
||||
continue
|
||||
if last_j == j - 1:
|
||||
pass
|
||||
else:
|
||||
peri += 1
|
||||
|
||||
last_j = j
|
||||
return peri
|
||||
|
||||
|
||||
tprice = 0
|
||||
for i in range(height):
|
||||
for j in range(width):
|
||||
pos = i, j
|
||||
if pos in visited:
|
||||
continue
|
||||
region = get_region(pos, set())
|
||||
visited |= region
|
||||
|
||||
area = len(region)
|
||||
sides = get_sides(region)
|
||||
price = area * sides
|
||||
tprice += price
|
||||
|
||||
char = lines[i][j]
|
||||
print(f"{char}: {area} × {sides} = {price}$")
|
||||
|
||||
print(tprice)
|
BIN
2024/13/Notes.xopp
Normal file
BIN
2024/13/Notes.xopp
Normal file
Binary file not shown.
12
2024/13/demog
Normal file
12
2024/13/demog
Normal file
|
@ -0,0 +1,12 @@
|
|||
Button A: X+3, Y+1
|
||||
Button B: X+4, Y+2
|
||||
Prize: X=17, Y=7
|
||||
|
||||
Button A: X+1, Y+1
|
||||
Button B: X+3, Y+3
|
||||
Prize: X=7, Y=7
|
||||
|
||||
Button A: X+3, Y+3
|
||||
Button B: X+1, Y+1
|
||||
Prize: X=7, Y=7
|
||||
|
78
2024/13/one.py
Normal file
78
2024/13/one.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import functools
|
||||
import re
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
coords = tuple[int, int]
|
||||
prizes: list[coords] = list()
|
||||
buttons: list[tuple[coords, coords]] = list()
|
||||
|
||||
for li, line in enumerate(lines):
|
||||
machine = li // 4
|
||||
offset = li % 4
|
||||
if offset == 0:
|
||||
match = re.match(r"^Button A: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_a = int(match[1]), int(match[2])
|
||||
elif offset == 1:
|
||||
match = re.match(r"^Button B: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_b = int(match[1]), int(match[2])
|
||||
buttons.append((button_a, button_b))
|
||||
elif offset == 2:
|
||||
match = re.match("^Prize: X=([0-9]+), Y=([0-9]+)$", line)
|
||||
assert match
|
||||
prize = int(match[1]), int(match[2])
|
||||
prizes.append(prize)
|
||||
|
||||
assert len(prizes) == len(buttons)
|
||||
|
||||
ttoks = 0
|
||||
for arcade, prize in enumerate(prizes):
|
||||
butts = buttons[arcade]
|
||||
button_a, button_b = butts
|
||||
|
||||
@functools.lru_cache(4096)
|
||||
def fun(x: int, y: int, rem_a: int, rem_b: int) -> int | None:
|
||||
if (x, y) == prize:
|
||||
return 0
|
||||
if x > prize[0] or y > prize[1]:
|
||||
return None
|
||||
ba = (
|
||||
fun(x + button_a[0], y + button_a[1], rem_a - 1, rem_b)
|
||||
if rem_a > 0
|
||||
else None
|
||||
)
|
||||
bb = (
|
||||
fun(x + button_b[0], y + button_b[1], rem_a, rem_b - 1)
|
||||
if rem_b > 0
|
||||
else None
|
||||
)
|
||||
if ba is not None:
|
||||
ba += 3
|
||||
if bb is not None:
|
||||
bb += 1
|
||||
if ba is None:
|
||||
if bb is None:
|
||||
return None
|
||||
else:
|
||||
return bb
|
||||
else:
|
||||
if bb is None or ba < bb:
|
||||
return ba
|
||||
else:
|
||||
return bb
|
||||
|
||||
toks = fun(0, 0, 100, 100)
|
||||
print(43, arcade, toks)
|
||||
if toks is not None:
|
||||
ttoks += toks
|
||||
# break
|
||||
|
||||
print(ttoks)
|
223
2024/13/two.py
Normal file
223
2024/13/two.py
Normal file
|
@ -0,0 +1,223 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
import re
|
||||
import sys
|
||||
|
||||
import rich.progress
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
coords = tuple[int, int]
|
||||
prizes: list[coords] = list()
|
||||
buttons: list[tuple[coords, coords]] = list()
|
||||
|
||||
for li, line in enumerate(lines):
|
||||
machine = li // 4
|
||||
offset = li % 4
|
||||
if offset == 0:
|
||||
match = re.match(r"^Button A: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_a = int(match[1]), int(match[2])
|
||||
elif offset == 1:
|
||||
match = re.match(r"^Button B: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_b = int(match[1]), int(match[2])
|
||||
buttons.append((button_a, button_b))
|
||||
elif offset == 2:
|
||||
match = re.match("^Prize: X=([0-9]+), Y=([0-9]+)$", line)
|
||||
assert match
|
||||
prize = int(match[1]), int(match[2])
|
||||
prize = prize[0] + 10000000000000, prize[1] + 10000000000000
|
||||
prizes.append(prize)
|
||||
|
||||
assert len(prizes) == len(buttons)
|
||||
|
||||
|
||||
def slope(point: coords) -> float:
|
||||
return point[1] / point[0]
|
||||
|
||||
|
||||
def norm(point: coords) -> float:
|
||||
return math.sqrt(math.pow(point[1], 2) + math.pow(point[0], 2))
|
||||
|
||||
|
||||
#
|
||||
# def in_range(p: coords, a: coords, b: coords) -> bool:
|
||||
# slope_a = slope(button_a)
|
||||
# slope_b = slope(button_b)
|
||||
# slope_p = slope(p)
|
||||
# slope_but_min = min(slope_a, slope_b)
|
||||
# slope_but_max = max(slope_a, slope_b)
|
||||
# return not (slope_p < slope_but_min or slope_p > slope_but_max)
|
||||
|
||||
|
||||
ttoks = 0
|
||||
token_a, token_b = 3, 1
|
||||
for arcade, prize in enumerate(prizes):
|
||||
butts = buttons[arcade]
|
||||
button_a, button_b = butts
|
||||
|
||||
print(43, prize, button_a, button_b)
|
||||
toks = None
|
||||
|
||||
max_a_x = int(math.ceil(prize[0] / button_a[0]))
|
||||
max_a_y = int(math.ceil(prize[1] / button_a[1]))
|
||||
max_a = min(max_a_x, max_a_y)
|
||||
max_b_x = int(math.ceil(prize[0] / button_b[0]))
|
||||
max_b_y = int(math.ceil(prize[1] / button_b[1]))
|
||||
max_b = min(max_b_x, max_b_y)
|
||||
|
||||
slope_a = slope(button_a)
|
||||
slope_b = slope(button_b)
|
||||
slope_prize = slope(prize)
|
||||
slope_but_min = min(slope_a, slope_b)
|
||||
slope_but_max = max(slope_a, slope_b)
|
||||
print(57, slope_but_min, slope_prize, slope_but_max)
|
||||
if slope_prize < slope_but_min or slope_prize > slope_but_max:
|
||||
print("Not in range")
|
||||
continue
|
||||
|
||||
norm_a = norm(button_a)
|
||||
norm_b = norm(button_b)
|
||||
speed_a = norm_a / 3
|
||||
speed_b = norm_b / 1
|
||||
|
||||
if speed_a > speed_b:
|
||||
button_fastest, button_slowest = button_a, button_b
|
||||
token_fastest, token_slowest = token_a, token_b
|
||||
max_fastest, max_slowest = max_a, max_b
|
||||
# slope_fastest, slope_slowes = slope_a, slope_b
|
||||
# norm_fastest, norm_slowest = norm_a, norm_b
|
||||
else:
|
||||
button_fastest, button_slowest = button_b, button_a
|
||||
token_fastest, token_slowest = token_b, token_a
|
||||
max_fastest, max_slowest = max_b, max_a
|
||||
# slope_fastest, slope_slowes = slope_b, slope_a
|
||||
# norm_fastest, norm_slowest = norm_b, norm_a
|
||||
toks = 0
|
||||
|
||||
# pri_x, pri_y = prize
|
||||
# slope_pri = slope((pri_x, pri_y))
|
||||
# while slope_pri >= slope_but_min and slope_pri <= slope_but_max:
|
||||
# toks += token_fastest
|
||||
# pri_x -= button_fastest[0]
|
||||
# pri_y -= button_fastest[1]
|
||||
# slope_pri = slope((pri_x, pri_y))
|
||||
# # print(98, pri_x, pri_y, slope_pri, toks)
|
||||
# pri_x += button_fastest[0]
|
||||
# pri_y += button_fastest[1]
|
||||
# toks -= token_fastest
|
||||
# print(100, token_fastest, toks / token_fastest, toks)
|
||||
|
||||
min_presses_fastest = 0
|
||||
max_presses_fastest = max_fastest
|
||||
while min_presses_fastest + 1 < max_presses_fastest:
|
||||
presses_fastest = int(
|
||||
math.floor((min_presses_fastest + max_presses_fastest) / 2)
|
||||
)
|
||||
print(120, min_presses_fastest, max_presses_fastest, presses_fastest)
|
||||
pri_x, pri_y = (
|
||||
prize[0] - button_fastest[0] * presses_fastest,
|
||||
prize[1] - button_fastest[1] * presses_fastest,
|
||||
)
|
||||
slope_pri = slope((pri_x, pri_y))
|
||||
if slope_pri >= slope_but_min and slope_pri <= slope_but_max:
|
||||
min_presses_fastest = presses_fastest
|
||||
else:
|
||||
max_presses_fastest = presses_fastest
|
||||
|
||||
presses_fastest = max_presses_fastest
|
||||
pri_x, pri_y = (
|
||||
prize[0] - button_fastest[0] * presses_fastest,
|
||||
prize[1] - button_fastest[1] * presses_fastest,
|
||||
)
|
||||
pri_x += button_fastest[0]
|
||||
pri_y += button_fastest[1]
|
||||
toks = presses_fastest * token_fastest
|
||||
toks -= token_fastest
|
||||
|
||||
print(101, token_fastest, toks / token_fastest, toks)
|
||||
|
||||
# while pri_x > 0 and pri_y > 0:
|
||||
# toks += token_slowest
|
||||
# pri_x -= button_slowest[0]
|
||||
# pri_y -= button_slowest[1]
|
||||
# print(103, token_slowest, toks)
|
||||
# if (pri_x, pri_y) != (0, 0):
|
||||
# toks = None
|
||||
|
||||
presses_slowest, remainder = divmod(pri_x, button_slowest[0])
|
||||
if remainder == 0 and (pri_y == presses_slowest * button_slowest[1]):
|
||||
toks += presses_slowest * token_slowest
|
||||
else:
|
||||
toks = None
|
||||
# dist = norm((pri_x, pri_y))
|
||||
# rem_presses, remainder = divmod(dist, norm_slowest)
|
||||
# presses_slowest = dist / norm_slowest
|
||||
# if remainder == 0:
|
||||
# toks += rem_presses * token_slowest
|
||||
# else:
|
||||
# toks = None
|
||||
|
||||
#
|
||||
# with rich.progress.Progress() as progress:
|
||||
# nb_a = max_a
|
||||
# nb_b = 0
|
||||
# task_a = progress.add_task("Button A", total=max_a)
|
||||
# task_b = progress.add_task("Button B", total=max_b)
|
||||
# x = nb_a * button_a[0] + nb_b * button_b[0]
|
||||
# while nb_a > 0 or x < prize[0]:
|
||||
# # print(54, nb_a, nb_b)
|
||||
# if x == prize[0]:
|
||||
# y = nb_a * button_a[1] + nb_b * button_b[1]
|
||||
# if y == prize[1]:
|
||||
# tok = 3 * nb_a + 1 * nb_b
|
||||
# if toks is None or tok < toks:
|
||||
# toks = tok
|
||||
# if x >= prize[0]:
|
||||
# # print(67)
|
||||
# nb_a -= 1
|
||||
# # progress.update(task_a, advance=1)
|
||||
# elif x < prize[0]:
|
||||
# nb_b += 1
|
||||
# # print(71)
|
||||
# # progress.update(task_b, advance=1)
|
||||
# if nb_b > max_b:
|
||||
# break
|
||||
# x = nb_a * button_a[0] + nb_b * button_b[0]
|
||||
|
||||
# @functools.lru_cache(4096)
|
||||
# def fun(x: int, y: int) -> int | None:
|
||||
# if (x, y) == prize:
|
||||
# return 0
|
||||
# if x > prize[0] or y > prize[1]:
|
||||
# return None
|
||||
# ba = fun(x + button_a[0], y + button_a[1])
|
||||
# bb = fun(x + button_b[0], y + button_b[1])
|
||||
# if ba is not None:
|
||||
# ba += 3
|
||||
# if bb is not None:
|
||||
# bb += 1
|
||||
# if ba is None:
|
||||
# if bb is None:
|
||||
# return None
|
||||
# else:
|
||||
# return bb
|
||||
# else:
|
||||
# if bb is None or ba < bb:
|
||||
# return ba
|
||||
# else:
|
||||
# return bb
|
||||
#
|
||||
# toks = fun(0, 0)
|
||||
|
||||
print(43, arcade, toks)
|
||||
if toks is not None:
|
||||
ttoks += toks
|
||||
# break
|
||||
|
||||
print(ttoks)
|
123
2024/13/two_clean.py
Normal file
123
2024/13/two_clean.py
Normal file
|
@ -0,0 +1,123 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import math
|
||||
import re
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
coords = tuple[int, int]
|
||||
prizes: list[coords] = list()
|
||||
buttons: list[tuple[coords, coords]] = list()
|
||||
|
||||
for li, line in enumerate(lines):
|
||||
machine = li // 4
|
||||
offset = li % 4
|
||||
if offset == 0:
|
||||
match = re.match(r"^Button A: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_a = int(match[1]), int(match[2])
|
||||
elif offset == 1:
|
||||
match = re.match(r"^Button B: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_b = int(match[1]), int(match[2])
|
||||
buttons.append((button_a, button_b))
|
||||
elif offset == 2:
|
||||
match = re.match("^Prize: X=([0-9]+), Y=([0-9]+)$", line)
|
||||
assert match
|
||||
prize = int(match[1]), int(match[2])
|
||||
# prize = prize[0] + 10000000000000, prize[1] + 10000000000000
|
||||
prizes.append(prize)
|
||||
|
||||
assert len(prizes) == len(buttons)
|
||||
|
||||
|
||||
def slope(point: coords) -> float:
|
||||
return point[1] / point[0]
|
||||
|
||||
|
||||
def norm(point: coords) -> float:
|
||||
return math.sqrt(math.pow(point[1], 2) + math.pow(point[0], 2))
|
||||
|
||||
|
||||
ttoks = 0
|
||||
token_a, token_b = 3, 1
|
||||
for arcade, prize in enumerate(prizes):
|
||||
butts = buttons[arcade]
|
||||
button_a, button_b = butts
|
||||
|
||||
print(43, prize, button_a, button_b)
|
||||
toks = None
|
||||
|
||||
max_a_x = int(math.ceil(prize[0] / button_a[0]))
|
||||
max_a_y = int(math.ceil(prize[1] / button_a[1]))
|
||||
max_a = min(max_a_x, max_a_y)
|
||||
max_b_x = int(math.ceil(prize[0] / button_b[0]))
|
||||
max_b_y = int(math.ceil(prize[1] / button_b[1]))
|
||||
max_b = min(max_b_x, max_b_y)
|
||||
|
||||
slope_a = slope(button_a)
|
||||
slope_b = slope(button_b)
|
||||
slope_prize = slope(prize)
|
||||
slope_but_min = min(slope_a, slope_b)
|
||||
slope_but_max = max(slope_a, slope_b)
|
||||
if slope_prize < slope_but_min or slope_prize > slope_but_max:
|
||||
print("Not in range")
|
||||
continue
|
||||
|
||||
norm_a = norm(button_a)
|
||||
norm_b = norm(button_b)
|
||||
speed_a = norm_a / 3
|
||||
speed_b = norm_b / 1
|
||||
|
||||
if speed_a > speed_b:
|
||||
button_fastest, button_slowest = button_a, button_b
|
||||
token_fastest, token_slowest = token_a, token_b
|
||||
max_fastest = max_a
|
||||
else:
|
||||
button_fastest, button_slowest = button_b, button_a
|
||||
token_fastest, token_slowest = token_b, token_a
|
||||
max_fastest = max_b
|
||||
toks = 0
|
||||
|
||||
min_presses_fastest = 0
|
||||
max_presses_fastest = max_fastest
|
||||
while min_presses_fastest + 1 < max_presses_fastest:
|
||||
presses_fastest = int(
|
||||
math.floor((min_presses_fastest + max_presses_fastest) / 2)
|
||||
)
|
||||
pri_x, pri_y = (
|
||||
prize[0] - button_fastest[0] * presses_fastest,
|
||||
prize[1] - button_fastest[1] * presses_fastest,
|
||||
)
|
||||
slope_pri = slope((pri_x, pri_y))
|
||||
if slope_pri >= slope_but_min and slope_pri <= slope_but_max:
|
||||
min_presses_fastest = presses_fastest
|
||||
else:
|
||||
max_presses_fastest = presses_fastest
|
||||
|
||||
presses_fastest = max_presses_fastest
|
||||
pri_x, pri_y = (
|
||||
prize[0] - button_fastest[0] * presses_fastest,
|
||||
prize[1] - button_fastest[1] * presses_fastest,
|
||||
)
|
||||
pri_x += button_fastest[0]
|
||||
pri_y += button_fastest[1]
|
||||
toks = presses_fastest * token_fastest
|
||||
toks -= token_fastest
|
||||
|
||||
|
||||
presses_slowest, remainder = divmod(pri_x, button_slowest[0])
|
||||
if remainder == 0 and (pri_y == presses_slowest * button_slowest[1]):
|
||||
toks += presses_slowest * token_slowest
|
||||
else:
|
||||
toks = None
|
||||
|
||||
print(76, toks)
|
||||
if toks is not None:
|
||||
ttoks += toks
|
||||
|
||||
print(ttoks)
|
64
2024/13/two_reddit.py
Normal file
64
2024/13/two_reddit.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Implementing:
|
||||
https://www.reddit.com/r/adventofcode/comments/1hd7irq/2024_day_13_an_explanation_of_the_mathematics/
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
coords = tuple[int, int]
|
||||
prizes: list[coords] = list()
|
||||
buttons: list[tuple[coords, coords]] = list()
|
||||
|
||||
for li, line in enumerate(lines):
|
||||
machine = li // 4
|
||||
offset = li % 4
|
||||
if offset == 0:
|
||||
match = re.match(r"^Button A: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_a = int(match[1]), int(match[2])
|
||||
elif offset == 1:
|
||||
match = re.match(r"^Button B: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_b = int(match[1]), int(match[2])
|
||||
buttons.append((button_a, button_b))
|
||||
elif offset == 2:
|
||||
match = re.match("^Prize: X=([0-9]+), Y=([0-9]+)$", line)
|
||||
assert match
|
||||
prize = int(match[1]), int(match[2])
|
||||
# prize = prize[0] + 10000000000000, prize[1] + 10000000000000
|
||||
prizes.append(prize)
|
||||
|
||||
assert len(prizes) == len(buttons)
|
||||
|
||||
ttoks = 0
|
||||
token_a, token_b = 3, 1
|
||||
for arcade, prize in enumerate(prizes):
|
||||
butts = buttons[arcade]
|
||||
button_a, button_b = butts
|
||||
|
||||
print(43, prize, button_a, button_b)
|
||||
p_x, p_y = prize
|
||||
a_x, a_y = button_a
|
||||
b_x, b_y = button_b
|
||||
|
||||
denom = a_x * b_y - a_y * b_x
|
||||
a = (p_x * b_y - p_y * b_x) / denom
|
||||
b = (a_x * p_y - a_y * p_x) / denom
|
||||
|
||||
if not a.is_integer() or not b.is_integer():
|
||||
print(76, None)
|
||||
continue
|
||||
|
||||
toks = int(a) * token_a + int(b) * token_b
|
||||
print(76, toks)
|
||||
ttoks += toks
|
||||
|
||||
print(ttoks)
|
82
2024/13/two_simpy.py
Normal file
82
2024/13/two_simpy.py
Normal file
|
@ -0,0 +1,82 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Someone mentionned sympy on reddit, wanted to see what I could do with it.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
import sympy
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
coords = tuple[int, int]
|
||||
prizes: list[coords] = list()
|
||||
buttons: list[tuple[coords, coords]] = list()
|
||||
|
||||
for li, line in enumerate(lines):
|
||||
machine = li // 4
|
||||
offset = li % 4
|
||||
if offset == 0:
|
||||
match = re.match(r"^Button A: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_a = int(match[1]), int(match[2])
|
||||
elif offset == 1:
|
||||
match = re.match(r"^Button B: X\+([0-9]+), Y\+([0-9]+)$", line)
|
||||
assert match
|
||||
button_b = int(match[1]), int(match[2])
|
||||
buttons.append((button_a, button_b))
|
||||
elif offset == 2:
|
||||
match = re.match("^Prize: X=([0-9]+), Y=([0-9]+)$", line)
|
||||
assert match
|
||||
prize = int(match[1]), int(match[2])
|
||||
# prize = prize[0] + 10000000000000, prize[1] + 10000000000000
|
||||
prizes.append(prize)
|
||||
|
||||
assert len(prizes) == len(buttons)
|
||||
|
||||
sympy.init_printing()
|
||||
|
||||
a, b, Ax, Ay, Bx, By, Px, Py = sympy.symbols(
|
||||
"a b Ax Ay Bx By Px Py", positive=True, integer=True
|
||||
)
|
||||
x_eq = sympy.Eq(a * Ax + b * Bx, Px)
|
||||
y_eq = sympy.Eq(a * Ay + b * By, Py)
|
||||
tokens = 3 * a + 1 * b
|
||||
sols = sympy.solve([x_eq, y_eq], a, b, dict=True)
|
||||
# In that case, should use linsolve directly (solve ain't great)
|
||||
# Would allow to .subs the whole solution set at once.
|
||||
|
||||
ttoks = sympy.Integer(0)
|
||||
for arcade, prize in enumerate(prizes):
|
||||
button_a, button_b = buttons[arcade]
|
||||
|
||||
print(43, prize, button_a, button_b)
|
||||
|
||||
vars = {
|
||||
Ax: button_a[0],
|
||||
Ay: button_a[1],
|
||||
Bx: button_b[0],
|
||||
By: button_b[1],
|
||||
Px: prize[0],
|
||||
Py: prize[1],
|
||||
}
|
||||
toks = None
|
||||
for sol in sols:
|
||||
a_presses, b_presses = sol[a].subs(vars), sol[b].subs(vars)
|
||||
if not a_presses.is_integer or not b_presses.is_integer:
|
||||
continue
|
||||
ntoks = tokens.subs({a: a_presses, b: b_presses})
|
||||
if toks is None or ntoks < toks:
|
||||
toks = ntoks
|
||||
|
||||
print(76, toks)
|
||||
if toks is not None:
|
||||
ttoks += toks
|
||||
|
||||
assert ttoks.is_integer
|
||||
print(int(ttoks.evalf()))
|
88
2024/14/one.py
Normal file
88
2024/14/one.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
import functools
|
||||
import re
|
||||
import sys
|
||||
|
||||
input_file = sys.argv[1]
|
||||
|
||||
with open(input_file) as fd:
|
||||
lines = [line.rstrip() for line in fd.readlines()]
|
||||
|
||||
vec = tuple[int, int]
|
||||
poss: list[vec] = list()
|
||||
vits: list[vec] = list()
|
||||
|
||||
for line in lines:
|
||||
match = re.findall(r"(-?\d+)", line)
|
||||
assert match
|
||||
pos = int(match[0]), int(match[1])
|
||||
vit = int(match[2]), int(match[3])
|
||||
poss.append(pos)
|
||||
vits.append(vit)
|
||||
|
||||
print(poss, vits)
|
||||
|
||||
|
||||
def print_poss(poss: list[vec]) -> None:
|
||||
viz = [[0] * width for _ in range(height)]
|
||||
for pos in poss:
|
||||
px, py = pos
|
||||
viz[py][px] += 1
|
||||
for line in viz:
|
||||
print("".join([(str(c) if c > 0 else ".") for c in line]))
|
||||
print()
|
||||
|
||||
|
||||
# x→ y↓
|
||||
if input_file == "input":
|
||||
width = 101
|
||||
height = 103
|
||||
else:
|
||||
width = 11
|
||||
height = 7
|
||||
if input_file == "demo1":
|
||||
secs = 5
|
||||
else:
|
||||
secs = 100
|
||||
|
||||
print_poss(poss)
|
||||
|
||||
for s in range(secs):
|
||||
for r, vit in enumerate(vits):
|
||||
px, py = poss[r]
|
||||
px += vit[0]
|
||||
py += |