Forum Programmation.autre Avent du Code, jour 2

PostĂ© par (site web personnel) . Licence CC By‐SA.
Étiquettes :
6
2
déc.
2022

Suite de l'Avent du Code, jour 2.

Les lutins et le PÚre Noël jouent à pierre-feuille-ciseaux pour déterminer qui dormira le plus prÚs de la réserve de nourriture. Un lutin nous a donné un genre d'antisÚche pour optimiser notre façon de jouer, et on doit compter les scores que ça donnerait.

  • # En Python bref

    PostĂ© par (site web personnel) . ÉvaluĂ© Ă  4.

    Toujours en Python, mais aujourd'hui, point de modélisation objet, c'est du concis, plus en mode calcul :

    from typing import Iterable, Tuple
    def solve_both(lines: Iterable[str]) -> Tuple[int, int]:
     # Symbol -> value for part 1
     values1 = {'A': 1, 'B': 2, 'C': 3, 'X': 1, 'Y': 2, 'Z': 3}
     # Symbol -> value for part 2
     values2 = {'A': 1, 'B': 2, 'C': 3, 'X': -1, 'Y': 0, 'Z': 1}
     score1 = 0 # for part 1
     score2 = 0 # for part 2
     for line in lines:
     char1, char2 = line.split()
     # Values for part 1
     value1_1, value1_2 = values1[char1], values1[char2]
     outcome1 = ((value1_2 - value1_1 + 1) % 3) * 3
     # Values for part 2
     value2_1, result2 = values2[char1], values2[char2]
     value2_2 = (value2_1 + result2 - 1) % 3 + 1
     outcome2 = ((result2 + 1) % 3) * 3
     # We are player 2!
     score1 += value1_2 + outcome1
     score2 += value2_2 + outcome2
     return score1, score2
    • [^] # Re: En Python bref

      PostĂ© par (Mastodon) . ÉvaluĂ© Ă  3.

      Sur celui-là, j'ai vachement modélisé au contraire :

      class chifumi(int):
       lose = 1
       draw = 2
       win = 3
       def __init__(self, chifumi):
       self.chifumi = chifumi
       self.chifumi = ~self
       def __invert__(self):
       """~chifumi returns value in [1, 2, 3]"""
       return (self.chifumi % 3) or 3
       def __eq__(self, other):
       return ~self == ~other
       def __lt__(self, other):
       return +self == ~other
       def __gt__(self, other):
       return -self == ~other
       def __neg__(self):
       return ((self.chifumi - 1) % 3) or 3
       def __pos__(self):
       return ((self.chifumi + 1) % 3) or 3
       def __mod__(self, other):
       """score of self against other"""
       if self == other:
       return ~self+3
       if self > other:
       return ~self+6
       return ~self
       def __matmul__(self, other):
       """score when result is self, against other"""
       if ~self == self.win:
       return +other+6
       if ~self == self.lose:
       return -other
       return ~other+3

      Et la résolution est triviale derriÚre :

      import sys
      input = [l.split(" ") for l in sys.stdin.read().strip().split("\n")]
      values = dict(
       A=chifumi(1),
       B=chifumi(2),
       C=chifumi(3),
       X=chifumi(1),
       Y=chifumi(2),
       Z=chifumi(3),
      )
      score1 = sum(values[me] % values[you] for you, me in input)
      score2 = sum(values[me] @ values[you] for you, me in input)
      print(f"Strategy 1 = {score1}")
      print(f"Strategy 2 = {score2}")
      • Yth.
      • [^] # Re: En Python bref

        PostĂ© par (site web personnel) . ÉvaluĂ© Ă  3. DerniĂšre modification le 07 dĂ©cembre 2022 Ă  14:52.

        Waouh. C'est pour le moins original ça.

         def __invert__(self):
         """~chifumi returns value in [1, 2, 3]"""
         return (self.chifumi % 3) or 3

        Si je comprends bien, ça fait de ~ une opération pour récupérer la valeur normalisée. Bien joué le (valeur % 3) or 3, c'est bien plus lisible que (valeur - 1) % 3 + 1.

         def __pos__(self):
         return ((self.chifumi + 1) % 3) or 3
         def __neg__(self):
         return ((self.chifumi - 1) % 3) or 3

        La valeur qui me vainc et la valeur que je vaincs, si je ne m'abuse.

         def __lt__(self, other):
         return +self == ~other
         def __gt__(self, other):
         return -self == ~other

        Je suis plus infĂ©rieur Ă  un autre si la valeur qui me vainc est la mĂȘme que la valeur normalisĂ©e de l'autre. Et mutatis mutandis pour la supĂ©rioritĂ©. Tu aurais pu utiliser functool.total_ordering().

        Ensuite, le reste est assez simple Ă  comprendre, une fois ces bases posĂ©es. La rĂ©utilisation des opĂ©rateurs est... intĂ©ressante. Je ne peux pas dire que je suis fan, c'est un peu bizarre Ă  lire quand mĂȘme.

        values = dict(
         A=chifumi(1),
         B=chifumi(2),
         C=chifumi(3),
         X=chifumi(1),
         Y=chifumi(2),
         Z=chifumi(3),
        )

        Tiens, j'ignorais la possibilité d'instancier un dictionnaire avec des mots-clefs. C'est amusant, ça aussi.

        • [^] # Re: En Python bref

          PostĂ© par (site web personnel, Mastodon) . ÉvaluĂ© Ă  1.

          Bien joué le (valeur % 3) or 3, c'est bien plus lisible que (valeur - 1) % 3 + 1.

          C'est Ă©trange ; c'est l'inverse pour moi ...qui ne pense pas assez en Phyton (et ai pratiquement beaucoup de langages oĂč on retrouve la derniĂšre forme)

          La rĂ©utilisation des opĂ©rateurs est... intĂ©ressante. Je ne peux pas dire que je suis fan, c'est un peu bizarre Ă  lire quand mĂȘme.

          On dirait que c'est Ă©crit par quelqu'un qui pratique/rĂ©flĂ©chi le/en OCaml ou peut-ĂȘtre Lisp ou Scheme...

          "It is seldom that liberty of any kind is lost all at once." ― David Hume

          • [^] # Re: En Python bref

            PostĂ© par (Mastodon) . ÉvaluĂ© Ă  3.

            J'ai fait du Caml, j'ai jouĂ© un peu avec OCaml, et mĂȘme un poil de Lisp Jadis, mais je ne code pas rĂ©guliĂšrement dans ces langages lĂ .

            Réutiliser les opérateurs, c'est bien pour jouer, mais ça peut péter complÚtement la lisibilité, donc il faut faire trÚs trÚs attention quand on veut partager le code...

            Bien fait c'est génial par contre.

            • Yth.
        • [^] # Re: En Python bref

          PostĂ© par (Mastodon) . ÉvaluĂ© Ă  3.

          J'aime bien réutiliser les opérateurs, mais j'ai fait ça assez rapidement, donc la pertinence est celle d'un truc pondu en vingt minutes.
          Le ~chifumi est pratique et plutÎt lisible, comme ça on normalise tout le temps.

          Par contre réutiliser la classe chifumi pour qu'elle représente une choix ou un résultat d'affrontement, c'est plutÎt moche, ça rendrait illisible un code plus gros, et c'est totalement lié à la présentation de la seconde partie du problÚme aprÚs la résolution de la premiÚre : comment bricoler vite fait du code qui répond à la question. C'était plus simple de rajouter un opérateur à une classe existante que de gérer une nouvelle classe.

          Mais en plus propre on pourrait avoir une classe resultat d'affrontement, qui sait se multiplier (par exemple) avec une classe chifumi, avec __mul__ et __rmul__, pour pouvoir faire chifumi * resultat = resultat * chifumi = "mais qu'a donc joué mon adversaire ?"
          On apprends Ă  resultat Ă  se multiplier dans les deux sens avec chifumi sans que celle-ci sache comment se multiplier avec resultat.

          On pourrait garder le mĂȘme opĂ©rateur partout, et faire du __mod__ et __rmod__ sur resultat. Sachant que dans tous les cas on retourne un score qui est un entier et n'a rien Ă  voir avec aucune des deux classes.

          Pour le total_ordering, c'est vrai, mais en pratique j'ai implémenté __lt__ qui n'est jamais utilisé. J'aurais pu nettoyer ça du code avant de le poster.

          • Yth.
  • # if vs modulo

    PostĂ© par . ÉvaluĂ© Ă  3.

    J'avoue que je suis passé à cÎté de la subtilité du modulo et que j'ai bouriné en énumérant les cas possible (nimage).

    • [^] # Re: if vs modulo

      PostĂ© par (site web personnel, Mastodon) . ÉvaluĂ© Ă  1. DerniĂšre modification le 08 dĂ©cembre 2022 Ă  11:04.

      Y a que neuf cas équitablement répartis, donc on peut se permettre d'énumérer au lieu de sortir l'artillerie lourde àmha.

      "It is seldom that liberty of any kind is lost all at once." ― David Hume

  • # petit bout de AWK

    PostĂ© par . ÉvaluĂ© Ă  5.

    #loose
    $0=="A Z"{S+=3}
    $0=="B X"{S+=1}
    $0=="C Y"{S+=2}
    #draw
    $0=="A X"{S+=3+1}
    $0=="B Y"{S+=3+2}
    $0=="C Z"{S+=3+3}
    #win
    $0=="A Y"{S+=6+2}
    $0=="B Z"{S+=6+3}
    $0=="C X"{S+=6+1}
    END{print S}
  • # en shell bref

    PostĂ© par (site web personnel, Mastodon) . ÉvaluĂ© Ă  1.

    Juste pour la premiĂšre partie

    #!/bin/sh
    # 1ăƒ‰ăƒ«: input file
    if test -z "1ăƒ‰ăƒ«"
    then
     echo "Please call me with an input file..." >&2
     exit 1
    fi
    _if="1ăƒ‰ăƒ«"
    if ! command -v grep >/dev/null
    then
     echo "Cannot locate 'grep' command in $PATH" >&2
     exit 2
    fi
    _ts=0 # total score
    _nr=0 # number of round
    # loose
    _nr=$( grep -cE '^ *B +X *$' "$_if" ) _ts=$(( _ts + 1*_nr ))
    _nr=$( grep -cE '^ *C +Y *$' "$_if" ) _ts=$(( _ts + 2*_nr ))
    _nr=$( grep -cE '^ *A +Z *$' "$_if" ) _ts=$(( _ts + 3*_nr ))
    # draw
    _nr=$( grep -cE '^ *A +X *$' "$_if" ) _ts=$(( _ts + 4*_nr ))
    _nr=$( grep -cE '^ *B +Y *$' "$_if" ) _ts=$(( _ts + 5*_nr ))
    _nr=$( grep -cE '^ *C +Z *$' "$_if" ) _ts=$(( _ts + 6*_nr ))
    # win
    _nr=$( grep -cE '^ *C +X *$' "$_if" ) _ts=$(( _ts + 7*_nr ))
    _nr=$( grep -cE '^ *A +Y *$' "$_if" ) _ts=$(( _ts + 8*_nr ))
    _nr=$( grep -cE '^ *B +Z *$' "$_if" ) _ts=$(( _ts + 9*_nr ))
    # end
    echo "$_ts"

    C'est une bĂȘte Ă©numĂ©ration exhaustive des cas, un peu comme la solution en AWK, mais en Ă©tant un peu plus lĂąche sur le formatage du fichier.

    "It is seldom that liberty of any kind is lost all at once." ― David Hume

    • [^] # Re: en shell bref

      PostĂ© par (site web personnel, Mastodon) . ÉvaluĂ© Ă  1.

      Juste pour la seconde partie

      #!/bin/sh
      # 1ăƒ‰ăƒ«: input file
      if test -z "1ăƒ‰ăƒ«"
      then
       echo "Please call me with an input file..." >&2
       exit 1
      fi
      _if="1ăƒ‰ăƒ«"
      if ! command -v grep >/dev/null
      then
       echo "Cannot locate 'grep' command in $PATH" >&2
       exit 2
      fi
      _ts=0 # total score
      _nr=0 # number of round
      # +0=loose
      _nr=$( grep -cE '^ *A +X *$' "$_if" ) _ts=$(( _ts + 3*_nr )) # AC RS
      _nr=$( grep -cE '^ *B +X *$' "$_if" ) _ts=$(( _ts + 1*_nr )) # BA PR
      _nr=$( grep -cE '^ *C +X *$' "$_if" ) _ts=$(( _ts + 2*_nr )) # CB SP
      # +3=draw
      _nr=$( grep -cE '^ *A +Y *$' "$_if" ) _ts=$(( _ts + 4*_nr )) # AA
      _nr=$( grep -cE '^ *B +Y *$' "$_if" ) _ts=$(( _ts + 5*_nr )) # BB
      _nr=$( grep -cE '^ *C +Y *$' "$_if" ) _ts=$(( _ts + 6*_nr )) # CC
      # +6=win
      _nr=$( grep -cE '^ *A +Z *$' "$_if" ) _ts=$(( _ts + 8*_nr )) # AB RP
      _nr=$( grep -cE '^ *B +Z *$' "$_if" ) _ts=$(( _ts + 9*_nr )) # BC PS
      _nr=$( grep -cE '^ *C +Z *$' "$_if" ) _ts=$(( _ts + 7*_nr )) # CA SR
      # end
      echo "$_ts"

      MĂȘme principe, juste qu'on calcule autrement.

      "It is seldom that liberty of any kind is lost all at once." ― David Hume

Suivre le flux des commentaires

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