diff --git a/2022/day12.py b/2022/day12.py new file mode 100755 index 0000000..32e9d2f --- /dev/null +++ b/2022/day12.py @@ -0,0 +1,162 @@ +#!/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() \ No newline at end of file