This commit is contained in:
augustin64 2023-12-01 10:54:02 +01:00
parent 44d067f79c
commit 94d71c9071
6 changed files with 762 additions and 0 deletions

91
2022/day13.py Executable file
View File

@ -0,0 +1,91 @@
#!/usr/bin/python3
"""
Jour 13 du défi Advent Of Code pour l'année 2022
"""
import functools
def read_sample():
"""récupère les entrées depuis le fichier texte correspondant"""
with open('inputs/day13.txt', 'r') as f:
sample = f.read().split('\n\n')
sample = [ [eval(j) for j in i.split('\n') if j != ''] for i in sample if i != '' ]
return sample
def is_right_order(elem1, elem2):
if type(elem1) == type(0) and type(elem2) == type(0): # two ints
if elem1 == elem2:
return None
return elem1 < elem2
if type(elem1) == type([]) and type(elem2) == type([]): # two lists
if len(elem1) == 0:
return True
for i in range(len(elem1)):
if i > len(elem2)-1:
return False # Out
order = is_right_order(elem1[i], elem2[i])
if order is not None:
return order
return is_right_order(len(elem1), len(elem2))
if type(elem1) == type(0) and type(elem2) == type([]):
return is_right_order([elem1], elem2)
if type(elem2) == type(0) and type(elem1) == type([]):
return is_right_order(elem1, [elem2])
def part1(sample):
"""Partie 1 du défi"""
somme = 0
for i in range(len(sample)):
order = is_right_order(sample[i][0], sample[i][1])
if order is None:
order = True
if order:
somme += i+1
return somme
def part2(sample):
"""Partie 2 du défi"""
n_sample = []
for i in sample:
for j in i:
n_sample.append(j)
n_sample.append([[2]])
n_sample.append([[6]])
def comparaison(x, y):
order = is_right_order(x, y)
if order is None:
return 0
if order:
return 1
return -1
keys = functools.cmp_to_key(comparaison)
n_sample = sorted(n_sample, key=keys)
n_sample.reverse()
tot = 1
for ind in range(len(n_sample)):
i = n_sample[ind]
if len(i)==1 and isinstance(i[0], list) and len(i[0])==1 and i[0][0]==2:
tot *= ind+1
elif len(i)==1 and isinstance(i[0], list) and len(i[0])==1 and i[0][0]==6:
tot *= ind+1
return tot
def main():
"""Fonction principale"""
sample = read_sample()
print(f"part1: {part1(read_sample())}")
print(f"part2: {part2(read_sample())}")
if __name__ == "__main__":
main()

116
2022/day14.py Executable file
View File

@ -0,0 +1,116 @@
#!/usr/bin/python3
"""
Jour 14 du défi Advent Of Code pour l'année 2022
"""
def read_sample():
"""récupère les entrées depuis le fichier texte correspondant"""
with open('inputs/day14.txt', 'r') as f:
sample = f.read().split('\n')
sample = [ [eval(j) for j in i.split(" -> ")] for i in sample if i != '' ]
return [[(j[1], j[0]) for j in i] for i in sample]
def create_map(sample):
maxi_0 = max([max([j[0] for j in i]) for i in sample])+1
maxi_1 = max([max([j[1] for j in i]) for i in sample])+120
map_ = [['.' for _ in range(maxi_1)] for _ in range(maxi_0)]
for line in sample:
for i in range(len(line)-1):
if line[i][0] == line[i+1][0]:
for j in range(min(line[i][1], line[i+1][1]), max(line[i][1], line[i+1][1])+1):
map_[line[i][0]][j] = '#'
else:
for j in range(min(line[i][0], line[i+1][0]), max(line[i][0], line[i+1][0])+1):
map_[j][line[i][1]] = '#'
return map_
def print_map(map_, sample):
mini = min([min([j[1] for j in i]) for i in sample])-15
for i in range(len(map_)):
print(i, "".join(map_[i][mini:]))
def make_sand_fall(map_, sand_source):
sand_pos = sand_source
while(sand_pos[0] >= 0 and sand_pos[0] < len(map_) and sand_pos[1] >= 0 and sand_pos[1] < len(map_[0])):
try:
if map_[sand_pos[0]+1][sand_pos[1]] == '.':
sand_pos = (sand_pos[0]+1, sand_pos[1])
elif map_[sand_pos[0]+1][sand_pos[1]-1] == '.':
sand_pos = (sand_pos[0]+1, sand_pos[1]-1)
elif map_[sand_pos[0]+1][sand_pos[1]+1] == '.':
sand_pos = (sand_pos[0]+1, sand_pos[1]+1)
else:
map_[sand_pos[0]][sand_pos[1]] = 'o'
return True
except:
return False
return False
def part1(sample):
"""Partie 1 du défi"""
map_ = create_map(sample)
sand_source = (0,500)
test = True
while (test):
test = make_sand_fall(map_, sand_source)
#print_map(map_, sample)
cpt = 0
for k in map_:
for j in k:
if j == 'o':
cpt += 1
return cpt
def create_map2(sample):
maxi_0 = max([max([j[0] for j in i]) for i in sample])+3
maxi_1 = max([max([j[1] for j in i]) for i in sample])+1+maxi_0 # +maxi0 car put tomber sur les bords
map_ = [['.' for _ in range(maxi_1)] for _ in range(maxi_0)]
for line in sample:
for i in range(len(line)-1):
if line[i][0] == line[i+1][0]:
for j in range(min(line[i][1], line[i+1][1]), max(line[i][1], line[i+1][1])+1):
map_[line[i][0]][j] = '#'
else:
for j in range(min(line[i][0], line[i+1][0]), max(line[i][0], line[i+1][0])+1):
map_[j][line[i][1]] = '#'
for i in range(len(map_[0])):
map_[-1][i] = '#'
return map_
def part2(sample):
"""Partie 2 du défi"""
map_ = create_map2(sample)
sand_source = (0,500)
test = True
while (test and map_[sand_source[0]][sand_source[1]] == '.'):
test = make_sand_fall(map_, sand_source)
print_map(map_, sample)
cpt = 0
for k in map_:
for j in k:
if j == 'o':
cpt += 1
return cpt
def main():
"""Fonction principale"""
sample = read_sample()
print(f"part1: {part1(sample)}")# 1409 too low # 1515 too high
print(f"part2: {part2(sample)}")
if __name__ == "__main__":
main()

