Advent of code

 24 décembre 2023 

  Never Tell Me The Odds : Trouver des intersections de droites paramétriques, puis résolution d'équations non linéaires
233210433951170, 272655040388795, 179982504986147 @ 39, -98, 166
   
385274025881243, 351578921558552, 375160114124378 @ -71, -36, -9
   
298962016918939, 322446494312107, 293073189215975 @ 36, 8, 96
   
                                
Autre possibilité que de résoudre des équations compliquées en recommençant tant qu'on n'a pas les bonnes équations: trouver une paire de directions parallèles, ce qui donne un plan avec lequel intersecter les autres trajectoires.
  1. code1.py
  2. code2.py
  3. code2_paralleles.py
import re, itertools

FICHIER_TEST = False
if FICHIER_TEST:
    BORD_INF = 7
    BORD_SUP = 27
    file = 'input2.txt' 
else:
    BORD_INF = 200_000_000_000_000
    BORD_SUP = 400_000_000_000_000
    file = 'input.txt' 

f = open(file, 'r', encoding='utf-8')
lines = [line[:-1] for line in f.readlines()]

def parse_ints(line: str) -> list[int]:
    return [ int(token) for token in re.split('[^-0-9]+', line) if token ]

Vecteur  = tuple[int,int,int]
Position = tuple[int,int,int]

pos: list[Position] = []
vit: list[Vecteur] = []

for line in lines:
    values = parse_ints(line)
    pos.append(tuple(values[:3]))
    vit.append(tuple(values[3:]))
    
nb = 0
for i,j in itertools.combinations(range(len(pos)), 2):
    x1, y1, _, x2, y2,_ = *pos[i], *pos[j]
    vx1,vy1,_,vx2,vy2,_ = *vit[i], *vit[j]
    # matrice pour résolution   pos1 + t1 * vit1 = pos2 + t2 * vit2
    a,b,c,d = vx1, -vx2, vy1, -vy2
    det = a*d - b*c
    if det == 0:
        continue   # Si parallèle, même si trajectoire confondues et dans le bon sens, on ne compte pas.
    t1  =  d*(x2-x1) + -b*(y2-y1)   # vaut le vrai t1 multiplié par det
    t2  = -c*(x2-x1) +  a*(y2-y1)   # idem
    if det < 0:
        t1, t2, det = -t1, -t2, -det
    if (t1 < 0 or t2 < 0):   # on va dans le futur
        if FICHIER_TEST:
            if t1 < 0:
                print(f"Grêlons {i+1,j+1}: 1er dans le passé")
            if t2 < 0:
                print(f"Grêlons {i+1,j+1}: 2e dans le passé")
        continue
    else:
        assert not (t1 == 0 or t2 == 0), "Grêlons stationnaires ou verticaux non prévus."
    x = x1 * det + vx1 * t1    # x est la valeur de la pos multipliée par det (qui a été absolufié)
    y = y1 * det + vy1 * t1    # idem
    assert not (x==BORD_INF*det or y==BORD_INF*det or x==BORD_SUP*det or y==BORD_SUP*det), "Cas limites non prévus."
    if (BORD_INF*det <= x <= BORD_SUP*det) and (BORD_INF*det <= y <= BORD_SUP*det):
        nb += 1

print("Réponse partie 1:", nb)