Suite de l'Avent du Code, jour 17.
En fait, avec nos éléphants de compagnie, nous ne sommes pas perdus dans n'importe quel volcan : c'est la console de jeu de Vulcain, qui a commencé une partie de Tetris avec des blocs de rocher et des jets de gaz brûlants dans la caverne où nous nous trouvons.
Mais pas de panique, la meilleure chose à faire, c'est de prendre le temps de bien modéliser ça, et tout va bien se passer.
Pas encore de solution de mon côté, ça attendra lundi je pense.
# Tetris style
Posté par syj . Évalué à 3.
J'ai bien galéré encore sur celui-ci ~ 4h.
La première partie est relativement simple. Je joue à Tetris dans un tableau de char.
La deuxième partie est galère car si j'utilise la méthode de la première partie ,avec un clear du tableau quand c'est possible après une ligne pleine.
Il me fallait ~20j de calcul pour approcher 1000000000000L piece.
J'ai donc identifié quand le pattern d'empilement se répète. De cette manière, j'ai rapidement le test unit de la 2eme partie qui marchait.
pour trouver 1514285714288.
Seulement, quand j'appliquais la méthode sur mon input, çà ne marchait pas.
Je suis revenu sur un jeu plus petite et j'ai comparé la première méthode et la deuxième méthode avec le raccourcis quand je détecte la répétition.
J'ai constaté qu'il me manquait 9 à chaque application de la répétition.
En ajoutant, le nombre de répétition fois 9 ,j'ai obtenu le résultat attendu.
[^] # Re: Tetris style
Posté par Eric P. . Évalué à 3.
Je viens de le finir, et il m'a fallu plusieurs heures aussi.
Ma premiere idee d'optimisation apres la partie 1 c'etait d'utiliser @functools.lru_cache pour gagner du temps au cas ou certains des inputs se repetaient. La suite de 'jets' est tres longue, mais sur une quantite si enorme d'essais j'avais un peu d'espoir.
Le cache aidait, mais pas suffisamment pour avoir une reponse suffisamment rapide. Je voulais voir a quel point le cache etait utilise donc j'ai trouve que lru_cache ajoute une method cache_info() sur la method cachee, qui renvoit les statistiques de cache hit/cache miss.
Et je me suis rendu compte que le cache etait systematiquement utilise apres la 1927e pierre, indiquant la presence d'une boucle.
J'ai aussi perdu du temps avec le fait que le tout premier cycle donnait une hauteur legerement au dessus des suivantes, mais j'ai finalement trouve.
Par contre je cale toujours sur la deuxieme partie du jour 16, je ne me suis pas encore resolu a regarder l'entree de forum d'hier, mais je crois que je vais m'y resoudre.
Excusez l'absence d'accents dans mes commentaires, j'habite en Australie et n'ai pas de clavier francais sous la main.
[^] # Re: Tetris style
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 4.
Je n'ai pas encore commencé, mais vu l'énoncé de la première partie, je dirais que l'incrément de hauteur doit se répéter au bout du PPCM du nombre de formes et du nombre de d'instructions de direction du vent.
Avec la première série de tant de blocs qui doit monter un petit peu plus haut puisqu'elle est posée sur un sol plat et non sur une tour qui sommet irrégulier.
[^] # Re: Tetris style
Posté par Yth (Mastodon) . Évalué à 2. Dernière modification le 17 décembre 2022 à 19:23.
C'est plus compliqué que ça a priori.
Je n'ai pas de méthode de calcul du cycle, je le mesure en prenant des bornes assez grandes.
On a plusieurs problèmes :
En pratique, il suffit de faire une tour de deux cycles plus la fin, on a un cycle normal et complet au milieu, donc on sait qu'on peut en rajouter autant qu'on veut, ça agrandira linéairement.
Le principe c'est ça, avec la fonction
simulation()
qui fait une simulation (ouais ouais ! Promis !), en paramètres lesdata
, et le nombre de blocs à faire tomber. Elle retourne la hauteur finale. L'exercice 1 c'est l'appel avec 2022 blocs, et voilà.Cas particulier, si je fournis un 3è paramètre, je laisse passer ce nombre de blocs, et je prend l'état (n° de bloc, n° d'instruction), et dès que je retrouve le même état, j'ai mon cycle, je sors la valeur !
Après on mesure, on calcule, ça marche.
[^] # Re: Tetris style
Posté par Yth (Mastodon) . Évalué à 2.
Sachant que j'ai deux valeurs en dur pour la calcul du cycle :
1 million d'itérations max, et 2000 blocs à laisser passer.
Je n'ai aucune idée de comment déterminer des valeurs propres a priori, la boucle sort à la 3705è itération, donc j'ai de la marge avec 1 million…
Je sais que le cycle vaut 1705 et que je dois passer plus de 200, mais qu'à 300 ça passe, mais quid d'autres données ?
Donc j'ai pris large, passer 2000 lignes, et avoir un cycle de moins de 1 millions de blocs, mais en vrai, j'en sais rien.
Pas d'algo en tête pour ces valeur, ou même de calcul de maximum où je peux affirmer qu'avec ces valeurs là j'aurais forcément une réponse.
[^] # Re: Tetris style
Posté par Yth (Mastodon) . Évalué à 2.
Ah !
J'ai trouvé comment tout résoudre (ex 1 et 2) avec la simulation d'une seule tour, d'environ 3600 de haut pour mes données.
Je valide demain, ou lundi selon les exos de demain…
# Le Jour du Tetris
Posté par Yth (Mastodon) . Évalué à 2.
Suite à mes messages précédents, j'ai avancé dans la résolution efficace du problème, mais en réalité pas terminé.
Mon idée c'était qu'on cycle dès qu'on revient à un couple
(n°block, n°instruction)
qui est déjà passé, n°block c'est de 1 à 5, et n°instruction de 0 à 10091 chez moi (taille des données en entrée), et 0 à 39 pour les données de test.Comme si ce seul état était déterministe, et que l'état du terrain n'entrait pas en ligne de compte.
Fourbement, ça suffit avec les données de test.
L'idée donc c'est générer des blocs en enregistrant à chaque itération la hauteur, on en aura besoin de quelques-unes à la fin.
Mais aussi on enregistre l'historique de l'état
(n°block, n°instruction)
et l'itération où elle s'est produite.Dès qu'on a le sentiment de cycler, c'est à dire que notre état est déjà passé, on note l'itération où ça s'est produit la première fois, et la seconde.
La différence c'est la durée de notre cycle.
On a donc :
(10**12-base)//cycle
;(10**12-base)%cycle
;En données de test ça fait une base de 14 blocs, un cycle de 35, une hauteur par cycle de 53.
Là on va simuler une tour complète en enlevant un maximum de cycles entiers au milieu, soit une hauteur de
base + 2 cycles + fin
, parce que avec un seul cycle on a des effets de bords.Et on continue si nécessaire jusqu'à une hauteur de 2022 pour le premier exercice.
Là on a la hauteur à 2022, la hauteur ajoutée par un cycle, et la hauteur des extrémités avec deux cycles, on multiplie, on ajoute, on mélange à la bave de crapaud et hop, 1514285714288 sur les données de test.
En données réelles j'ai ce résultat :
Base de 39 blocs (?!?), cycle de 1725 (mais non c'est 1705 !!), et score final de 1555942028979 au lieu de 1553665689155.
L'idée est bonne, mais la réalisation craint un peu, la supposition de départ est fausse, je rappelle :
En pratique, je stocke comme état
(n°block, n°instruction, représentation des X dernières lignes du terrain)
.Et avec 995 lignes, j'atteins la vraie stabilité, la vraie base non cyclique, même si 14 suffisent pour trouver le résultat avec mes données.
Donc encore un peu de travail pour trouver vraiment le résultat sans le connaître à l'avance.
Par contre une unique construction de tour de 4995 blocs !
[^] # Re: Le Jour du Tetris
Posté par Yth (Mastodon) . Évalué à 2.
Et la solution, enfin, nous apparaît avec un mélange de brutalité et de finesse.
On reprend où on en était quand on croyait avoir raison : on vient de reboucler sur un état
(n°block, n°instruction)
.On compare avec un éventuel hash et snapshot enregistré pour cet état. La première fois qu'on boucle : on n'en a pas.
Donc on prend une photo, c'est à dire l'état du terrain sur l'ensemble des lignes qui forment le cycle potentiel, et uniquement elles (en gros :
str(board[-(hauteur actuelle - hauteur d'avant):]
).On calcule le hash de cette photo pour comparer plus vite.
On stocke ces deux valeurs dans deux tableaux.
On continue, et maintenant on va revenir une troisième fois sur le même état ! Sauf que là on a un hash et une photo, on compare.
Si c'est différent, on remplace et on poursuit.
Si c'est identique, on valide en comparant la photo complète hein, faudrait pas planter sur une peu probable collision, et on a enfin trouvé un vrai cycle authentique et prouvé par une photo certifiée, avec signature !
On reprend l'algo là où on en était.
Et on constate que le premier vrai cycle commence au bloc 59 (!?!?! Mais… Pourquoi si peu ?), avec un cycle de 1705 blocs.
On a trouvé deux cycles rigoureusement identiques, le premier de 60 à 1764 et le second de 1765 à 3469.
Ils ont une hauteur de 2649 lignes, et on a donc comparé deux blocs de 2649 lignes de Tetris qui se suivent, et ils étaient rigoureusement identiques, et chacun des deux commence avec le même bloc à la même instruction. On cycle, c'est acquis.
La zone début + 2 cycles + fin fait toujours 4995 blocs, on ne simule pas un bloc de plus.
Et on a toujours un résultat valide, mais là on en est sûrs.
PS : Je nettoie un peu le code et je poste ça…
# Côté code
Posté par Yth (Mastodon) . Évalué à 2.
Ici j'ai pas mal de modélisation de mon Block Tétris.
Vu l'ampleur de la tâche avant grosse réduction, cf messages précédents, je prévoyais de gagner le moindre micro-cycle d'horloge.
Donc quand on déplace à gauche, on teste les blocs de gauche, à droite ceux de droite, en bas ceux du bas.
La Simulation par contre devient complexe entre ma première version et la seconde…
Le code en brut. C'est bourré d'itérateurs de partout
[^] # Re: Côté code
Posté par Yth (Mastodon) . Évalué à 2.
et le Block.color sert à un truc :
On affiche en couleur le Tetris des n-4 dernières lignes (les 4 du haut sont toujours vides).
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.