Advent of code

 22 décembre 2022 

  Monkey Map : Se déplacer sur une carte 2D d'un tore, puis sur un cube
   ..................#..
   
   #......#........##..#
   
             ⋮   
  
   
36R27L7R50R50L10L1R4R47L15
  1. codeToutFaitALaMain.py
  2. codeMeilleurMaisPasTop.py
  3. codeAutomatique.py
### CODE pour *mon* input seulement: pas de détection de la forme du dé, tout est codé à la main, mais cette fois seulement 7 lignes à calculer au lieu de 28
### Pas eu le temps de récrire les noms de variables et de fonctions au propre...

import re
f = open("input.txt", 'r')
lines = [line[:-1] for line in f.readlines()]

INSTRUCTIONS = tuple(map(lambda x:x in 'RL' and x or int(x), re.findall('[0-9]+|[RL]', lines[-1])))
lines = lines[:-2]

HEIGHT = len(lines)
WIDTH = 0
for line in lines:
    if len(line) > WIDTH:
        WIDTH = len(line)

lines = [WIDTH*" "] + lines + [WIDTH*" "]
for i in range(len(lines)):
    lines[i] = " " + lines[i] + (WIDTH+1)*" "
WIDTH += 2
HEIGHT += 2

DROITE, BASE, GAUCHE, HAUT = list(range(4))
DIRS = [(1,0), (0,1), (-1,0), (0,-1)]
SYMBOLE = ['>', 'v', '<', '^']

START_Y = 1
START_X = lines[START_Y].index('.')


# Partie 1: fonction calculant le prochain endroit, None si obstacle
def nextXY1(lines, dirIndex, x, y):
    move = True
    while move:
        x = (x + DIRS[dirIndex][0]) % WIDTH
        y = (y + DIRS[dirIndex][1]) % HEIGHT
        if lines[y][x] == '#':
            return None
        move = (lines[y][x] == ' ')
    return (x,y,dirIndex)


# Pour partie 2
correspondances = {}
    
def departSegment(col, row, dirIndex, entree=False):
    dirIndex = (dirIndex + 1) % len(DIRS)   # tourner à droite
    ajout = {DROITE:(1,1), BAS:(50,1), GAUCHE:(50,50), HAUT:(1,50)}[(dirIndex + (entree and 3 or 0)) % 4]
    x,y = 50*col + ajout[0], 50*row + ajout[1]
    return (x,y,dirIndex)

def addCorrespondances(col1, row1, dirIndex1, col2, row2, dirIndex2):
    global correspondances
    x1,y1,d1 = departSegment(col1, row1, dirIndex1, entree=False)
    x2,y2,d2 = departSegment(col2, row2, dirIndex2, entree=True)

    for i in range(50):
        nx1, ny1 = x1 + i * DIRS[d1][0], y1 + i * DIRS[d1][1]
        nx2, ny2 = x2 + i * DIRS[d2][0], y2 + i * DIRS[d2][1]
        correspondances[(nx1 + DIRS[dirIndex1][0], ny1 + DIRS[dirIndex1][1], dirIndex1)] = (nx2, ny2, dirIndex2)
        dirRetour1 = (dirIndex1 + 2) % 4
        dirRetour2 = (dirIndex2 + 2) % 4
        correspondances[(nx2 + DIRS[dirRetour2][0], ny2 + DIRS[dirRetour2][1], dirRetour2)] = (nx1, ny1, dirRetour1)

### LES CORRESPONDANCES À CALCULER À LA MAIN ###
addCorrespondances(1,0,HAUT, 0,3,DROITE)
addCorrespondances(1,0,GAUCHE, 0,2,DROITE)
addCorrespondances(2,0,HAUT, 0,3,HAUT)
addCorrespondances(2,0,DROITE, 1,2,GAUCHE)
addCorrespondances(1,1,GAUCHE, 0,2, BAS)
addCorrespondances(1,1,DROITE, 2,0,HAUT)
addCorrespondances(1,2,BAS, 0,3,GAUCHE)


def nextXY2(lines, dirIndex, x, y):
    x = (x + DIRS[dirIndex][0])
    y = (y + DIRS[dirIndex][1])
    if lines[y][x] == ' ':
        x,y,dirIndex = correspondances[(x,y,dirIndex)]

    if lines[y][x] == '#':
        return None
    else:
        return (x,y, dirIndex)
    

def avancer(lines, dirIndex, d, x, y):
    for _ in range(d):
        nxt = nextXY(lines, dirIndex, x, y)
        if nxt == None:
            break
        else:
            x,y,dirIndex = nxt
            # lines[y] = lines[y][:x] + SYMBOLE[dirIndex] + lines[y][x+1:]    # pour visualiser, ne change pas les obstacles '#'
    return (x, y, dirIndex)



for partie in [1, 2]:
    x = START_X
    y = START_Y
    dirIndex = DROITE
    if partie == 1:
        nextXY = nextXY1
    else:
        nextXY = nextXY2

    for instr in INSTRUCTIONS:
        if instr in ['R', 'L']:
            if instr == 'R':
                dirIndex = (dirIndex + 1) % len(DIRS)
            elif instr == 'L':
                dirIndex = (dirIndex - 1) % len(DIRS)
        else:
            x, y, dirIndex = avancer(lines, dirIndex, instr, x, y)


    print("Réponse partie "+str(partie)+":", 1000*y + 4*x + dirIndex)