Suite de l'Avent du Code, jour 14.
Derrière la cascade se trouve une caverne. Pas de bol, elle commence à se remplir de sable.
Il va falloir trouver un endroit sûr.
Suite de l'Avent du Code, jour 14.
Derrière la cascade se trouve une caverne. Pas de bol, elle commence à se remplir de sable.
Il va falloir trouver un endroit sûr.
# python, vite fait bien fait
Posté par steph1978 . Évalué à 4.
Le parsing de l'input est presque plus long à écrire que l'application de règles : 4 boucles
for
imbriquées et 4split
contre 3 boucleswhile
imbriquées.Voici mon code pour la partie deux. La partie est identique excepté la condition de sortie.
Et une jolie nimage de la caverne remplie de sable:
[^] # Re: python, vite fait bien fait
Posté par Eric P. . Évalué à 2.
Comment as-tu généré l'image?
Excusez l'absence d'accents dans mes commentaires, j'habite en Australie et n'ai pas de clavier francais sous la main.
[^] # Re: python, vite fait bien fait
Posté par steph1978 . Évalué à 2.
J'aime bien utiliser le format PNM car c'est du texte et donc facile à générer.
Sous linux, ça se visualise nativement. Mais ça peut être converti en PNG grâce à ImageMagic :
convert a.pnm -scale 400% a.png
# En Python, modélisé
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 4. Dernière modification le 14 décembre 2022 à 11:40.
# Pistes pour la partie 2
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 4.
Je me demande s'il ne serait pas possible de résoudre la partie 2 bien plus vite, en calculant l'aire des zones protégées par des rochers.
En effet, le nombre d'unités de sables tombées, c'est l'aire d'une triangle plein, moins celle des rochers qu'il contient, moins l'aire des zones protégées par ces derniers.
Ceci dit, déterminer la zone protégée par l'ensemble des rochers, c'est loin d'être évident. La zone protégée par un segment horizontal, c'est facile, c'est un triangle dessous. La zone protégée par un segment vertical, c'est facile, c'est rien du tout. Mais quand on commence à avoir des segments horizontaux et verticaux qui se touchent, ça devient compliqué.
Allez, une autre piste, sans doute pas beaucoup plus simple. On dirait qu'on peut déterminer la zone protégée par des rochers, non pas seulement par calcul, mais aussi par une simulation bizarre : faire couler de l'air depuis le bas vers le haut et regarder où il s'accumule. Mais ça pose le problème d'introduire cet air : il faut qu'il s'accumule et qu'il traverse en même temps les segments…
# Beaucoup de temps pour animer et afficher joli
Posté par Yth (Mastodon) . Évalué à 4.
Parce que un truc de 351 * 175 dans le terminal c'est galère quand même…
Bref, j'ai perdu plein de temps à faire une animation pas trop lente (j'ai fini par exponentiellement sauter des images : j'affiche l'image 2n), et réussir à faire entrer ça proprement dans le terminal. Après coup j'ai réalisé qu'il suffisait d'afficher chaque grain de sable une fois calculé, au lieu de tout retracer… Dans un terminal… Diantre…
J'avais un bug débile aussi pour l'exo 2, comme je voulais un sol pas trop large pour l'affichage, j'ai essayé d'être intelligent, et ça n'a pas marché, j'ai fini par faire un affichage avec un sol pas très large, puis rajouter un sol très très large.
Après j'ai triché et j'ai juste mis le sol en dur aux bonnes dimensions pour tout afficher, une fois le résultat obtenu.
Deux belles images :
Et un code probablement trop complexe.
L'affichage déjà
Et le code en lui-même :
Il faut vachement zoomer arrière dans le terminal, après c'est écrit trop petit pour lire, mais on a une belle animation :)
[^] # Re: Beaucoup de temps pour animer et afficher joli
Posté par Yth (Mastodon) . Évalué à 2. Dernière modification le 14 décembre 2022 à 16:01.
Et maintenant, on allume le cerveau :
Pour l'exercice 2, la base se calcule trivialement : le sable formant une pyramide, on sait qu'il va de 500-hauteur à 500+hauteur, vu qu'on a 174 de haut (de 0 à 173), la coursive est en 174, et le sol en 175, le sable s'entasse donc de 326 à 674, et le sol doit s'étendre une case plus loin : de 325 à 675, comme « triché » dans mon code, sauf que ça se calcule de façon sûre avec d'autres données en entrée.
Pour l'exercice 2 encore, et suivant la remarque de Tanguy sur les zones protégées par les rochers pour calculer des surfaces :
On va créer des cases « dark » sous les lignes.
Une ligne de
(x1, y1)
à(x2, y2)
avecx1<=x2
va générer une ligne protégée de gauche à droite de(x1+1, max(y1, y2))
à(x2-1, max(y1, y2))
, donc six1+1>x2-1
(ça arrive quandx1==x2
, ligne verticale, ou quand la ligne horizontale fait 2 de large :x2=x1+1
) on ne met rien.Après on peut filtrer les cases bouchées (dark et rocher) sur la zone de pyramide de sable, c'est à dire quand
500-y <= x <= 500+y
pour chaque élément. Ici on ne supprime rien, donc on n'a pas à gérer d'éventuels effets de bord, avec une plateforme qui dépasse de la pyramide de sable et peut protéger une zone qui serait ensevelie si la source du sable était plus haute.La taille de la pyramide est, en prenant le triangle de droite et en le posant retourné au dessus du triangle de gauche, un carré de la hauteur totale, soit
175^2 = 30625
grains potentiels.Ici ça ne suffit pas : un mur vertical sous une plate-forme va protéger une zone. Donc il faut ne pas réduire la ligne sur un côté si on a un rocher juste là.
Les données en entrée ne sont pas collaboratives, donc en fait on essaie toujours d'élargir la plate-forme qu'on considère pour la zone protégée du dessous, sur la gauche et la droite, puis on protège la ligne en dessous en retirant un élément à gauche et un à droite.
-> Ça fonctionne, il faut juste faire très attention à protéger une ligne en dessous des derniers rochers, le niveau de la coursive, mais pas plus bas au niveau du sol et en dessous, en traitant les données en flux on n'a pas la taille de la zone, donc la position du sol, donc on doit élaguer après coup pour le décompte : tout ce qui est en
y < 175
.Voici l'image générée avec les rochers et les zones protégées en dessous :
Pour mon exemple, j'ai en zones protégées (rochers et dark) 1804 cases, donc 30625-1804 = 28821, c'est mon résultat !
Pour les deux exercices :
Quand le sable n'est pas en chute libre, il va s'empiler sur toutes les cases visiter, à terme, sauf à sortir du terrain de jeu pour l'exercice 1.
Donc on n'est pas obligé de faire tomber le sable grain par grain, mais on peut poser des couches, avec un algo récursif.
Il suffit de le faire prendre en remontant la récursion quand on a trouver où se poser en bas. Parce que si on ne trouve pas où se poser (exercice 1 uniquement), alors aucun grain suivant ne pourra se poser.
C'est beaucoup plus simple à mettre en œuvre pour l'exo 2 puisqu'un fil de sable trouvera toujours un endroit où s'arrêter, donc on peut remplir en descendant, et explorer à la fois à gauche et à droite en bas de chaque chute libre.
Pour l'exo 1, si on parcours normalement, qu'on pose les grains en remontant de la récursion et pas avant de descendre, et qu'on sort brutalement (exception python en haut de l'exploration) dès qu'on est au bout, on devrait avoir le résultat.
Je ne l'ai pas encore fait, il est tard, je devrais commencer ma journée de taf quand même :D
[^] # Re: Beaucoup de temps pour animer et afficher joli
Posté par Yth (Mastodon) . Évalué à 2.
Au passage, les images sont générées comme un bourrin :
Yth.
[^] # Re: Beaucoup de temps pour animer et afficher joli
Posté par Yth (Mastodon) . Évalué à 2.
[^] # Re: Beaucoup de temps pour animer et afficher joli
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 3.
Bravo pour l'implémentation de mon idée !
# Optimisation
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 3.
Visiblement, il y a une optimisation possible : une si un grain de sable, lâché du point de départ, tombe à un endroit, on peut lâcher ce grain et les suivants de cet endroit, jusqu'à ce qu'il soit ensablé…
[^] # Re: Optimisation
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 3.
Avec ladite optimisation :
[^] # Re: Optimisation
Posté par barmic 🦦 . Évalué à 2.
J'ai essayé et ça ne m'a pas fait gagner grand chose. J'ai trouvé par contre une solution efficace.
Au lieu de faire tomber un grain de sable, je regarde toutes les positions accessible depuis le point de départ avec comme règle les même mouvements qu'un pion aux échecs. Je passe de 27 minutes d’exécution à 0.7s.
En groovy ça donne:
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.