159
2022/day15.py Executable file
View File

@ -0,0 +1,159 @@
#!/usr/bin/python3
"""
Jour 15 du défi Advent Of Code pour l'année 2022
"""
from tqdm import tqdm
def read_sample():
"""récupère les entrées depuis le fichier texte correspondant"""
with open('inputs/day15.txt', 'r') as f:
sample = f.read().split('\n')
sample = [ i for i in sample if i != '' ]
return sample
def parse_sample(sample):
sensors = []
for line in sample:
spl = line.split(", ")
tmp1 = int(spl[0].split("x=")[1])
tmp2 = int(spl[1].split("y=")[1].split(":")[0])
tmp3 = int(spl[1].split("x=")[1])
tmp4 = int(spl[2].split("y=")[1].split(":")[0])
sensors.append(((tmp1, tmp2), (tmp3, tmp4)))
return sensors
def intersection(seg1, seg2):
seg = []
for line in seg1:
added = False
for line2 in seg2:
if line[0] >= line2[0] and line[1] <= line2[1]:
added = True
seg.append(line)
break
if not added:
for line2 in seg2:
if line[0] <= line2[1]:
seg.append((max(line2[0], line[0]), min(line[1], line2[1])))
elif line[1] >= line2[0]:
None#yet
return seg
def overlapping_segment(a, b):
x = max(a[0], b[0])
y = min(a[1], b[1])
return x,y
def find_overlaps(r, b):
retVal = []
ri = 0
bi = 0
while (ri < len(r)) and (bi < len(b)):
s = overlapping_segment(r[ri], b[bi])
if s[0] < s[1]:
retVal.append([ri, bi])
if r[ri][1] == s[1]:
ri += 1
if b[bi][1] == s[1]:
bi += bi + 1
return retVal
def taille_seg(segment):
taille = 0
for i in segment:
taille += i[1]-i[0]+1
return taille
def manhattan(x, y):
return abs(x[0]-y[0]) + abs(x[1]-y[1])
def create_map(sensors):
maxi_x = max([x[0]+manhattan(x, y) for (x, y) in sensors])
maxi_y = max([x[1]+manhattan(x, y) for (x, y) in sensors])
map_ = [['.' for _ in range(maxi_y)] for _ in range(maxi_x)]
for i in range(len(map_)):
for j in range(len(map_[0])):
for sensor in sensors:
if manhattan(sensor[0], sensor[1]) > manhattan(sensor[0], (i, j)):
map_[i][j] = '#'
return map_
def part1(sample):
"""Partie 1 du défi"""
sensors = parse_sample(sample)
maxi_y = max([x[1]+manhattan(x, y) for (x, y) in sensors])
mini_y = min([x[1]-manhattan(x, y) for (x, y) in sensors])
cpt = 0
j = 10
j=2000000
seg = [(mini_y, maxi_y)]
for sensor in sensors:
d = manhattan(sensor[0], sensor[1])
if d+sensor[0][0] >= j:
a = sensor[0][0] - j + d
print(seg)
print([(mini_y, sensor[0][1]-a), (sensor[0][1]+a, maxi_y)])
seg = find_overlaps(seg, [(mini_y, sensor[0][1]-a), (sensor[0][1]+a, maxi_y)])
print("=>",seg)
if sensor[0][0]-d <= j:
a = -sensor[0][0] + j + d
#print([(mini_y, sensor[0][1]-a), (sensor[0][1]+a, maxi_y)])
seg = find_overlaps(seg, [(mini_y, sensor[0][1]-a), (sensor[0][1]+a, maxi_y)])
print(seg, taille_seg(seg))
taille = taille_seg(seg)
"""
for i in range(mini_y, maxi_y):
for sensor in sensors:
if manhattan(sensor[0], sensor[1]) >= manhattan(sensor[0], (i, j)):
if True not in [ a==i and b==j for ((_, _), (a, b)) in sensors ]:
cpt += 1
break
"""
return (maxi_y-mini_y)-taille
def part2(sample):
"""Partie 2 du défi"""
sensors = parse_sample(sample)
maxi = 4000000
#maxi = 20
dists = {}
for i in range(len(sensors)):
dists[i] = manhattan(sensors[i][0], sensors[i][1])
for i in tqdm(range(maxi)):
for j in range(maxi):
test = True
for k in range(len(sensors)):
if test:
if dists[k] >= manhattan(sensors[k][0], (i, j)):
test = False
if test:
return (i, j)
def main():
"""Fonction principale"""
sample = read_sample()
print(f"part1: {part1(sample)}")
print(f"part2: {part2(read_sample())}")
if __name__ == "__main__":
main()

