Yth a écrit 2671 commentaires

  • [^] # Re: J'un souci avec l'orthographe.

    Posté par  (Mastodon) . En réponse au journal Un souci…. Évalué à 4.

    On a des textes de philosophes grecs qui déjà se plaignaient de la jeunesse qui part à vau l'eau, que c'est plus c'que c'était, on va droit dans le mur, etc.

    Depuis que l'être humain vieilli, il oublie qu'il a été jeune, et se plaint que les nouveaux jeunes font exactement la même chose qu'eux avant, voire pire : font des choses qu'ils regrettent de n'avoir pas fait eux-même !

    • Yth.
  • [^] # Re: J'un souci avec l'orthographe.

    Posté par  (Mastodon) . En réponse au journal Un souci…. Évalué à 6.

    En fait tout dépend des fautes, de leur quantité, et de l'altération du sens qu'elles peuvent provoquer.

    En français, on s'y retrouve assez bien, entre le contexte et la grande variété des mots, tomber via une faute sur un truc qui fait contre-sens n'est pas si commun.

    Mais quand ça arrive, on peut simplement ne pas savoir ce que la personne voulait dire.

    Et quand les fautes sont « graves » ça rend la lecture bien plus difficile, parce qu'en lecture on reconnaît un mot via sa graphie, mais si on est obligé de vocaliser une phrase pour la comprendre, ça rend les choses bien plus difficile.
    À l'extrême tu as le créole, si tu le prononces tu vas souvent comprendre le sens, mais le lire directement, sans le connaître et sans le vocaliser, c'est mort, tu piges rien.

    Et il y a tout un monde entre les deux !
    Et beaucoup de fautes, en effet, ne gênent pas.
    Mais un texte écrit phonétiquement - quand c'est pas pour faire le guignol avec des commentaires légers - et si l'auteur veut faire passer un vrai message, ben il ne va pas y arriver, pas comme ça…

    Je pense faire partie de ces gens qui sont assez carrés, font peu, mais pas pas, de fautes, et corrigent, parfois, autrui.
    Mais je corrige quand ça a de l'importance pour la compréhension, ou de temps en temps sur une faute courante qui m'irrite (mais je suis moins irritable avec la sagesse, qui, elle, a attendu le nombre des années, d'ailleurs, je la vois toujours pas venir à l'horizon hein, du pipeau tout ça j'vous dis).

    Et surtout, il ne faut pas se formaliser quand quelqu'un corrige ton texte, au contraire, ça peut te faire retenir un truc, ça peut aider d'autres personnes, ça peut permettre à un modo de corriger après coup, tout ça est positif, et n'est jamais une attaque personnelle. Ou ne devrait jamais l'être en tout cas…

    • Yth.
  • [^] # Re: Format mort-né ?

    Posté par  (Mastodon) . En réponse au lien Le format d'image APNG. Évalué à 3.

    En plus, côté support, c'est assez général avec un fallback immédiat partout : une animation APNG est un fichier image PNG valide, sur la première image de l'animation.

    Donc là-aussi, c'est un truc à fignoler, un truc d'artisan, pour caler ton bidule au poil, mais en situation d'incompatibilité, au lieu d'avoir un rectangle vide, où un message d'erreur, (crédibles avec AV1 ou webp, là où APNG n'est pas géré), ben tu as une image classique et parfaitement gérée.
    GIF fait ça aussi, j'ai souvent vu des lecteurs d'images n'afficher que la première image d'un GIF animé, sans animation, mais pour le coup c'est plutôt lourd, puisque tout est chargé malgré tout, c'est pas du streaming.

    • Yth.
  • [^] # Re: Format mort-né ?

    Posté par  (Mastodon) . En réponse au lien Le format d'image APNG. Évalué à 10.

    C'est pas du vectoriel, donc ça ne s'utilise pas dans les mêmes conditions que du SVG, je veux bien envisager de comparer flash et SVG, mais APNG ? Nope….

    C'est du PNG donc sans pertes, contrairement à AV1 qui est un format vidéo classique avec pertes.
    Il y a ce qu'on peut trouver comme avantages et inconvénients du PNG comparé au JPG/WebP ou au GIF, un peu au milieu, mieux sur certains points, moins bien sur d'autres, et terriblement efficace quand utilisé correctement.

    Par ailleurs, l'APNG, comme le PNG utilise un vrai canal alpha.
    Là aussi, les comparaisons avec l'existant sont un peu les mêmes : en GIF on a une transparence binaire, en JPG on n'a rien, en WebP on a le canal alpha aussi.
    Je ne suis pas assez calé dans les formats plus récents, mais je ne suis pas très sûr que l'AV1 par exemple ait cette faculté, ça ne correspond pas à sa cible.

    WebP a les mêmes fonctionnalités, mais là aussi, selon le type d'image, un PNG, ou APNG selon le cas, utilisé correctement va faire mieux : plus joli, plus léger.
    Tandis que mal utilisé c'est très gros, très lourd, et à éviter absolument !

    Tout comme le PNG, l'APNG c'est un peu un format de connaisseurs, et de niche, mais qu'est-ce que c'est bien !

    • Yth.
  • [^] # Re: 23 ème minute et propriété privé

    Posté par  (Mastodon) . En réponse au lien Gael Giraud - "Composer un monde en commun". Évalué à 3.

    C'est pareil pour l'expropriation par exemple ?

    Ben… oui…
    La seule question qui se pose c'est celle des effets de l'expropriation sur l'exproprié.
    C'est d'ailleurs pour ça qu'il y a compensation financière et délai généralement assez long, pour vider les lieux.

    Tout ce dont on parle ne signifie pas qu'on ne peut jamais rien faire aux autres, même contre leur gré, mais qu'il y a une frontière à définir, souvent claire, généralement légalement définie, parfois très obscure et complexe…

    Mais c'est pareil, c'est bien une question de ce que ça fait à l'exproprié. Si ça ne lui faisait rien, la question ne se poserait pas.
    Il n'est pas en soi question du droit à l'expropriation, mais du droit du futur exproprié à ne pas l'être, et en pratique - la puissance publique étant ce qu'elle est - surtout du droit de l'exproprié à l'être dans de bonnes conditions.

    Et la nappe phréatique se retrouve être ta cible indirecte, et ça joue. Si tu fais exploser une bombe dans une poubelle du métro, tu n'as visé aucune des victimes spécifiquement (probablement pas en tout cas), mais l'argument de « mais je visais uniquement la poubelle » ne tiendra pas !
    Alors, si tu ne savais pas, pour la pollution des sols, tu ne vas pas être puni, mais tu vas devoir cesser tout de même (ou tu devrais dans un monde logique). Et aujourd'hui, en 2023, tu ne peux plus sincèrement prétendre ne pas savoir.
    La nappe phréatique est donc bien une de tes cibles, et en plus tu le sais pertinemment, et même si ton arrière-grand-père faisait exactement pareil, lui ne savait pas (forcément) !

    Mais ton agriculteur sera condamné (peut-être) parce qu'une loi indique que sa liberté à lui s'arrête là où il pollue la nappe phréatique de tout le monde, empêchant de fait tes voisins de profiter d'une nappe phréatique non polluée. Tes voisins sont la cible - involontaire - de tes actions. Des animaux et des plantes aussi, qui ont des droits.
    C'est pareil pour la rivière avec les rejets industriels, ou l'océan pour le super-tanker (ah non, lui ranapéter, il est en eaux internationale, osef).
    Encore une fois, si polluer une nappe phréatique n'avait aucun impact sur qui ou quoi que ce soit, personne ne te dirait de ne pas le faire ! Le problème est toujours l'impact de tes actions sur autrui, pas une réglementation pour le plaisir d'une réglementation.

    • Yth.
  • [^] # Re: 23 ème minute et propriété privé

    Posté par  (Mastodon) . En réponse au lien Gael Giraud - "Composer un monde en commun". Évalué à 2.

    Si on veut être pointilleux, tu as parfaitement le droit de faire le mouvement avec le couteau, mais tu n'as pas le droit, d'une quelconque manière que ce soit, de blesser ou tuer quelqu'un.

    Là tu veux « faire quelque chose » avec « une chose » sur « une autre chose ».

    Si l'autre chose est ton ours en peluche, ya pas de soucis, le plantage au couteau, parfaitement légal.
    Mais si l'autre chose ne t'appartient pas, et ta femme ne t'appartient pas, c'est un tout autre problème.
    Pour un animal c'est encore différent.
    Il y a des subtilités dans la réglementation, par exemple une poule d'élevage t'appartient et tu peux la planter, et la manger. Pas sûr que ça soit vrai pour ton chat ou ton chien, dont tu n'as peut-être « que » la responsabilité.

    Bref, le fait que le couteau t'appartienne ou pas, et la nature du mouvement envisagé, n'entre à peu près jamais en ligne de compte.
    Ce qui compte c'est bien la « cible » de l'action, et les effets sur cette cible.

    Remplace « planter avec un couteau » par « remarque salace avec ta bouche et tes cordes vocales », c'est pareil.
    Les effets étant sans commune mesure, la qualification l'est aussi, et d'un crime on passe à un délit (selon la remarque, n'entrons pas dans les détails, mais ça peut être du harcèlement sexuel), ça n'en est pas moins interdit, alors qu'il est difficile d'imaginer que tu n'aies pas le droit de parler…

    • Yth, la liberté des uns s'arrête là où commence celle des autres, et ton ours en peluche n'a aucunes libertés, désolé pour lui.
  • [^] # Re: Les défauts de backmarket...

    Posté par  (Mastodon) . En réponse au message Cherche modèle de téléphone. Évalué à 2.

    Ceux qui ont un Pixel 3 savent à quel point ton affirmation est à prendre avec des pincettes, même si elle est probablement généralement assez juste.

    Et ce n'est pas lié à une mauvaise position.

    • Yth.
  • # Les défauts de backmarket...

    Posté par  (Mastodon) . En réponse au message Cherche modèle de téléphone. Évalué à 3. Dernière modification le 06 janvier 2023 à 16:15.

    Pour du reconditionné, et à tarif raisonnable, backmarket fait du très bon travail.
    Par contre trouver un smartphone compatible LineageOS c'est super casse-pied, il faut sans cesse passer de la liste des smartphone gérés par LineageOS à la liste des trucs dispos sur backmarket, filtrer par constructeur, parfois rechercher les modèles un par un.
    Quant-à savoir s'ils ont la batterie accessible, il faut aller chercher encore plus loin les specs techniques du téléphone que tu vises.

    Bref, même si mes deux derniers téléphones (le premier a souffert du syndrôme de l'écrasement entre une pierre et un coureur en plein vol plané) ont été achetés là-bas, en général je passe quasiment une semaine à chercher, trier, y revenir plus tard, faire mon choix et me retrouver avec un téléphone sans prise jack et une qualité audio à chier (bonjour pixel 3 XL, ça serait bien que t'aies l'option téléphone tu sais ?).

    Si quelqu'un connaît un meilleur site de vente d'occase, je suis preneur !

    • Yth.

    PS : on peut noter que backmarket fournit toujours un casque audio classique (filaire, jack) avec ses téléphones, même s'ils n'ont pas de prise jack, c'est en standard.

  • [^] # Re: Ça va être compliqué...

    Posté par  (Mastodon) . En réponse au message Cherche modèle de téléphone. Évalué à 3.

    KaiOS c'est FirefoxOS, donc plutôt bien côté liberté, apparemment en GPL, yabon.

    Par contre, c'est chaud de trouver un de ces téléphones en France, le marché n'est pas (encore ?) ici…
    Le marché des téléphones proposés est surtout l'Afrique, le Moyen-Orient, l'Amérique centrale ou du sud.
    Difficile même d'être certain qu'ils vont bien se connecter sur des opérateurs en France, les normes ne sont pas les mêmes partout.

    Côtés applis, faudrait se passer de f-droid, évidemment, et dans le catalogue il n'y a pas de client IMAP (mais une appli système pour le mail), XMPP ou fediverse.
    Ça force à utiliser des versions web de tout ça, mais bon, pour un OS basé sur firefox, où les applis natives sont des webapps, ça se tient quelque part.

    Mais ça permet sans soucis de faire point d'accès wifi vers la 4G, et j'espère que le téléphone fonctionne correctement (contrairement à certains smartphones dont le mien… Si j'ai pas de casque, communiquer est un calvaire, pour moi et mon correspondant, un peu con quand même ?).

    Merci pour l'information, ça mérite de garder un œil là-dessus !

    • Yth.
  • [^] # Re: Ça va être compliqué...

    Posté par  (Mastodon) . En réponse au message Cherche modèle de téléphone. Évalué à 5.

    Ça commence à exister les smartphones à l'ancienne.
    Un truc à clapet, clavier T9, mais android, donc possibilité d'avoir un jabber, des mails, et surtout de partager sa connexion data en wifi !

    Bon, aucun ne semble se vendre vraiment en europe, et aucun ne permet d'installer lineageOS.

    Sonim xp3 plus
    Samsung Galaxy Folder 2
    Cat S22 Flip

    Franchement, pour remplacer un gros machin avec une grosse vitre, avoir un vrai clavier de téléphone portable avec lesquels on écrivait jadis des SMS bien plus rapidement qu'avec le tactile pourrave moderne, tout en ayant quand même le minimum, ça me fait un rien rêver…

    À quand un FairClapet sous LineageOS ou /e/ ?

    • Yth.
  • [^] # Re: Erreur dans le titre du lien à corriger

    Posté par  (Mastodon) . En réponse au lien L'assureur MAIF consacre 10% de ses bénéfices à la planète. Évalué à 6.

    La comm MAIF indique, je cite :

    Nous avons décidé d'allouer désormais 10% de notre résultat annuel à la planète.
    En 2022, cela représentera près de 10 millions d'euros.

    Et oui, le CA c'est pas super crédible :)

    • Yth.
  • # sqldiff

    Posté par  (Mastodon) . En réponse au message diff DDL (SQL). Évalué à 6. Dernière modification le 05 janvier 2023 à 08:35.

    Avec une base SQLite tu as l'outil sqldiff.

    Usage: sqldiff [options] DB1 DB2
    Output SQL text that would transform DB1 into DB2.
    […]
    --schema Show only differences in the schema

    • Yth.
  • [^] # Re: La part réelle du nucléaire dans le bouquin

    Posté par  (Mastodon) . En réponse au lien Erratum pour «Le monde sans fin» : Dargaud piégé par des activistes. Évalué à 9.

    Quels seraient, selon toi, les acteurs puissants dans le secteur énergétique en France ?

    Total.

    À mon avis largement plus puissant que la nébuleuse EDF.

    • Yth.
  • [^] # Re: J'ai galéré :)

    Posté par  (Mastodon) . En réponse au message Avent du code jour 25. Évalué à 2.

    Bah bravo à tous les deux d'être allés au bout !
    Heureusement que les derniers jours étaient plus faciles, parce que bon, j'ai vraiment aimé le challenge dans son ensemble, mais beaucoup moins le jour de Noël :p

    Merci aussi à tous les gens ici qui ont participé, en particulier Tanguy qui a bien animé la chose, c'était fun de partager et discuter :)

    Bonne année !

    • Yth.
  • [^] # Re: J'ai galéré :)

    Posté par  (Mastodon) . En réponse au message Avent du code jour 25. Évalué à 3.

    Réponse en voiture (mais pas au volant !).
    On est en base 5, donc l'algo de base c'est un divmod : division entière pour l'itération suivante, reste de la division pour le chiffre courant.

    Ici le chiffre va de -2 à 2, donc on prend le reste, donc x%5, qu'on ramène sur -2/2, par exemple r=(x+2)%5-2, on a notre chiffre dans "=-012".
    Là tu retires ton reste, donc x-=r, ton nouvel x est divisible par 5, ru divises et tu itères.

    Plus simple mais j'ai pas testé :
    x, r = divmod(x+2, 5)
    r -= 2
    Et là ton r est le bon entre -2 et 2, ton x est le suivant dans l'itération.

    • Yth.
  • [^] # Re: Belle modélisation, rapide, efficace.

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 24. Évalué à 3.

    Le PPCM ça me permet juste d'avoir une modélisation complète directement, et plus un calcul après.
    Je t'assure qu'avec mon bug initial où on n'allait jamais vers le haut, on fait défiler les rounds, le temps de relire le code, c'est plus de 100 000 qui sont passés à tourner en rond sur un cycle de 600, logique 😅

    Bref, ça permet un plantage très performant !

    • Yth.
  • [^] # Re: vizu

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 12. Évalué à 2.

    J'aime beaucoup :)
    Bravo !

    • Yth.
  • # Belle modélisation, rapide, efficace.

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 24. Évalué à 4.

    Je suis fier de moi !
    Bon, j'ai pu démarrer très tard aujourd'hui, mais j'ai été efficace et j'ai fait du joli code, court et propre.
    Une bête erreur de préparation a flingué ma perfection, pour le calcule des 4 directions de mouvements, j'avais fait droite, gauche, bas, gauche… Et les données de test passent : ya jamais besoin d'aller en haut pour trouver la bonne solution, rhaaa !

    Bref, j'ai relu, j'ai trouvé, et j'ai passé à peine quelques minutes entre le 1 et le 2, le temps de mettre le code d'itération dans une fonction avec une position de départ et une d'arrivée, et de l'appeler trois fois d'affilé.

    Exécution en 1,5 secondes.
    Utilisation extensives des set(), union, intersection.
    J'ai aussi eu une flemme terrifiante de calculer un PPCM, alors il est mochement en dur dans le code, comme quoi tout n'est pas si beau ^

    from collections import deque
    
    class Position(tuple):
        def __add__(self, other):
            return Position((self[0] + other[0], self[1] + other[1]))
        def __contains__(self, other):
            return (
                0 <= other[0] < self[0] and
                0 <= other[1] < self[1])
        def moves(self, dimensions):
            return (
                _
                for _ in (self + (1, 0), self + (-1, 0), self + (0, 1), self + (0, -1))
                if _ in dimensions
            )
    
    def whirlwind(x, y, d, w, h, n):
        if d == ">":
            return [(_ % w, y) for _ in range(x, x + n)]
        if d == "<":
            return [(_ % w, y) for _ in range(x, x - n, -1)]
        if d == "^":
            return [(x, _ % h) for _ in range(y, y - n, -1)]
        if d == "v":
            return [(x, _ % h) for _ in range(y, y + n)]
    
    
    data = sys.stdin.read().strip().splitlines()
    dimensions = Position((len(data[0]) - 2, len(data) - 2))  # should be 120, 25
    ppcm = 12 if dimensions[0] == 6 else 600  # complete whirlwind board cycle length
    start = Position((data[0].index(".") - 1, -1))  # Should be (0, -1)
    startpos = start + (0, 1)  # Should be (0, 0)
    end = Position((data[-1].index(".") - 1, dimensions[1]))  # should be (6, 3) or (120, 24)
    # ending on the tile before the end, north of it, last move being unique, and unstoppable
    endpos = end + (0, -1)  # Should be (5, 3) or (119, 24)
    board = deque((set(_) for _ in zip(*[
        whirlwind(x - 1, y - 1, c, dimensions[0], dimensions[1], ppcm)
        for y, line in enumerate(data)
        for x, c in enumerate(line)
        if c in "<>^v"
    ])), ppcm)
    
    
    def reach(start, end, board, dimensions):
        positions = {start}
        i = 0
        while end not in positions:
            positions = positions.union(
                p
                for _ in positions
                for p in _.moves(dimensions)
            ).difference(board[0])
            board.rotate(-1)
            i += 1
        return i
    
    
    r1 = reach(start, endpos, board, dimensions)
    r2 = reach(end, startpos, board, dimensions)
    r3 = reach(start, endpos, board, dimensions)
    print(f"Reaching destination in {r1} rounds")
    print(f"Returning to start in {r2} rounds")
    print(f"Reaching destination again in {r3} rounds")
    print(f"Total of {r1+r2+r3=} rounds")

    L'état du terrain avec ses tornades est cycliques en PPCM(largeur, hauteur), donc je calcule tous les états possibles au début et je me balade après en faisant tourner le deque.
    L'initialisation est presque plus longue que la solution…

    • Yth.
  • [^] # Re: Question naïve aux lutins du Père Noël qui font l'Avent du code

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 21. Évalué à 3.

    Et pis j'vais mieux répondre, genre moins à côté de la plaque :)

    Les seules stats réelles sont pour chacun combien de temps s'est écoulé entre la publication de l'exercice (6h du matin heure de Chaville), et l'heure où on a soumit une réponse valable, et numéro combien on est arrivé pour donner cette solution.
    Ce qui a le sens qu'on veut bien lui donner, par exemple mon premier jour c'est ça :

    Jour 1, exercice 1 : 16:57:57, 111022ème, exercice 2 : 16:59:28, 105671ème.

    On voit surtout la minute et trente secondes entre les deux exercices, mais les quasi 17h avant la première réponse, bah, c'est un peu le temps que je me rappelle qu'il y avait ce truc qui allait me bouffer un temps de dingue durant 25 jours !!

    À côté on a ça :

    Jour 19, ex1 : 05:18:28, 2937è, ex2 : 05:28:27, 2267è

    5h c'est largement plus que ma moyenne, mais 2267è à finir l'exo2 c'est largement mieux que ma moyenne, donc j'ai été performant sur un exo difficile.

    En comparaison hier, j'ai pataugé sur l'exercice 2 :

    Jour 22, ex1 : 03:17:54, 4372è, exo2 : 10:36:01, 3791è

    Autant dire que ça sert assez peu ces stats.
    Par contre il y a les stats générales ici :
    https://adventofcode.com/2022/stats
    On y voit que le nombre de participants diminue beaucoup au fil du temps.
    Et par exemple l'exercice du 22 a été fatal à plein de gens sur l'exercice 2 : c'est la plus grosse proportion de gens n'ayant fait que l'exercice 1 et abandonné le 2 !

    D'ailleurs, ici, ceux qui ont validé le deux on fait ce qu'on appelle tricher pour y arriver.

    Tricher c'est faire un code qui va fonctionner avec notre propre jeu de donnée, mais pas forcément avec celles du voisin. En l'occurrence avec une analyse statique et plastique des données (papier, ciseau, colle), pour rajouter des informations et permettre à notre code de sortir le résultat sans complètement « comprendre » le problème.

    C'est le seul exercice où j'ai « triché », mais il y en a eu au moins un autre où j'ai un peu triché pour sortir le résultat avant de trouver comment être complètement générique, cf discussion sur le Jour du Tetris, le 17, et la tour à mille milliards de blocs.
    Ma dernière version du programme peut te donner la réponse pour n'importe quel nombre de bloc, quelles que soient les données en entrée. Avec les miennes il suffit de calculer 5170 blocs, et quatre opérations (une soustraction, un modulo, une multiplication, et une addition), je te dis quelle est la taille de la tour pour X blocs.
    Là c'est beau et pas triché :)

    Après les discussions ici ont eu l'intérêt de donner des idées de programmation en général :

    • l'utilisation de structures de données peu habituelles ;
    • l'exploitation de pypy pour gagner terriblement en performances (pypy c'est un compilateur de Python en Python, et ça fulgure totalement, facilement 10 fois plus rapide sur nos exercices longs) ;
    • les choix entre modélisation, c'est à dire abstraction des données et des actions pour manipuler plutôt des concepts, et algorithme impératif, qui fait le boulot rapidement, élégamment, et en quelques lignes.

    J'avoue que sur la fin, ça tient plus de la persévérance, voire de l'entêtement, que du pur plaisir.
    Et demain et après-demain ça va être coton, surtout dimanche, je n'ai aucune idée de si je vais pouvoir les faire dimanche les exercices !
    En tout cas pas si c'est trop long à coder…

    Mais sinon oui, je pense qu'on pourra rechercher quelques morceaux choisis, des jolies représentations, et peut-être faire une dépêche à 14 mains, sur le ressenti, le pourquoi on le fait, et ce que ça apporte d'en discuter ici sur les forums de LunxFR, etc.

    • Yth.
  • [^] # Re: Mes conseils...

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 23. Évalué à 2.

    Et les données initiales qui donnent le résultat vu plus haut après 881 itérations !

    Titre de l'image

    • Yth.
  • [^] # Re: Mes conseils...

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 23. Évalué à 2.

    Titre de l'image

    Et une autre image pour valider visuellement les résultats de test, avec la solution finale du test au round 20.

    • Yth.
  • [^] # Re: Mes conseils...

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 23. Évalué à 2. Dernière modification le 23 décembre 2022 à 13:34.

    @dataclass(frozen=True)
    class Direction:  # Sur-modélisation de la direction
        d: int
        @classmethod
        def init(cls):
            cls.N = Direction(0)
            cls.S = Direction(1)
            cls.W = Direction(2)
            cls.E = Direction(3)
            return [cls.N, cls.S, cls.W, cls.E]
        @classmethod
        @cache
        def get(cls, d):
            return cls.init()[d % 4]
        @cached_property
        def next(self):
            return Direction.get(self.d + 1)
        def __str__(self):
            return "NSWE"[self.d]
    
    class Elf(tuple):  # Modélisation failsafe d'une position d'elfe.
        @cached_property
        def col(self):
            return self[0]
        @cached_property
        def row(self):
            return self[1]
        @cached_property
        def enw(self):
            return Elf((self.col - 1, self.row - 1))
        @cached_property
        def en(self):
            return Elf((self.col, self.row - 1))
        @cached_property
        def ene(self):
            return Elf((self.col + 1, self.row - 1))
        @cached_property
        def ew(self):
            return Elf((self.col - 1, self.row))
        @cached_property
        def ee(self):
            return Elf((self.col + 1, self.row))
        @cached_property
        def esw(self):
            return Elf((self.col - 1, self.row + 1))
        @cached_property
        def es(self):
            return Elf((self.col, self.row + 1))
        @cached_property
        def ese(self):
            return Elf((self.col + 1, self.row + 1))
        @cached_property
        def around(self):
            return {self.enw, self.en, self.ene, self.ew, self.ee, self.esw, self.es, self.ese}
        @cached_property
        def N(self):
            return {self.enw, self.en, self.ene}
        @cached_property
        def S(self):
            return {self.esw, self.es, self.ese}
        @cached_property
        def W(self):
            return {self.enw, self.ew, self.esw}
        @cached_property
        def E(self):
            return {self.ene, self.ee, self.ese}
        def look(self, d):
            return [self.N, self.S, self.W, self.E][d.d]
        def go(self, d):
            return [self.en, self.es, self.ew, self.ee][d.d]
        def choose(self, direction, elves):
            for _ in range(4):
                if self.look(direction).isdisjoint(elves):
                    return self.go(direction)
                direction = direction.next
    
    def inputs(data):
        return {
            Elf((col, row))
            for row, r in enumerate(data.splitlines())
            for col, c in enumerate(r)
            if c == "#"
        }
    
    
    def dimension(elves):
        return (
            min(e.col for e in elves),
            max(e.col for e in elves),
            min(e.row for e in elves),
            max(e.row for e in elves),
        )
    
    
    def iteration(elves, direction, debug=False):
        considering = set()
        blocked = set()
        for elf in elves:
            if elf.around.isdisjoint(elves):
                elf.choice = None
                continue
            elf.choice = elf.choose(direction, elves)
            if not elf.choice:
                continue
            if elf.choice in considering:
                blocked.add(elf.choice)
                elf.choice = None
            else:
                considering.add(elf.choice)
        considering.difference_update(blocked)
        move = {elf for elf in elves if elf.choice in considering}
        moveto = {elf.choice for elf in move}
        elves.difference_update(move)
        elves.update(moveto)
        return len(considering)
    
    Direction.init()
    direction = Direction.N
    elves = inputs(sys.stdin.read())
    round = 0
    while iteration(elves, direction):
        round += 1
        direction = direction.next
        if round == 10:
            c0, c1, r0, r1 = dimension(elves)
            print(f"Empty Spaces at Round 10 = {(c1 - c0 + 1) * (r1 - r0 + 1) - len(elves)}")
    print(f"Ended at round {round+1}")

    Simple, propre, impossible de se planter, tout est clair, tout est sur-validé. Et ça fonctionne.
    Mon bug c'est parce que j'avais fait une boucle pour afficher du debug.
    Sinon j'aurais pas fait de boucle, et utiliser des set.difference/update comme dans le code présenté…
    Pfff…

    Ah, oui, partir sur une classe dérivée de tuple pour les Elfes, c'est évidemment pour pouvoir utiliser les fonctions d'ensemble, très simples et efficaces, sans avoir à coder quoi que ce soit de compliqué, ou réinventer la roue !

    • Yth.
  • # Mes conseils...

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 23. Évalué à 2.

    Ne pas modifier un set() pendant qu'on itère ce même set().

    Vérifier notre index d'itération, des fois qu'il indique la dernière itération a avoir vue des changements plutôt que la première itération où personne n'a bougé.

    Après 3h à traquer un bug pourri (j'ai vraiment le cerveau en rade), une simple simulation avec une jolie modélisation fonctionne sans lourdeur, pas de données extraordinaires ni de surcharge CPU ici, juste de la méthode, des intersections d'ensembles, et une jolie image.

    Titre de l'image

    for elf in elves:
        if elf.choice in ok:
            elves.remove(elf)
            elves.add(elf.choice)

    Hein que c'est pourrave et qu'on voit pas vite les effets du bidule quand ça fonctionne sur deux rounds de validation ?
    Bref : for elf in elves.copy() pour faire vite.
    Ou mieux :

    move = {elf for elf in elves if elf.choice in ok}
    moveto = {elf.choice for elf in move}
    elves.difference_update(move)
    elves.update(moveto)
    • Yth.
  • [^] # Re: papier, ciseaux, colle

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 22. Évalué à 2.

    Joli :)

    • Y.
  • [^] # Re: Trop pour moi

    Posté par  (Mastodon) . En réponse au message Avent du Code, jour 22. Évalué à 3.

    Je pense que l'idée du patron peut fonctionner.
    Tu as 12 liens à faire, les 12 arêtes, et déjà quelques-unes de posées : les faces adjacentes, il y en a 5 dans un patron.
    Et là de proche en proche tu peux recontruire les liens manquants.

    Avec les données d'exemple mais en modélisant un vrai dé, tu as ça:
    __1_
    453_
    __62

    Les liens sont : 1-3, 3-6, 3-5, 5-4, 6-2
    À gauche de la face 1 et de la face 3 tu as la même face, ici on l'a à gauche de la face 3, c'est la 5, tu peux donc lier 1 et 5 avec une rotation de -1 de 1 vers 5 et de +1 de 5 vers 1.

    Et tu cherches des faces adjacentes dont une des deux a un voisin, tu vas pouvoir faire :

    • 1 et 3 -> 5 -> ajoute 1-5
    • 3 et 5 -> 6 -> ajoute 5-6
    • 3 et 6 -> 2 -> ajoute 3-2

    Tu viens de passer à 8 arêtes, et tu sais qui te manque :
    1-2, 1-4, 2-4, 4-6.
    Là je suppose qu'il faut chercher des voisins virtuels, par exemple tu as le lien construit 3-2, 3 adjacent à 1, selon la première méthode :

    • 1 et 3 -> 2' -> ajoute 1-2' où 2' est la rotation de 2 selon le lien construit 3-2, en additionnant les rotations, on a un demi-tour entre 1 et 2.
    • 4 et 5 -> 1' -> ajoute 4-1' où 1' est la rotation de 1 selon le lien construit 1-5, en additionnant les rotations, on a aussi un demi-tour entre 1 et 4.
    • 4 et 5 -> 6' -> ajoute 4-6' où 6' est la rotation de 6 selon le lien construit 5-6, en additionnant les rotations, on a aussi un demi-tour entre 4 et 6.

    Trois liens de premier niveau nous permettent de trouver trois liens de second niveau, il nous reste un dernier lien à trouver : 4-2, chacun à l'autre bout du bidule.
    Mais avec 2', le 2 construit à côté de 3 avec une rotation de -1, on a un alignement de 4 faces : 4-5-3-2, qu'on aurait pu avoir sur un patron initial d'ailleurs. Et là 4-2' est lié directement parce que la terre est ronde (un truc du genre), donc on a notre lien 4-2 avec une rotation dont il faut bien calculer le sens avec une aspirine.

    Bref, on doit pouvoir bricoler un algorithme en deux passe et un dernier lien, et tout reconstruire.

    • Yth.