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 ^
fromcollectionsimportdequeclassPosition(tuple):def__add__(self,other):returnPosition((self[0]+other[0],self[1]+other[1]))def__contains__(self,other):return(0<=other[0]<self[0]and0<=other[1]<self[1])defmoves(self,dimensions):return(_for_in(self+(1,0),self+(-1,0),self+(0,1),self+(0,-1))if_indimensions)defwhirlwind(x,y,d,w,h,n):ifd==">":return[(_%w,y)for_inrange(x,x+n)]ifd=="<":return[(_%w,y)for_inrange(x,x-n,-1)]ifd=="^":return[(x,_%h)for_inrange(y,y-n,-1)]ifd=="v":return[(x,_%h)for_inrange(y,y+n)]data=sys.stdin.read().strip().splitlines()dimensions=Position((len(data[0])-2,len(data)-2))# should be 120, 25ppcm=12ifdimensions[0]==6else600# complete whirlwind board cycle lengthstart=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 unstoppableendpos=end+(0,-1)# Should be (5, 3) or (119, 24)board=deque((set(_)for_inzip(*[whirlwind(x-1,y-1,c,dimensions[0],dimensions[1],ppcm)fory,lineinenumerate(data)forx,cinenumerate(line)ifcin"<>^v"])),ppcm)defreach(start,end,board,dimensions):positions={start}i=0whileendnotinpositions:positions=positions.union(pfor_inpositionsforpin_.moves(dimensions)).difference(board[0])board.rotate(-1)i+=1returnir1=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…
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 :
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.
Posté par Yth (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)classDirection:# Sur-modélisation de la directiond:int@classmethoddefinit(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@cachedefget(cls,d):returncls.init()[d%4]@cached_propertydefnext(self):returnDirection.get(self.d+1)def__str__(self):return"NSWE"[self.d]classElf(tuple):# Modélisation failsafe d'une position d'elfe.@cached_propertydefcol(self):returnself[0]@cached_propertydefrow(self):returnself[1]@cached_propertydefenw(self):returnElf((self.col-1,self.row-1))@cached_propertydefen(self):returnElf((self.col,self.row-1))@cached_propertydefene(self):returnElf((self.col+1,self.row-1))@cached_propertydefew(self):returnElf((self.col-1,self.row))@cached_propertydefee(self):returnElf((self.col+1,self.row))@cached_propertydefesw(self):returnElf((self.col-1,self.row+1))@cached_propertydefes(self):returnElf((self.col,self.row+1))@cached_propertydefese(self):returnElf((self.col+1,self.row+1))@cached_propertydefaround(self):return{self.enw,self.en,self.ene,self.ew,self.ee,self.esw,self.es,self.ese}@cached_propertydefN(self):return{self.enw,self.en,self.ene}@cached_propertydefS(self):return{self.esw,self.es,self.ese}@cached_propertydefW(self):return{self.enw,self.ew,self.esw}@cached_propertydefE(self):return{self.ene,self.ee,self.ese}deflook(self,d):return[self.N,self.S,self.W,self.E][d.d]defgo(self,d):return[self.en,self.es,self.ew,self.ee][d.d]defchoose(self,direction,elves):for_inrange(4):ifself.look(direction).isdisjoint(elves):returnself.go(direction)direction=direction.nextdefinputs(data):return{Elf((col,row))forrow,rinenumerate(data.splitlines())forcol,cinenumerate(r)ifc=="#"}defdimension(elves):return(min(e.colforeinelves),max(e.colforeinelves),min(e.rowforeinelves),max(e.rowforeinelves),)defiteration(elves,direction,debug=False):considering=set()blocked=set()forelfinelves:ifelf.around.isdisjoint(elves):elf.choice=Nonecontinueelf.choice=elf.choose(direction,elves)ifnotelf.choice:continueifelf.choiceinconsidering:blocked.add(elf.choice)elf.choice=Noneelse:considering.add(elf.choice)considering.difference_update(blocked)move={elfforelfinelvesifelf.choiceinconsidering}moveto={elf.choiceforelfinmove}elves.difference_update(move)elves.update(moveto)returnlen(considering)Direction.init()direction=Direction.Nelves=inputs(sys.stdin.read())round=0whileiteration(elves,direction):round+=1direction=direction.nextifround==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 !
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.
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 :
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.
faces=" 12 3 56 4 "# positions des faces du d6 dans mon input, mis en lignesmax=cubesize-1forrowinrange(totalsize):forcolinrange(totalsize):c=board2[row][col]ifc==" ":continuecolor={".":"Blue","#":"Gray","<":"White",">":"White","v":"White","^":"White"}[c]face=faces[(col//cubesize)+(row//cubesize)*4]a,b=col%cubesize,row%cubesizeifface=="1":x,y,z,X,Y,Z=a,b,smax+1,1,1,.01elifface=="2":x,y,z,X,Y,Z=smax+1,b,smax-a,.01,1,1elifface=="3":x,y,z,X,Y,Z=a,0,smax-b,1,.01,1elifface=="4":x,y,z,X,Y,Z=b,smax+1,smax-a,1,.01,1elifface=="5":x,y,z,X,Y,Z=0,smax-b,smax-a,.01,1,1elifface=="6":x,y,z,X,Y,Z=a,smax-b,0,1,1,.01print(f"color(\"{color}\") translate([{x},{y},{z}]) cube([{X},{Y},{Z}]);")
Le switch de 1 à 6 applique les rotations, et déplacements en 3D pour poser la surface de la face du cube sur la face du cube 3D, j'ai dû inverser des trucs à des endroits.
C'est sous optimisé pour de l'openScad, mais j'ai fait ça rapidement, on génère tout de même 15000 objets (50x50x6), ça le perturbe pas beaucoup cela dit !
Ma grippe m'a rattrapé, le premier exo nickel, le second j'ai cédé comme toi sur les données des faces et rotations, et passé des heures à débugger un code bon à jeter !
Mon dernier code tombe enfin sur le bon résultat, mais je sais pas bien pourquoi par rapport aux précédents.
L'algo est bon depuis ce matin 9h30 environ…
C'est juste qu'il est mal écrit, et que j'arrive à rien :)
Dommage, si j'avais été plus vite, j'aurais peut-être essayé une représentation.
Oui, je l'ai fait instinctivement, mais après c'est apparu évident.
En pratique on maximise toujours l'ore dans les chemins gagnants, mais pas en construisant tout d'un coup.
Pour l'exo 1 je fais du re.findall, str.replace, re.sub, et un gros eval dès que j'ai root.
Youpi, bourrin :)
Pour le 2, bah non.
On remplace root: truc * much par root: truc - much, et humn: ???? par humn: X
À la fin on a une grosse opération bourrée de parenthèses, avec au fond du fond (X), il faut résoudre ce truc = 0.
Donc on remonte en inversant les opérations, chaque parenthèse est (nombre opération (trucs...)) ou ((trucs...) opération nombre), des gros if tout moches, et à la fin le résultat.
Sans finesse ça va assez vite : une demi seconde.
importredefiteration1(data):reg=re.compile(r"^([a-z]{4}): ([^a-z]+?)$",re.MULTILINE)whileTrue:numbers={a:f"({b})"if'X'inbelsestr(eval(b))fora,binreg.findall(data)}if"root"innumbers:yieldnumbers['root']returndata=reg.sub("",data)forname,valueinnumbers.items():data=data.replace(name,value)yielddatadefiteration2(data,r=0):reg1=re.compile(r"^\((.*) (.) ([\d.]+)\)$")reg2=re.compile(r"^\(([\d.]+) (.) (.*)\)$")whileTrue:# r = a o ba,o,b=(reg1.findall(data)+reg2.findall(data))[0]if'X'ina:data=aifo=='+':r=r-float(b)ifo=='-':r=r+float(b)ifo=='*':r=r/float(b)ifo=='/':r=r*float(b)else:data=bifo=='+':r=r-float(a)ifo=='-':r=float(a)-rifo=='*':r=r/float(a)ifo=='/':r=float(a)/ryielddata,rifdata=="(X)":returndata=sys.stdin.read().strip()# Exercice 1r=0fordiniteration1(data):r=dprint(eval(d))# Exercice 2data2=re.sub(r"root: ([a-z]{4}) . ([a-z]{4})",r"root: \1 - \2",re.sub(r"humn: \d+","humn: X",data))fordiniteration1(data2):r=dfordiniteration2(r,0):r=dprint(r[1])
Zéro modélisation, à peine de la réflexion, zéro optimisations sauf l'eval ajouté dans l'iteration1 quand on peut réduire à un nombre, basta.
Je n'ai jamais écrit que laposte.net était responsable de ce qui se passe :
on constate que laposte.net ne se foule pas beaucoup beaucoup pour essayer d'arranger la situation de leur côté, d'où la grogne…
Ce n'est pas rendre laposte.net responsable.
C'est l'explication des mécontentements.
Et oui, ils sont mal dirigés les mécontentements, mais on est en France, c'est vachement plus facile de tape sur La Poste que sur un MAGAF, c'est limite culturel !
Par contre Ferrari serait un peu responsable de continuer à te vendre une voiture qui ne peut plus rouler nulle part…
C'est pas mal de ne pas aller jusqu'au bout si on sait déjà qu'on sera en-dessous du meilleur temps.
J'ai ajouté un truc comme ça sur mon code, ça fonctionne nickel, et je divise le temps par deux, je suis à 5s pour les deux exercices.
Je passe de 492 462 chemins à 46 859 sur l'exo 1.
Et au total de 4 661 927 à 755 262 sur l'exo 2.
Vu la réduction sévère du nombre de chemins, je me demande où le temps est perdu tout de même…
Posté par Yth (Mastodon) .
En réponse au message Avent du Code, jour 20.
Évalué à 4.
Dernière modification le 20 décembre 2022 à 15:02.
C'est tellement plus intelligent que ce que j'ai fait, je suis jaloux !
Je ne pensais pas que les listes seraient assez performantes, j'aurais dû essayer.
Alors, juste comme ça, j'ai aussi une adresse @laposte.net, depuis une vingtaine d'années, que j'utilise de moins en moins.
Le service rendu pendant 15 ans était parfait, c'est à dire que je pouvais envoyer des mails à des gens, et en recevoir.
Donc je n'ai pas souscrits une adresse mail pour utiliser une Ferrari dans la gadoue ou forer de la pierre avec un forêt à métal, et le service a été parfaitement adapté au besoin - qui n'a pas changé - pendant 15 années.
Mais force est de constater que ça n'est pas le cas : ça fonctionne mais moins bien, c'est comme si ma voiture ne pouvait plus dépasser le 110 sur l'autoroute, alors que c'est la même voiture et qu'elle faisait ça très bien avant.
Aujourd'hui les Google, Microsoft et Cie essaient de flinguer le mail.
Google en faisant un immense silo Gmail vers lequel il est difficile de communiquer quand on n'est pas dedans, mais qui envoie sans soucis : utilisateur@gmail = chez-moi-ça-marche, viens ici !
Microsoft en remplaçant le mail par Exchange, ce qui fait une autre forme de silo partiellement incompatible. On a moins de difficulté à communiquer depuis l'extérieur, mais ça noyaute énormément d'entreprise qui de fait n'utilise plus le mail mais un service propriétaire nommé Exchange.
laposte.net c'est du mail.
Et aujourd'hui ça fonctionne moins bien parce que Google, Microsoft et Cie essaient de tuer le mail.
Voilà le cœur du problème.
Et on constate que laposte.net ne se foule pas beaucoup beaucoup pour essayer d'arranger la situation de leur côté, d'où la grogne…
@dataclass(frozen=False)classNumber:v:intp:intn:intdef__call__(self):returnself.v,self.p,self.n@propertydefnext(self):returnself.problem[self.n]@propertydefprevious(self):returnself.problem[self.p]@cached_propertydefmoves(self):returnself.value%(len(self.problem)-1)@cached_propertydefvalue(self):returnself.v*self.decryptionkey# Input handlingdefnumbers(data):lastid=len(data)-1yieldNumber(data[0],lastid,1)foriinrange(1,lastid):yieldNumber(data[i],i-1,i+1)yieldNumber(data[-1],lastid-1,0)defresult(problem):number=[xforxinproblemifx.v==0][0]for_inrange(1000):number=number.nextn1000=number.valuefor_inrange(1000):number=number.nextn2000=number.valuefor_inrange(1000):number=number.nextn3000=number.valuer=n1000+n2000+n3000returnrdefdecrypt(problem):fori,numberinenumerate(problem):ifnumber.v==0:continue# removes number from listnumber.previous.n=number.nnumber.next.p=number.psearch=numberfor_inrange(number.moves):search=search.next# search is now the new previousnumber.n=search.nnumber.p=search.next.p# Inserting numbernumber.next.p=inumber.previous.n=idata=[int(x)forxinsys.stdin.read().strip().splitlines()]# Problème n°1problem=list(numbers(data))Number.problem=problemNumber.decryptionkey=1decrypt(problem)print(f"First answer = {result(problem)}")# Problème n°2problem=list(numbers(data))Number.problem=problemNumber.decryptionkey=811589153for_inrange(10):decrypt(problem)print(f"Final answer = {result(problem)}")
[^] # Re: vizu
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 12. Évalué à 2.
J'aime beaucoup :)
Bravo !
# Belle modélisation, rapide, efficace.
Posté par Yth (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 ^
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…
[^] # Re: Question naïve aux lutins du Père Noël qui font l'Avent du code
Posté par Yth (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 :
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 :
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 :
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 :
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.
[^] # Re: Mes conseils...
Posté par Yth (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 !
[^] # Re: Mes conseils...
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 23. Évalué à 2.
Et une autre image pour valider visuellement les résultats de test, avec la solution finale du test au round 20.
[^] # Re: Mes conseils...
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 23. Évalué à 2. Dernière modification le 23 décembre 2022 à 13:34.
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 !
# Mes conseils...
Posté par Yth (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.
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 :
[^] # Re: papier, ciseaux, colle
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 22. Évalué à 2.
Joli :)
[^] # Re: Trop pour moi
Posté par Yth (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 :
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 :
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.
[^] # Re: Mode triche on
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 22. Évalué à 4.
Le switch de 1 à 6 applique les rotations, et déplacements en 3D pour poser la surface de la face du cube sur la face du cube 3D, j'ai dû inverser des trucs à des endroits.
C'est sous optimisé pour de l'openScad, mais j'ai fait ça rapidement, on génère tout de même 15000 objets (50x50x6), ça le perturbe pas beaucoup cela dit !
Le fichier scad est xzippé ici : aoc-2022-22-01.scad.xz
Et OpenScad se trouve dans toutes les bonnes crémeries de logiciels libres ;)
[^] # Re: Mode triche on
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 22. Évalué à 4.
Un truc dans ce goût là mais mieux fait parce que là c'est pas raccord, j'ai dû me planter dans mes rotations ^
[^] # Re: Mode triche on
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 22. Évalué à 5.
Ma grippe m'a rattrapé, le premier exo nickel, le second j'ai cédé comme toi sur les données des faces et rotations, et passé des heures à débugger un code bon à jeter !
Mon dernier code tombe enfin sur le bon résultat, mais je sais pas bien pourquoi par rapport aux précédents.
L'algo est bon depuis ce matin 9h30 environ…
C'est juste qu'il est mal écrit, et que j'arrive à rien :)
Dommage, si j'avais été plus vite, j'aurais peut-être essayé une représentation.
[^] # Re: Question naïve aux lutins du Père Noël qui font l'Avent du code
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 21. Évalué à 2.
Parfois, les résultats, c'est juste un nombre débile sans autre intérêt que de valider qu'on a un algo qui fonctionne.
Par contre dans certains exercices il y a des visualisations sympas, comme les écoulements de sables, ou la géode en OpenSCAD.
[^] # Re: Modélisation trop longue à débugger
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 19. Évalué à 2.
Oui, je l'ai fait instinctivement, mais après c'est apparu évident.
En pratique on maximise toujours l'ore dans les chemins gagnants, mais pas en construisant tout d'un coup.
[^] # Re: Un bug que j'ai résolu sans jamais le trouver.
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 20. Évalué à 2.
C'est clair, on fait de belles modélisations, alors que la solution d'Éric cartonne tout.
Possible que la liste chaînée devienne plus performante si on a des millions d'éléments, mais à 5000, on se fait laminer.
[^] # Re: Pas de force brute, mais soyons bourrins, oh oui, bourrins !
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 21. Évalué à 2. Dernière modification le 21 décembre 2022 à 10:51.
Donc je vire mon iteration2 puis :
Et voilà !
Finalement c'était facile à utiliser :D
[^] # Re: Pas de force brute, mais soyons bourrins, oh oui, bourrins !
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 21. Évalué à 2.
Nope, si j'avais connu sympy je l'aurais utilisé.
Jadis j'avais un truc qui faisait ça sur ma HP48GX !
Je savais qu'un truc du genre existait en Python, mais j'ai jugé que le chercher et apprendre à l'utiliser serait plus long que de bourriner :)
# Pas de force brute, mais soyons bourrins, oh oui, bourrins !
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 21. Évalué à 2.
Pour l'exo 1 je fais du re.findall, str.replace, re.sub, et un gros eval dès que j'ai root.
Youpi, bourrin :)
Pour le 2, bah non.
On remplace
root: truc * much
parroot: truc - much
, ethumn: ????
parhumn: X
À la fin on a une grosse opération bourrée de parenthèses, avec au fond du fond
(X)
, il faut résoudrece truc = 0
.Donc on remonte en inversant les opérations, chaque parenthèse est
(nombre opération (trucs...))
ou((trucs...) opération nombre)
, des gros if tout moches, et à la fin le résultat.Sans finesse ça va assez vite : une demi seconde.
Zéro modélisation, à peine de la réflexion, zéro optimisations sauf l'eval ajouté dans l'iteration1 quand on peut réduire à un nombre, basta.
[^] # Re: pour les raleurs : Que disent les conditions d'utilisation sur la fiabilité du service fourni ?
Posté par Yth (Mastodon) . En réponse au journal La Poste pas nette a encore du mal avec le courrier. Évalué à 4.
Je n'ai jamais écrit que laposte.net était responsable de ce qui se passe :
Ce n'est pas rendre laposte.net responsable.
C'est l'explication des mécontentements.
Et oui, ils sont mal dirigés les mécontentements, mais on est en France, c'est vachement plus facile de tape sur La Poste que sur un MAGAF, c'est limite culturel !
Par contre Ferrari serait un peu responsable de continuer à te vendre une voiture qui ne peut plus rouler nulle part…
[^] # Re: Erreur bete
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 19. Évalué à 2.
Parcourir en largeur et virer les chemins pourraves, c'pas mal.
Mon algo parcours en profondeur, j'ai pas cette possibilité sauf à le refaire…
Une idée de comment être raisonnablement sûr que tu as la meilleure solution en limitant à 100 ?
[^] # Re: Modélisation trop longue à débugger
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 19. Évalué à 2.
C'est pas mal de ne pas aller jusqu'au bout si on sait déjà qu'on sera en-dessous du meilleur temps.
J'ai ajouté un truc comme ça sur mon code, ça fonctionne nickel, et je divise le temps par deux, je suis à 5s pour les deux exercices.
Je passe de 492 462 chemins à 46 859 sur l'exo 1.
Et au total de 4 661 927 à 755 262 sur l'exo 2.
Vu la réduction sévère du nombre de chemins, je me demande où le temps est perdu tout de même…
[^] # Re: Un bug que j'ai résolu sans jamais le trouver.
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 20. Évalué à 2. Dernière modification le 20 décembre 2022 à 15:18.
Faut aussi que 0 reste (0, 0), pour le retrouver à la fin.
Mais ça gagne 35% de temps :)
Bravo, j'admire la simplicité !
[^] # Re: Un bug que j'ai résolu sans jamais le trouver.
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 20. Évalué à 4. Dernière modification le 20 décembre 2022 à 15:02.
C'est tellement plus intelligent que ce que j'ai fait, je suis jaloux !
Je ne pensais pas que les listes seraient assez performantes, j'aurais dû essayer.
Bravo !
Tu peux pas faire ça plutôt ?
Tu t'en fous du nombre d'occurrence, ce que tu veux c'est que chaque élément de la liste soit unique.
[^] # Re: pour les raleurs : Que disent les conditions d'utilisation sur la fiabilité du service fourni ?
Posté par Yth (Mastodon) . En réponse au journal La Poste pas nette a encore du mal avec le courrier. Évalué à 10.
Alors, juste comme ça, j'ai aussi une adresse @laposte.net, depuis une vingtaine d'années, que j'utilise de moins en moins.
Le service rendu pendant 15 ans était parfait, c'est à dire que je pouvais envoyer des mails à des gens, et en recevoir.
Donc je n'ai pas souscrits une adresse mail pour utiliser une Ferrari dans la gadoue ou forer de la pierre avec un forêt à métal, et le service a été parfaitement adapté au besoin - qui n'a pas changé - pendant 15 années.
Mais force est de constater que ça n'est pas le cas : ça fonctionne mais moins bien, c'est comme si ma voiture ne pouvait plus dépasser le 110 sur l'autoroute, alors que c'est la même voiture et qu'elle faisait ça très bien avant.
Aujourd'hui les Google, Microsoft et Cie essaient de flinguer le mail.
Google en faisant un immense silo Gmail vers lequel il est difficile de communiquer quand on n'est pas dedans, mais qui envoie sans soucis : utilisateur@gmail = chez-moi-ça-marche, viens ici !
Microsoft en remplaçant le mail par Exchange, ce qui fait une autre forme de silo partiellement incompatible. On a moins de difficulté à communiquer depuis l'extérieur, mais ça noyaute énormément d'entreprise qui de fait n'utilise plus le mail mais un service propriétaire nommé Exchange.
laposte.net c'est du mail.
Et aujourd'hui ça fonctionne moins bien parce que Google, Microsoft et Cie essaient de tuer le mail.
Voilà le cœur du problème.
Et on constate que laposte.net ne se foule pas beaucoup beaucoup pour essayer d'arranger la situation de leur côté, d'où la grogne…
[^] # Re: Un bug que j'ai résolu sans jamais le trouver.
Posté par Yth (Mastodon) . En réponse au message Avent du Code, jour 20. Évalué à 4.