77
2022/day16.py Executable file
View File

@ -0,0 +1,77 @@
#!/usr/bin/python3
"""
Jour 16 du défi Advent Of Code pour l'année 2022
"""
import copy
def read_sample():
"""récupère les entrées depuis le fichier texte correspondant"""
with open('inputs/day16.txt', 'r') as f:
sample = f.read().split('\n')
sample = [ i for i in sample if i != '' ]
data = []
for line in sample:
split = line.split(" ")
"Valve AA has flow rate=0; tunnels lead to valves DD, II, BB"
valve_nb = split[1]
flow_rate = int(split[4].split("=")[-1].split(";")[0])
lead_to = " ".join(split[9:]).split(", ")
data.append((valve_nb, flow_rate, lead_to))
return data
def floyd_warshall(valves):
dist = {v: {u: int(1e9) for u in valves} for v in valves}
for v in valves:
dist[v][v] = 0
for u in valves[v]["lead_to"]:
dist[v][u] = 1
for k in valves:
for i in valves:
for j in valves:
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
return dist
def part1(sample):
"""Partie 1 du défi"""
data = {}
for i in sample:
data[i[0]] = {"enabled":False, "flow_rate": i[1], "lead_to": i[2]}
distances = floyd_warshall(data)
non_zero = [v for v in data if data[v]["flow_rate"] > 0]
def generate_open_options(pos, opened, time_left):
for next in non_zero:
if next not in opened and distances[pos][next] <= time_left:
opened.append(next)
yield from generate_open_options(
next, opened, time_left - distances[pos][next] - 1
)
opened.pop()
yield copy.copy(opened)
def get_order_score(open_order, time_left):
now, ans = "AA", 0
for pos in open_order:
time_left -= distances[now][pos] + 1
ans += data[pos]["flow_rate"] * time_left
now = pos
return ans
return max(get_order_score(ordre, 30) for ordre in generate_open_options("AA", [], 30))
def part2(sample):
"""Partie 2 du défi"""
return NotImplementedError
def main():
"""Fonction principale"""
sample = read_sample()
print(f"part1: {part1(sample)}")
print(f"part2: {part2(sample)}")
if __name__ == "__main__":
main()

179
2022/day18.py Executable file
View File

