• # Un zest de math, pas de modélisation

    Posté par (Mastodon) . En réponse au message Advent of Code 2023, day 6. Évalué à 4. Dernière modification le 06 décembre 2023 à 11:10.

    Ça fait en effet pas mal de possibilités, puisque ma réponse est de plus de 34 millions de façon de gagner.

    En fait, la meilleure course c'est simplement d'appuyer sur le bouton la moitié du temps et de laisser filer l'autre moitié.
    Mais c'est pas ça qu'on demande, on demande juste de calculer les racines d'un polynome du second degré, et de mesurer l'intervalle entre les deux.

    Ok, pour l'exercice 1, on modélise quand même, parce que ça a l'air plus simple que de réfléchir :

    races = list(zip(*[
     [
     int(y.strip())
     for y in x.split(":")[-1].strip().split()
     ] for x in sys.stdin.read().strip().splitlines()
    ][:2]))
    ex1 = reduce(lambda x, y: x * y, (
     sum(
     1
     for i in range(1, time)
     if i * (time - i) > distance
     )
     for time, distance in races
    ))
    print(f"Number of ways to win, score : {ex1}")

    Après, on prend peur, et on se dit que ça va être énorme, les chiffres sont gros, blabla, donc résolution de polynôme, cas limites, soustraction, résultat :

    data = sys.stdin.read().strip().splitlines()
    time, distance = (
     int(x.split(":")[-1].strip().replace(" ", ""))
     for x in data[:2]
    )
    print(f"Big race time {time}, high score : {distance}")
    Δ = math.sqrt(time**2 - 4 * distance) # Ok, this is √Δ and not Δ
    r1 = math.floor((time - Δ) / 2 + 1) # if r is an integer, it's not a winning race, it's a tie
    r2 = math.ceil((time + Δ) / 2 - 1) # so we make sure to handle that edge case.
    # All winning solutions are between r1 and r2, included, hence:
    print(f"Result = {r2 - r1 + 1}")

    Bon, et puis au final on se dit que 35 millions c'est pas si lourd, alors on tente la force brute :

    ex2 = 0
    for i in range(1, time):
     if i * (time - i) > distance:
     ex2 += 1
    print(f"Brute Score : {ex2}")

    Et... des petites comparaisons :
    PyPy3, polynôme : 0,171s
    PyPy3, force brute : 0,268s
    Python3, polynôme : 0,031s
    Python3, force brute : 12,634s

    D'accord, PyPy a un surcoût au démarrage, environ 0.15 secondes, donc la solution efficace en python3 est plus rapide.
    Mais la force brute, bigre, quelle différence, dans les 50 fois plus rapide !

    Et bref, dans tous les cas, on peut y aller comme un bourrin, ou intelligemment, ya rien de difficile dans ces exercices.

    • Yth.