advent-of-code/2022/day12.py

162 lines
4.8 KiB
Python
Raw Permalink Normal View History

2022-12-12 18:09:33 +01:00
#!/usr/bin/python3
"""
Jour 12 du défi Advent Of Code pour l'année 2022
"""
import copy # pour deepcopy
def read_sample():
"""récupère les entrées depuis le fichier texte correspondant"""
with open('inputs/day12.txt', 'r') as f:
sample = f.read().split('\n')
sample = [ [j for j in i] for i in sample if i != '' ]
return sample
def elevation(char):
return ord(char) - ord('a')
def direction(sample, i, j):
dirs = []
if i > 0 :
hdiff = (elevation(sample[i-1][j]) - elevation(sample[i][j]))
if hdiff <= 1:
dirs.append('up')
if j > 0:
hdiff = (elevation(sample[i][j-1]) - elevation(sample[i][j]))
if hdiff <= 1:
dirs.append('left')
if i < len(sample)-1 :
hdiff = (elevation(sample[i+1][j]) - elevation(sample[i][j]))
if hdiff <= 1:
dirs.append('down')
if j < len(sample[0])-1:
hdiff = (elevation(sample[i][j+1]) - elevation(sample[i][j]))
if hdiff <= 1:
dirs.append('right')
if len(dirs)==0:
return []
return dirs
def better_height(moves, heights, i, j, sample):
available = []
if heights[i][j] != -1:
available.append(heights[i][j])
if i > 0 :
if ('down' in moves[i-1][j] and heights[i-1][j] != -1):
available.append(heights[i-1][j]+1)
if j > 0:
if ('right' in moves[i][j-1] and heights[i][j-1] != -1):
available.append(heights[i][j-1]+1)
if i < len(sample)-1 :
if ('up' in moves[i+1][j] and heights[i+1][j] != -1):
available.append(heights[i+1][j]+1)
if j < len(sample[0])-1:
if ('left' in moves[i][j+1] and heights[i][j+1] != -1):
available.append(heights[i][j+1]+1)
if len(available) == 0:
return -1
return min(available)
def update_heights(moves, heights, sample):
changed = False
heights_c = copy.deepcopy(heights)
for i in range(len(sample)):
for j in range(len(sample[0])):
heights_c[i][j] = better_height(moves, heights, i, j, sample)
changed = changed or (heights_c[i][j] != heights[i][j])
return heights_c, changed
def print_val(sample, heights):
"""Afficher l'état actuel des chemins découverts"""
for i in range(len(sample)):
for j in range(len(sample[0])):
if heights[i][j] != -1:
print(f"\x1b[38;2;{heights[i][j]};{heights[i][j]};{heights[i][j]}m", end='')
else:
print("\x1b[38;2;0;0;0m", end='')
print("#", end='')
print("\033[0m")
def part1(sample):
"""Partie 1 du défi"""
start = (-1, -1)
end = (-1, -1)
# Récupère le début et la fin
for i in range(len(sample)):
for j in range(len(sample[0])):
if sample[i][j] == 'E':
end = (i, j)
sample[i][j] = 'z'
elif sample[i][j] == 'S':
start = (i, j)
sample[i][j] = 'a'
moves = [['.' for _ in range(len(sample[0]))] for _ in range(len(sample))]
# Calcul des positions directement accessibles
for i in range(len(sample)):
for j in range(len(sample[0])):
moves[i][j] = direction(sample, i, j)
# Initialisation des hauteurs
heights = [[-1 for _ in range(len(sample[0]))] for _ in range(len(sample))]
heights[start[0]][start[1]] = 0
steps = 0
changed = True
while heights[end[0]][end[1]] == -1 and changed:
steps += 1
heights, changed = update_heights(moves, heights, sample)
#print_val(sample, heights)
return heights[end[0]][end[1]]
def part2(sample):
"""Partie 2 du défi"""
start = (-1, -1)
end = (-1, -1)
for i in range(len(sample)):
for j in range(len(sample[0])):
if sample[i][j] == 'E':
end = (i, j)
sample[i][j] = 'z'
elif sample[i][j] == 'S':
start = (i, j)
sample[i][j] = 'a'
moves = [['.' for _ in range(len(sample[0]))] for _ in range(len(sample))]
for i in range(len(sample)):
for j in range(len(sample[0])):
moves[i][j] = direction(sample, i, j)
# Chaque 'a' est maintenant un point de départ
heights = [[-1 for _ in range(len(sample[0]))] for _ in range(len(sample))]
for i in range(len(sample)):
for j in range(len(sample[0])):
if sample[i][j] == 'a':
heights[i][j] = 0
steps = 0
changed = True
while heights[end[0]][end[1]] == -1 and changed:
steps += 1
heights, changed = update_heights(moves, heights, sample)
#print_val(sample, heights)
return heights[end[0]][end[1]]
def main():
"""Fonction principale"""
print(f"part1: {part1(read_sample())}")
print(f"part2: {part2(read_sample())}")
if __name__ == "__main__":
main()