@ -0,0 +1,179 @@
#!/usr/bin/python3
"""
Jour 18 du défi Advent Of Code pour l'année 2022
"""
import copy
def read_sample():
"""récupère les entrées depuis le fichier texte correspondant"""
with open('inputs/day18.txt', 'r') as f:
#with open('test.txt', 'r') as f:
sample = f.read().split('\n')
sample = [ (int(i.split(",")[0]), int(i.split(",")[1]), int(i.split(",")[2])) for i in sample if i != '' ]
return sample
def nb_voisins(cube, sample):
vois = 0
if (cube[0]-1, cube[1], cube[2]) in sample:
vois += 1
if (cube[0]+1, cube[1], cube[2]) in sample:
vois += 1
if (cube[0], cube[1]-1, cube[2]) in sample:
vois += 1
if (cube[0], cube[1]+1, cube[2]) in sample:
vois += 1
if (cube[0], cube[1], cube[2]-1) in sample:
vois += 1
if (cube[0], cube[1], cube[2]+1) in sample:
vois += 1
return vois
def nb_voisins2(cube, sample, carte, num):
vois = 0
x, y, z = cube
if (x-1, y, z) in sample and carte[x-1][y][z] == num:
vois += 1
if (x+1, y, z) in sample and carte[x+1][y][z] == num:
vois += 1
if (x, y-1, z) in sample and carte[x][y-1][z] == num:
vois += 1
if (x, y+1, z) in sample and carte[x][y+1][z] == num:
vois += 1
if (x, y, z-1) in sample and carte[x][y][z-1] == num:
vois += 1
if (x, y, z+1) in sample and carte[x][y][z+1] == num:
vois += 1
return vois
def part1(sample):
"""Partie 1 du défi"""
sides = 6*len(sample)
for cube in sample:
sides -= nb_voisins(cube, sample)
return sides
def print_cubes(sample, carte=None):
min_x, max_x = 0, max([i[0] for i in sample])+2
min_y, max_y = 0, max([i[1] for i in sample])+2
min_z, max_z = 0, max([i[2] for i in sample])+2
for z in range(min_z, max_z):
print(f"\n--- Couche {z} ---\n")
for y in range(min_x, max_x):
for x in range(min_x, max_x):
if carte is not None and carte[x][y][z] == 2:
print("%", end="")
elif (x, y, z) in sample:
print("#", end="")
elif carte is not None and carte[x][y][z] == 1:
print('.', end="")
else:
print(" ", end="")
print()
def init_propagation(carte):
for x in range(len(carte)):
for y in range(len(carte[0])):
for z in range(len(carte[0][0])):
if x == 0 or y == 0 or z == 0 or x == len(carte)-1 or y == len(carte[0])-1 or z == len(carte[0][0])-1:
carte[x][y][z] = 1
def propagation(cart, sample):
carte = copy.deepcopy(cart)
modif = False
for x in range(len(carte)):
for y in range(len(carte[0])):
for z in range(len(carte[0][0])):
bon = False
if not(x == 0 or y == 0 or z == 0 or x == len(carte)-1 or y == len(carte[0])-1 or z == len(carte[0][0])-1 or cart[x][y][z] != 0):
if cart[x-1][y][z]==1:
bon = True
elif cart[x+1][y][z]==1:
bon = True
elif cart[x][y+1][z]==1:
bon = True
elif cart[x][y-1][z]==1:
bon = True
elif cart[x][y][z+1]==1:
bon = True
elif cart[x][y][z+1]==1:
bon = True
if bon:
if (x, y, z) in sample:
carte[x][y][z] = 2
else:
carte[x][y][z] = 1
modif = True
return modif, carte
def part2(sample):
"""Partie 2 du défi, simule l'eau qui se propage"""
min_x, max_x = 0, max([i[0] for i in sample])+2
min_y, max_y = 0, max([i[1] for i in sample])+2
min_z, max_z = 0, max([i[2] for i in sample])+2
carte = [[[0 for z in range(min_z, max_z)] for y in range(min_y, max_y)] for x in range(min_x, max_x)]
init_propagation(carte)
test, carte = propagation(carte, sample)
while(test):
test, carte = propagation(carte, sample)
None
sides = part1(sample)
for x in range(len(carte)):
for y in range(len(carte[0])):
for z in range(len(carte[0][0])):
if carte[x][y][z] == 0:
sides -= nb_voisins2((x, y, z), sample, carte, 2)
return sides
def is_exterior(cube, sample):
if nb_voisins(cube, sample) == 6:
return False
if cube[0] == min([i[0] for i in sample if (i[1], i[2])==(cube[1], cube[2])]):
return True
if cube[0] == max([i[0] for i in sample if (i[1], i[2])==(cube[1], cube[2])]):
return True
if cube[1] == min([i[1] for i in sample if (i[0], i[2])==(cube[0], cube[2])]):
return True
if cube[1] == max([i[1] for i in sample if (i[0], i[2])==(cube[0], cube[2])]):
return True
if cube[2] == min([i[2] for i in sample if (i[0], i[1])==(cube[0], cube[1])]):
return True
if cube[2] == max([i[2] for i in sample if (i[0], i[1])==(cube[0], cube[1])]):
return True
return False
def part2_old(sample):
"""Partie 2 du défi"""
"""Ne regarde que les extrema, omet des résultats"""
sides = 6*len(sample)
for cube in sample:
if not is_exterior(cube, sample):
sides -= 6
else:
sides -= nb_voisins(cube, sample)
return sides
def main():
"""Fonction principale"""
sample = read_sample()
print(f"part1: {part1(sample)}")
print(f"part2: {part2(sample)}")
if __name__ == "__main__":
main()

