Forum Programmation.autre Advent of Code 2023 : Day 1

Posté par  . Licence CC By‑SA.
Étiquettes :
2
3
déc.
2023

Le premier d'une série de 25 forums qui proposeront de partager vos solutions pour l'édition 2023 de l'Advent of Code.

Vous pouvez vous inscrire à un leadboard privé que j'ai créé pour LinuxFR : 2423220-c94050af

Jour 1 (résumé) :

Partie 1

Les petits lutins vont vous envoyer voir où la production de neige a des problèmes, et utilisent pour cela un trébuchet.

Pour cela, ils ont besoin des valeurs de calibrations écrites dans un document qui a été « amélioré » par un jeune lutin.

Image

Le document se présente ainsi :

1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet

Pour obtenir les valeurs de calibration, il suffit de combiner le premier et le dernier chiffre de chaque ligne pour obtenir un nombre à deux chiffres. Les valeurs qui correspondent à cet exemple sont 12,38,15,77. La solution est la somme de ses chiffres, soit 142.

Partie 2

C'était trop simple, en fait les chiffres écrits en lettre comptent aussi.
Par exemple :

two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen

Donne les valeurs 29,83,13,24,42,14,76, pour une somme de 281.

Image

  • # Premier jour : on n'optimise pas, on fonce dans l'tas !

    Posté par  (Mastodon) . Évalué à 2.

    Le premier exercice est trivial :

    import sys
    print(sum(
        int(f"{digit[0]}{digit[-1]}")
        for line in sys.stdin
        for digit in [[x for x in line if x in "0123456789"]]
        if digit
    )

    On fait python3 01.py < 01.input ou 01.demo pour les données de test, et hop, résultat en une commande.

    Le second exercice sans optimisation consiste à rechercher les chiffres et les chiffres écrits, ajouter ça dans une liste, et faire pareil :

    import sys
    text = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
    def analyze(line):
        def _iter():
            for n in range(len(line)):
                if line[n] in "0123456789":
                    yield line[n]
                    continue
                for t in text:
                    if line[n:].startswith(t):
                        yield str(text.index(t))
                        continue
        return _iter()
    
    print(sum(
        int(f"{digit[0]}{digit[-1]}")
        for line in sys.stdin
        for digit in [list(analyze(line))]
        if digit
    )

    La fonction analyze prend une ligne, la parcours charactère par charactère, et regarde si c'est un chiffre, ou l'écriture d'un chiffre, et envoie dans l'itérateur.
    Zéro intelligence, zéro optimisation, zéro plantage.
    Bientôt on pourra plus faire comme ça !
    Mais bon, jour 1, on se dérouille les neurones, on reprend le pli des traitements de flux, on essaie déjà de mettre des itérateurs plutôt que de tout traiter en mémoire, juste pour reprendre les futurs bonnes habitudes…

    • Yth.
  • # Python

    Posté par  . Évalué à 1.

    Ma solution :

    #!/bin/python3
    
    replaces = {
        "one":1,
        "two":2,
        "three":3,
        "four":4,
        "five":5,
        "six":6,
        "seven":7,
        "eight":8,
        "nine":9,
    }
    
    def extract(word):
    
        fd = 0
        ld = 0
    
        for l in word:
            n = 0
            if l.isdigit():
                n = int(l)
            if n != 0:
                if fd == 0:
                    fd = n
                ld = n
        return fd*10+ld
    
    def digitalize(word):
    
        fd = 0
        ld = 0
    
        for i in range(len(word)):
            n = 0
            if word[i].isdigit():
                n = int(word[i])
            else:
                for k in replaces.keys():
                    if word[i:].replace(k,str(replaces[k]))[0].isdigit():
                        n = replaces[k]
                        break
            if n != 0:
                if fd == 0:
                    fd = n
                ld = n
        return fd*10+ld
    
    def solve1(testinput,testing=False):
        s = 0
        for line in testinput:
            d = extract(line)
            if testing:
                print(line, "=", d)
            s += d
        if testing:
            print(s)
        return s
    
    def solve2(testinput,testing=False):
        s = 0
        for line in testinput:
            d = digitalize(line)
            if testing:
                print(line, "=", d)
            s += d
        if testing:
            print(s)
        return s
    
    test1 = """1abc2
    pqr3stu8vwx
    a1b2c3d4e5f
    treb7uchetn"""
    result1 = 142
    
    test2 = """two1nine
    eightwothree
    abcone2threexyz
    xtwone3four
    4nineeightseven2
    zoneight234
    7pqrstsixtee"""
    result2 = 281
    
    def solve(short=False):
    
        print("----Part 1----")
        if short == False:
            if solve1(test1.split("\n"),testing=True) != result1:
                print("Not working.")
                return False
            else :
                print("Maybe working?")
        with open("input.txt",'r') as file:
            lines = file.read().split("\n")
            s1 = solve1(lines)
            print(s1)
    
        print("----Part 2----")
        if short == False:
            if solve2(test2.split("\n"),testing=True) != result2:
                print("Not working.")
                return False
            else :
                print("Maybe working?")
        with open("input.txt",'r') as file:
            lines = file.read().split("\n")
            s2 = solve2(lines)
            print(s2)
    
        return s1, s2
    
    if __name__ == "__main__":
    
        from sys import argv
    
        try:
            if argv[1] == "--summary" or argv[1] == "-s":
                solve(short=True)
        except IndexError:
            solve()

    Après quelques essais en remplaçant avant de traiter, je me suis rendu compte que le plus simple était de reprendre intégralement la logique de la partie 1 en vérifiant une chaine plutôt qu'un nombre.

    Et c'est plutôt propre.

    L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès

    • [^] # Re: Python

      Posté par  (site web personnel) . Évalué à 4.

      Et pour 0 et zéro ? (Nb : je n'ai pas essayé de faire l'exercice, je regardais juste les 2 réponses fournies ici et leurs différences)

      • [^] # Re: Python

        Posté par  (Mastodon) . Évalué à 2.

        "zero" n'est pas dans les données, mais l'ajouter chez moi permet d'avoir la correspondance entre les textes et les index de la liste Python qui commence à 0.

        C'est une optimisation facile de lisibilité on va dire.

        Par ailleurs, j'ai codé sans regarder les données justement, donc en fait je ne savais pas que le zéro était inutilisé.
        Dans l'idée, il aurait pu l'être.

        • Yth.
      • [^] # Re: Python

        Posté par  . Évalué à 2.

        J'ai vérifié avant et avait fais quelques tests dans la première partie, il n'y a pas de zéro. Et si c'était le cas, il suffirait d'ajouter une ligne au dictionnaire.

        L'informatique n'est pas une science exacte, on n'est jamais à l'abri d'un succès

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.