162 lines
4.8 KiB
Python
162 lines
4.8 KiB
Python
|
#!/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()
|