140
2022/day21.py Executable file
View File

@ -0,0 +1,140 @@
#!/usr/bin/python3
"""
Jour 21 du défi Advent Of Code pour l'année 2022
"""
from tqdm import tqdm
def read_sample():
"""récupère les entrées depuis le fichier texte correspondant"""
with open('inputs/day21.txt', 'r') as f:
#with open('test.txt', 'r') as f:
sample = f.read().split('\n')
sample = [ Monkey(i) for i in sample if i != '' ]
return sample
class Monkey():
def __init__(self, data):
self.name = data.split(": ")[0]
self.has_yelled = False
self.value = -1
if len(data.split(": ")[1].split(" ")) == 1:
self.dependencies = []
self.operation = lambda x : int(data.split(": ")[1])
else:
self.dependencies = [data.split(": ")[1].split(" ")[0], data.split(": ")[1].split(" ")[2]]
self.operator = data.split(': ')[1].split(' ')[1]
self.operation = lambda deps: eval(f"deps[0] {data.split(': ')[1].split(' ')[1]} deps[1]")
def evaluate(self, data):
if len(self.dependencies) == 0:
self.has_yelled = True
self.value = self.operation(0)
return
for name in self.dependencies:
monkey = data[name]
if not monkey.has_yelled:
monkey.evaluate(data)
self.has_yelled = True
self.value = self.operation((data[self.dependencies[0]].value, data[self.dependencies[1]].value))
def get_recursive_dependencies(self, data):
if len(self.dependencies) == 0:
return [self.name]
return data[self.dependencies[0]].get_recursive_dependencies(data) + data[self.dependencies[1]].get_recursive_dependencies(data) + [self.name]
def find_value(self, value, name, data):
if self.name == name:
return int(value)
if name in data[data[self.name].dependencies[0]].get_recursive_dependencies(data):
change_me = data[data[self.name].dependencies[0]]
other = data[data[self.name].dependencies[1]]
else:
change_me = data[data[self.name].dependencies[1]]
other = data[data[self.name].dependencies[0]]
other.evaluate(data)
if self.operator == '*':
return int(change_me.find_value(value/other.value, name, data))
if self.operator == '+':
return int(change_me.find_value(value-other.value, name, data))
if change_me.name == data[data[self.name].dependencies[1]]:
if self.operator == '/':
return int(change_me.find_value(other.value/value, name, data))
if self.operator == '-':
return int(change_me.find_value(other.value-value, name, data))
if self.operator == '/':
return int(change_me.find_value(other.value*value, name, data)) # Not really)
if self.operator == '-':
return int(change_me.find_value(other.value+value, name, data))
def part1(sample):
"""Partie 1 du défi"""
data = {}
for monkey in sample:
data[monkey.name] = monkey
data["root"].evaluate(data)
return data["root"].value
def part2_brute():
"""Partie 2 du défi"""
"""Relativement lent, mais l'approche par brute force finit par fonctionner"""
for i in tqdm(range(3876907167494-5, 3876907167494+5)):
sample = read_sample()
data = {}
for monkey in sample:
data[monkey.name] = monkey
data["humn"].value = i
data["humn"].has_yelled = True
data[data["root"].dependencies[0]].evaluate(data)
data[data["root"].dependencies[1]].evaluate(data)
if data[data["root"].dependencies[0]].value == data[data["root"].dependencies[1]].value:
return i
return NotImplementedError
def part2(sample):
"""Partie 2 du défi"""
"""Ne fonctionne pas"""
data = {}
for monkey in sample:
data[monkey.name] = monkey
if "humn" in data[data["root"].dependencies[0]].get_recursive_dependencies(data):
humn = data[data["root"].dependencies[0]]
other = data[data["root"].dependencies[1]]
else:
humn = data[data["root"].dependencies[1]]
other = data[data["root"].dependencies[0]]
other.evaluate(data)
return humn.find_value(other.value, "humn", data)
def main():
"""Fonction principale"""
sample = read_sample()
print(f"part1: {part1(sample)}")
print(f"part2: {part2(read_sample())}")
print(f"part2 bruteforce: {part2_brute()}")
if __name__ == "__main__":
main()