<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Programmation | Dr. Goulu</title><link>https://drgoulu.com/tags/programmation/</link><atom:link href="https://drgoulu.com/tags/programmation/index.xml" rel="self" type="application/rss+xml"/><description>Programmation</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>fr-FR</language><lastBuildDate>Fri, 30 Sep 2016 00:00:00 +0000</lastBuildDate><image><url>https://drgoulu.com/media/icon_hu_eee4a95885829ab2.png</url><title>Programmation</title><link>https://drgoulu.com/tags/programmation/</link></image><item><title>Couleurs, Gamuts, Python et Open Source</title><link>https://drgoulu.com/2016/09/30/couleur-gamut-python-open-source/</link><pubDate>Fri, 30 Sep 2016 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2016/09/30/couleur-gamut-python-open-source/</guid><description>&lt;p&gt;Ce fut une excellente journée de travail, stimulante et productive. Tôt le matin, Cédric m&amp;rsquo;a montré les slides d&amp;rsquo;un article sur la mesure géométrique de la différence entre deux 
, en me demandant s&amp;rsquo;il était facile de programmer la méthode présentée
&lt;/p&gt;
&lt;p&gt;Avant d&amp;rsquo;attaquer la question et la réponse,  une petite introduction sur le merveilleux monde des couleurs s&amp;rsquo;impose.&lt;/p&gt;
&lt;h3 id="couleurs-et-gamuts"&gt;Couleurs et gamuts&lt;/h3&gt;
&lt;p&gt;En imprimerie, on mesure à l&amp;rsquo;aide d&amp;rsquo;un
 l&amp;rsquo;ensemble des couleurs produites par une imprimante, ne serait-ce que pour la calibrer 
. Mais lorsqu&amp;rsquo;on développe une imprimante industrielle, il faut en plus mesurer l&amp;rsquo;effet sur les couleurs de nombreux paramètres (qualité des substrats, composition des encres, puissance des séchoirs etc. ) afin de maximiser le &amp;ldquo;volume&amp;rdquo; des couleurs que l&amp;rsquo;imprimante est capable de reproduire.&lt;/p&gt;
&lt;figure class="alignright" style="max-width: 320px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2016/images/color7.gif" alt="cube des couleurs RGB (Red Green Blue)" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" /&gt;&lt;figcaption&gt;cube des couleurs RGB (Red Green Blue)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;L&amp;rsquo;ensemble des couleurs définit un volume car il faut trois paramètres pour déterminer une couleur. La représentation la plus connue est celle basée sur les
rouge, vert et bleu, le &amp;ldquo;RGB&amp;rdquo;. Sur votre écran, des pixels rouges, verts et bleus peuvent être allumés avec des intensités variables, habituellement codée par un entier entre 0 et 255. La
permet ainsi de vous faire percevoir 16'777'216 couleurs différentes définies par autant de points dans le cube ci-contre.&lt;/p&gt;
&lt;p&gt;De même, on peut faire un cube &amp;ldquo;CMY&amp;rdquo; avec les couleurs produites par
en déposant des encres cyan, magenta et jaune sur du papier supposé blanc.&lt;/p&gt;
&lt;p&gt;Oui mais voilà, comme vous vous en apercevez chaque fois que vous imprimez des photos à la maison, on n&amp;rsquo;obtient pas les mêmes couleurs en RGB et en CMY. Les deux cubes ne se superposent pas bien. Intuitivement, on comprend qu&amp;rsquo;un écran ne peut pas être plus noir que quand il est éteint, et qu&amp;rsquo;on ne peut pas rendre le papier plus blanc qu&amp;rsquo;il ne l&amp;rsquo;est originellement. Le même raisonnement s&amp;rsquo;applique aux autres directions de l&amp;rsquo;espace des couleurs : certaines couleurs possibles en RGB ne peuvent pas être obtenues en impression CMY, et vice-versa. C&amp;rsquo;est d&amp;rsquo;ailleurs pour ça que les imprimantes photo ont des couleurs supplémentaires, souvent du &amp;ldquo;magenta clair&amp;rdquo; et du &amp;ldquo;cyan clair&amp;rdquo; pour mieux imprimer vos couchers de soleils. Et aussi du noir, mais c&amp;rsquo;est plutôt pour imprimer du plus joli texte et économiser de l&amp;rsquo;encre des 3 autres couleurs.&lt;/p&gt;
&lt;p&gt;Les couleurs que l&amp;rsquo;on peut reproduire fidèlement se trouvent dans l&amp;rsquo;intersection des deux cubes, mais les axes des deux cubes ne sont pas les mêmes, alors comment faire ?&lt;/p&gt;
&lt;p&gt;En les représentant dans un autre espace de couleurs, plus vaste, le 
. Dans cet espace, la coordonnée L* correspond à la
et les coordonnées a* et b* à des échelles entre couleurs tenant compte de la sensibilité de l&amp;rsquo;oeil humain. En LAB, le cube CMY d&amp;rsquo;une imprimante donnée devient un patatoïde comme celui représenté ci-dessous, et le cube RGB d&amp;rsquo;un écran précis devient le volume enfermé dans le treillis. Comme on le voit, l&amp;rsquo;intersection des deux est un volume compliqué, nettement plus petit que chacun des patatoïdes.&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 512px; width: 100%;"&gt;&lt;a href="http://www.viegroup.com/mvrhelweb/gamut.html" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2016/images/crt_print_gamut_big_hu_b8550179eb21b5a1.webp" srcset="https://drgoulu.com/posts/2016/images/crt_print_gamut_big_hu_b8550179eb21b5a1.webp 320w, https://drgoulu.com/posts/2016/images/crt_print_gamut_big_hu_727fb52fba9820d1.webp 480w, https://drgoulu.com/posts/2016/images/crt_print_gamut_big_hu_3147257836a9c584.webp 512w" sizes="(max-width: 640px) 100vw, 512px" alt="Gamut d" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;Gamut d&amp;rsquo;une imprimante (solide) et d&amp;rsquo;un moniteur (treillis). Image : Michael J. Vrhel&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id="retour-aucode"&gt;Retour au Code&lt;/h3&gt;
&lt;p&gt;Bon mais alors, est-ce qu&amp;rsquo;on peut faire facilement un programme qui calcule l&amp;rsquo;intersection de deux gamuts quelconques ? Dans ces cas là la réponse standard est &amp;ldquo;ça dépend&amp;rdquo; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;si le code Matlab décrit dans l&amp;rsquo;article
est disponible, c&amp;rsquo;est tout cuit. Et peut-être même gratuit si  
 suffit.&lt;/li&gt;
&lt;li&gt;sinon (je n&amp;rsquo;ai pas trouvé le code&amp;hellip;), ça dépend de l&amp;rsquo;existence de librairies (Python de préférence) effectuant les opérations délicates:
&lt;ul&gt;
&lt;li&gt;Lire les fichiers produits par le  : pas de problème car ce sont des .txt avec les valeurs LAB des quelques dizaines de couleurs mesurées&lt;/li&gt;
&lt;li&gt;Obtenir l&amp;rsquo;
* des points : pas de problème non plus. J&amp;rsquo;avais déjà utilisé la fonction 
 basée sur la librairie 
. C&amp;rsquo;est d&amp;rsquo;ailleurs la même qu&amp;rsquo;utilise la fonction Matlab 
. Et elle fournit même le volume du
en prime!&lt;/li&gt;
&lt;li&gt;Par contre, je n&amp;rsquo;ai aucune idée de comment calculer l&amp;rsquo;intersection des deux polyèdres / gamuts. Ou plutôt si : je sais que si je ne trouve pas du code faisant ça vite et bien, je vais passer longtemps à le faire mal. En gros il faut calculer l&amp;rsquo;intersection de la surface en fil de fer avec la surface colorée dans l&amp;rsquo;image ci-contre, et vice-versa. L&amp;rsquo;algorithme le plus simple qui vient à l&amp;rsquo;esprit est de vérifier si chaque côté des petits triangles formant une surface intersecte un (ou deux &amp;hellip;) triangles formant l&amp;rsquo;autre surface, puis de refaire une enveloppe convexe de tous points d&amp;rsquo;intersection. Comme tout algo simple, il y en a probablement un bien plus efficace quelque part &amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En cherchant un peu, je tombe sur la solution :
, un package Python capable de faire des &amp;ldquo;Boolean operations on meshes (intersection, union, difference)&amp;rdquo;. Je l&amp;rsquo;installe, je code le gros de l&amp;rsquo;application, et exactement une heure après avoir attaqué le problème, je vois le volume de mes gamuts s&amp;rsquo;afficher ! mais l&amp;rsquo;appel à la fonction calculant l&amp;rsquo;intersection crashe&amp;hellip;&lt;/p&gt;
&lt;h3 id="cest-la-saison-des-châtaignes-débogage"&gt;C&amp;rsquo;est la saison des châtaignes : débogage&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;d&amp;rsquo;abord il faut installer
, un wrapper Python de 
. J&amp;rsquo;avais déjà rencontré cette librairie permettant de trouver rapidement les points les plus proches d&amp;rsquo;un autre en utilisant la structure d&amp;rsquo;
mais n&amp;rsquo;étais pas sur d&amp;rsquo;en avoir vraiment besoin. Un message d&amp;rsquo;erreur me dit que si&amp;hellip; Sur une machine Windows, cette librairie ne s&amp;rsquo;installe pas &amp;ldquo;toute seule&amp;rdquo;, il faut aller la chercher sur la fabuleuse page &amp;ldquo;
&amp;rdquo;&lt;/li&gt;
&lt;li&gt;ensuite je découvre pourquoi la phrase &amp;ldquo;Boolean operations on meshes (intersection, union, difference)&amp;rdquo; avait une suite : &amp;ldquo;if
or
is installed&amp;rdquo;. En fait, trimesh appelle l&amp;rsquo;un ou l&amp;rsquo;autre de ces logiciels pour faire le vrai boulot. Connaissant l&amp;rsquo;existence des deux, mais ayant joué avec Blender il y a quelques années et me souvenant qu&amp;rsquo;il utilise Python comme langage de script, j&amp;rsquo;opte pour Blender et &amp;hellip;&lt;/li&gt;
&lt;li&gt;&amp;hellip; le code tourne ! Mais me renvoie toujours un volume de l&amp;rsquo;intersection de mes gamuts nul. Ce sont les
temporaires que trimesh crée qui sont encore ouverts lorsque Blender y accède. Bizarre, parce que
 pour effectuer des tests automatiques et que ceux-ci ne montrent aucun problème &amp;hellip; Mais les tests tournent sur une machine (virtuelle) Linux ! Apparemment, un pingouin a le droit de lire un fichier qu&amp;rsquo;un autre pingouin a laissé ouvert, mais une fenêtre doit être refermée avant qu&amp;rsquo;elle puisse être réouverte&amp;hellip; Je vais devoir modifier le code de trimesh pour corriger ça, et je décide de le faire bien.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="lopen-source-cest-bon-pour-le-business"&gt;L&amp;rsquo;Open Source, c&amp;rsquo;est bon pour le business&lt;/h3&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt="%image_alt%"
srcset="https://drgoulu.com/posts/2016/images/opensourceloveday_hu_f8e8269531be077.webp 320w, https://drgoulu.com/posts/2016/images/opensourceloveday_hu_14d395d074fc5b5c.webp 480w, https://drgoulu.com/posts/2016/images/opensourceloveday_hu_2ebfd42e89b313b1.webp 760w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2016/images/opensourceloveday_hu_f8e8269531be077.webp"
width="760"
height="428"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
En effet, je ne sais pas si vous avez tout suivi mais je travaille dans une entreprise qui vend des machines pour gagner du pognon et payer quelques salaires en passant. Or tous les logiciels utilisés pour développer cette application relativement pointue en une seule journée sont &amp;ldquo;
&amp;rdquo;, gratuits. La moindre des choses est, me semble-t-il, de renvoyer parfois l&amp;rsquo;ascenseur partageant les améliorations que j&amp;rsquo;apporte à ces logiciels, évidemment dans la mesure où ça ne va pas à l&amp;rsquo;encontre des intérêts de mon employeur.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc
de 
, modifié
qui gère les fichiers temporaires et hop ! l&amp;rsquo;application fonctionne après grosso-modo 4 heures de boulot et 4 cafés. Et comme
 de trimesh passent toujours (sur Linux), je soumets une &amp;ldquo;
&amp;rdquo; à l&amp;rsquo;auteur de trimesh pour lui proposer d&amp;rsquo;incorporer mes changements à la branche officielle : B.A. accomplie en une heure supplémentaire à tout casser.&lt;/p&gt;
&lt;p&gt;Après ça il me restait encore un moment pour implanter une idée qui m&amp;rsquo;avait traversé l&amp;rsquo;esprit : compter combien de
sont incluses dans chaque gamut (et donc possible d&amp;rsquo;imprimer avec notre machine), et lister celles qui n&amp;rsquo;y sont pas. Mais comme les valeurs Lab de ces couleurs sont protégées par copyright, je ne pourrai pas mettre ce code à disposition en Open Source. Des centaines de milliers de lignes de code testé et performant oui, mais une table de couleurs, non&amp;hellip;&lt;/p&gt;
&lt;p&gt;Note* : ce qu&amp;rsquo;il y a de bien en écrivant un article, c&amp;rsquo;est que ça met les idées en place, ou que ça instille un léger doute. En regardant les polyèdres des gamuts RGB et CMY dans LAB, on voit qu&amp;rsquo;ils ne sont pas convexes&amp;hellip; Pour être plus précis, peut-être bien qu&amp;rsquo;il me faudrait utiliser un algo plus subtil que ConvexHull &amp;hellip;&lt;/p&gt;
&lt;h3 id="références"&gt;Références:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span id="ref-1"&gt;&lt;/span&gt;Deshpande, K., Green, P., &amp;amp; Pointer, M. R. &amp;ldquo;Metrics for comparing and analyzing two colour gamuts&amp;rdquo;, 2015, Color Research &amp;amp; Application, 40(5), 465–471.
(
)&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-2"&gt;&lt;/span&gt;Arnaud Frich &amp;ldquo;Guide de la Gestion des Couleurs -
&amp;rdquo;, 2016&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-3"&gt;&lt;/span&gt;Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., &amp;ldquo;The Quickhull algorithm for convex hulls,&amp;rdquo; &lt;em&gt;ACM Trans. on Mathematical Software&lt;/em&gt;, 22(4):469-483, Dec 1996,
&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-4"&gt;&lt;/span&gt;Vrhel, M. J., &amp;amp; Trussell, H. J. &amp;ldquo;
&amp;rdquo;, 1999, IEEE Transactions on Image processing, 8(12).&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-5"&gt;&lt;/span&gt;Beckmann, N., &amp;amp; al. &amp;ldquo;
&amp;rdquo; 1990, In Proceedings of the 1990 ACM SIGMOD international conference on Management of data  - SIGMOD ’90 (Vol. 19, pp. 322–331). New York, USA: ACM Press. DOI : 
&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>La première boucle</title><link>https://drgoulu.com/2016/06/26/la-premiere-boucle/</link><pubDate>Sun, 26 Jun 2016 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2016/06/26/la-premiere-boucle/</guid><description>&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2016/images/220px-Cf-while-fr.svg_hu_bf1e93b22836da03.webp 220w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2016/images/220px-Cf-while-fr.svg_hu_bf1e93b22836da03.webp"
width="220"
height="190"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
Comme d&amp;rsquo;autres sources fort sérieuses, Sirtin a récemment fait remonter l&amp;rsquo;origine de l&amp;rsquo;informatique aux métiers à tisser Jacquard, &amp;ldquo;programmables&amp;rdquo; par cartes perforées au tout début du XIXème siècle déjà
. Pour ma part je n&amp;rsquo;adhère pas à cette filiation car les métiers Jacquard ne connaissaient pas la notion de
: si on voulait qu&amp;rsquo;ils tissent 123 fois un motif, il fallait répéter 123 fois la même séquence de petits trous sur les cartes perforées. Autrement dit ces cartes perforées ne contenaient pas un programme mais des données pour un lecteur qui ne faisait que commander des éléments mécaniques indépendants.&lt;/p&gt;
&lt;p&gt;Une idée fondatrice de la programmation, c&amp;rsquo;est de pouvoir coder &amp;ldquo;répète 123 fois ceci:&amp;rdquo;, et que la machine ait un moyen de compter jusqu&amp;rsquo;à 123, ce qui implique l&amp;rsquo;existence d&amp;rsquo;une mémoire dont le contenu est modifié par les instructions du programme. Comme l&amp;rsquo;a très bien exprimé Alan Perlis dans un de ses
:&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;Un programme sans boucle et sans structure de données ne vaut pas la peine d’être écrit.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class="alignright" style="max-width: 302px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2016/images/302px-Ada_Lovelace_hu_20ec1c90b6f52172.webp" srcset="https://drgoulu.com/posts/2016/images/302px-Ada_Lovelace_hu_20ec1c90b6f52172.webp 302w" sizes="(max-width: 640px) 100vw, 302px" alt="Ada, en tenue de geek de 1836" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;figcaption&gt;Ada, en tenue de geek de 1836&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Alors qui a écrit le premier programme valant la peine d&amp;rsquo;être écrit, la première boucle ? C&amp;rsquo;est
. Parfaitement : une femme
. Et ceci bien avant qu&amp;rsquo;
ne propose sa
, dont l&amp;rsquo;intérêt est surtout théorique.&lt;/p&gt;
&lt;p&gt;Au contraire, Ada Lovelace a travaillé avec
sur un problème bien pratique : établir des tables nautiques, astronomiques et mathématiques exactes en automatisant leur calcul, car à l&amp;rsquo;époque ces tables calculées à la main étaient truffées d&amp;rsquo;erreurs. Des
comme la
ou la &amp;ldquo;multiplicatrice&amp;rdquo; de
facilitaient déjà le travail, mais Babbage voulut construire une &amp;ldquo;
&amp;rdquo; capable de produire des tables en évaluant des polynômes de manière itérative. Tout en la construisant, il se lança dans la conception d&amp;rsquo;une &amp;ldquo;
&amp;rdquo;  réellement programmable, et dotée notamment d&amp;rsquo;une mémoire et d&amp;rsquo;un mécanisme de
qui permettait l&amp;rsquo;exécution de boucles. Un hardware au sens propre : tout en rouages et cames propulsées à la vapeur&amp;hellip;&lt;/p&gt;
&lt;p&gt;Et c&amp;rsquo;est Ada Lovelace qui s&amp;rsquo;est attaquée au &amp;ldquo;software&amp;rdquo;. Imaginez que vous soyez à sa place et que vous disposiez de la première et unique calculatrice programmable de l&amp;rsquo;histoire, qui coûte des millions de livres de l&amp;rsquo;époque et dont la fiabilité précaire rend chaque opération précieuse. Que proposez-vous comme programme qui &amp;ldquo;vaut la peine d&amp;rsquo;être écrit&amp;rdquo; ? Certainement pas for i=1 to 100:print i; ni les nombres de Fibonacci ou les nombres premiers qu&amp;rsquo;on connait déjà. Ce qu&amp;rsquo;Ada a choisi pour le premier programme de l&amp;rsquo;histoire, c&amp;rsquo;est de calculer les
dont je vous ai
. Pourquoi ? Parce qu&amp;rsquo;avec eux et la
on peut calculer plein de tables et d&amp;rsquo;intégrales utiles.&lt;/p&gt;
&lt;p&gt;Lady Ada a donc écrit le premier programme utile de l&amp;rsquo;histoire, que voici
,
:&lt;/p&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt="la première boucle"
srcset="https://drgoulu.com/posts/2016/images/Diagram_for_the_computation_of_Bernoulli_numbers_hu_83d0d12709c43c96.webp 320w, https://drgoulu.com/posts/2016/images/Diagram_for_the_computation_of_Bernoulli_numbers_hu_c5fa33b4d6d97080.webp 480w, https://drgoulu.com/posts/2016/images/Diagram_for_the_computation_of_Bernoulli_numbers_hu_c19182a227240db8.webp 760w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2016/images/Diagram_for_the_computation_of_Bernoulli_numbers_hu_83d0d12709c43c96.webp"
width="760"
height="532"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Les boucles sont indiquées par les accolades dans les premières colonnes et par le texte &amp;ldquo;here follows a repetition of Operations thirteen to twenty-three&amp;rdquo;. La fameuse &amp;ldquo;Note G&amp;rdquo; rédigée par Ada Lovelace au base de
montre clairement qu&amp;rsquo;elle a inventé les notions de variables et de boucle en programmation:&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;It will be perceived that every unit added to &lt;em&gt;n&lt;/em&gt; in B2_n_-1, entails an additional repetition of operations (13…23) for the computation of B2_n_-1. Not only are all the &lt;em&gt;operations&lt;/em&gt; precisely the same however for every such repetition, but they require to be respectively supplied with numbers from the very_same pairs of columns_; with only the one exception of Operation 21, which will of course need B5 (from V23) instead of B3 (from V22). This identity in the &lt;em&gt;columns&lt;/em&gt; which supply the requisite numbers must not be confounded with identity in the &lt;em&gt;values&lt;/em&gt; those columns have upon them and give out to the mill. Most of those values undergo alterations during a performance of the operations (13…23), and consequently the columns present a new set of values for the &lt;em&gt;next&lt;/em&gt; performance of (13…23) to work on&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class="alignright" style="max-width: 590px; width: 100%;"&gt;&lt;a href="https://marquisdegeek.com/code_ada99" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2016/images/ADA99-Bernouilli_hu_129278aa0e12456d.webp" srcset="https://drgoulu.com/posts/2016/images/ADA99-Bernouilli_hu_129278aa0e12456d.webp 320w, https://drgoulu.com/posts/2016/images/ADA99-Bernouilli_hu_13414389dd317d1f.webp 480w, https://drgoulu.com/posts/2016/images/ADA99-Bernouilli_hu_ec2728226f29fd73.webp 590w" sizes="(max-width: 640px) 100vw, 590px" alt="ADA99 Bernouilli" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;fonction de calcul des nombres de Bernoulli en Javascript langage ADA, par S. Goodwin [4)&lt;/figcaption&gt;&lt;/figure&gt;
Et accessoirement que Madame Lovelace commentait son code en prose intelligible, une habitude qui se perd. Exemple : le code ci-contre qui calcule les nombres de Bernoulli en  
et hélas pas en
, baptisé ainsi en l&amp;rsquo;honneur de la première véritable programmeuse de l&amp;rsquo;histoire.&lt;/p&gt;
&lt;p&gt;Mais on l&amp;rsquo;a longtemps oubliée car son code n&amp;rsquo;a hélas jamais pu être exécuté : la machine analytique de Babbage avait trop de frottements, trop d&amp;rsquo;imprécisions mécaniques, elle n&amp;rsquo;a jamais fonctionné&amp;hellip;&lt;/p&gt;
&lt;p&gt;Le premier calculateur réellement programmable ayant fonctionné est, n&amp;rsquo;en déplaise aux cow-boys, allemand. Le
de
a été construit en 1941 et détruit lors d&amp;rsquo;un bombardement en 1943, mais entre deux il a été utilisé pour calculer des choses et donné naissance au premier &amp;ldquo;vrai&amp;rdquo; langage de programmation de l&amp;rsquo;histoire :
. Cependant, le Z3 ne permettait pas le
qui semble aujourd&amp;rsquo;hui indispensable à toute boucle utile. Mais comme expliqué dans
et
, le Z3 était bel et bien
 grâce à deux horribles magouilles:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;on pouvait assigner le résultat binaire d&amp;rsquo;un test à une variable, par exemple if i&amp;gt;123 then t=0 else t=1; puis utiliser cette variable pour coder les deux &amp;ldquo;branches&amp;rdquo; correspondant au &amp;ldquo;then&amp;rdquo; et au &amp;ldquo;else&amp;rdquo; en codant des formules comme a=t*x+(1-t)*y; qui fait a=x ou a=y selon la valeur de t&lt;/li&gt;
&lt;li&gt;on pouvait effectuer une boucle infinie en scotchant la fin de la bande perforée au début pour qu&amp;rsquo;elle tourne en rond, et rendre la boucle finie avec un code du genre a=a/t qui ne faisait rien tant que t=1, et provoquait une erreur &amp;ldquo;division par zéro&amp;rdquo; quand t=0, ce qui arrêtait la machine. Beark! Mais efficace.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;C&amp;rsquo;est sans aucun doute Konrad Zuse qui a fait tourner la première boucle conditionnelle de l&amp;rsquo;histoire, mais hélas on ne sait plus quel était le premier programme à utiliser cette possibilité.&lt;/p&gt;
&lt;figure class="alignright" style="max-width: 320px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2016/images/VonNeumannProgram_hu_44e78531b312919b.webp" srcset="https://drgoulu.com/posts/2016/images/VonNeumannProgram_hu_44e78531b312919b.webp 320w, https://drgoulu.com/posts/2016/images/VonNeumannProgram_hu_d9efe2816e9b0b99.webp 406w" sizes="(max-width: 640px) 100vw, 320px" alt="page de programme ENIAC par Klara von Neumann" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;figcaption&gt;page de programme ENIAC par Klara von Neumann&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Comme ce sont les vainqueurs qui écrivent l&amp;rsquo;histoire, je termine en mentionnant tout de même l&amp;rsquo;
, qui fut la première machine Turing-complète électronique. Conçue par
selon l&amp;rsquo;architecture qui est toujours celle des ordinateurs actuels. Cette machine est la première a être programmable au sens moderne du terme avec mémoire, branchements conditionnels, boucles, et femmes.&lt;/p&gt;
&lt;p&gt;En effet, avant chaque calcul, les différentes unités de l&amp;rsquo;ENIAC doivent être reconfigurées par câblage, une tâche dévolue aux 6 &amp;ldquo;
&amp;rdquo; Kay McNulty, Betty Jennings, Betty Snyder, Marlyn Wescoff, Fran Bilas et Ruth Lichterman. Elles aussi longtemps oubliées par l&amp;rsquo;histoire, un récent reportage
leur rend un hommage mérité. J&amp;rsquo;en ai retenu une phrase :&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;&amp;ldquo;The ENIAC was a son of a bitch to program&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On dit souvent que l&amp;rsquo;ENIAC a servi au calcul de la bombe atomique. Ca dépend laquelle :
, Hiroshima et Nagasaki ont eu lieu en 1945, avant qu&amp;rsquo;ENIAC soit opérationnelle en 1946. Mais ENIAC a effectivement été utilisée pour le développement des armes nucléaires américaines dans les années 1950. Par exemple le petit bout de code ci-contre provient d&amp;rsquo;un programme de calcul par la
 des neutrons diffusés lors de la fission nucléaire. Et ce code est du à 
, la femme de John. Oui, encore une femme.&lt;/p&gt;
&lt;p&gt;Qui ose encore prétendre que l&amp;rsquo;informatique est un truc de mecs ?&lt;/p&gt;
&lt;h3 id="références"&gt;Références&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span id="ref-1"&gt;&lt;/span&gt;&amp;ldquo;Le tissage à l’origine de l’informatique ?&amp;rdquo;
,
et
chez Sirtin&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-2"&gt;&lt;/span&gt;Christian Braesch &amp;ldquo;
&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-3"&gt;&lt;/span&gt;Anne-Marie Kermarrec &amp;ldquo;
&amp;rdquo;, 2015, Binaire, Le Monde&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-4"&gt;&lt;/span&gt;Steven Goodwin &amp;ldquo;
&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-5"&gt;&lt;/span&gt;Eugene Eric Kim, Betty Alexandra Toole, &amp;ldquo;Lady Ada et le premier ordinateur&amp;rdquo;, 1999, Pour la science No 261,p 64‑69. (
&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-6"&gt;&lt;/span&gt;L. F. Menebrea, &amp;ldquo;
&amp;rdquo; Bibliothèque Universelle de Genève,  Octobre 1842, No. 82, (
)&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-7"&gt;&lt;/span&gt;Bram Bruines &amp;ldquo;
&amp;rdquo;, 2010&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-8"&gt;&lt;/span&gt;
 sur StackOverflow&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-9"&gt;&lt;/span&gt;Raul Rojas&amp;quot;
&amp;quot;, 1998&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-10"&gt;&lt;/span&gt;
sur
&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-11"&gt;&lt;/span&gt;Len Shustek &amp;ldquo;
&amp;rdquo;, 2016&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>"Contre-exemples" au théorème de Fermat-Wiles</title><link>https://drgoulu.com/2016/03/25/contre-exemples-au-theoreme-de-fermat-wiles/</link><pubDate>Fri, 25 Mar 2016 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2016/03/25/contre-exemples-au-theoreme-de-fermat-wiles/</guid><description>&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;&lt;img alt="simpson_fermat"
src="https://drgoulu.com/posts/2016/images/simpson_fermat.gif"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
vient de remporter le
pour sa démonstration du
qui dit qu’il n’existe pas de solution de l’équation an+bn=cn pour a,b,c,n entiers et n&amp;gt;2. Pourtant &lt;em&gt;&lt;mauvaise foi=on&gt;&lt;/em&gt; :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;il a en réalité &amp;ldquo;seulement&amp;rdquo; démontré un cas particulier du 
(aussi appelé conjecture de Shimura-Taniyama-Weil) dont le théorème de Fermat résulte directement&lt;/li&gt;
&lt;li&gt;quelques semaines après la publication des quelques 100 pages de la démonstration d&amp;rsquo;Andrew Wiles en 1995
, Homer Simpson se promène nonchalamment et en 3D devant un contre-exemple : 1782¹² + 1841¹² = 1922¹²
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Cette égalité est due à 
, matheux et co-scénariste de cette
. Si on la vérifie sur une calculatrice standard, on trouve que le terme de gauche vaut 2.541210259e+39 et que celui de droite vaut&amp;hellip; 2.541210259e+39 ! C&amp;rsquo;est un contre-exemple du Grand théorème de Fermat, et la démonstration d&amp;rsquo;Andrew Wiles ne vaut pas tripette! &lt;em&gt;&lt;mauvaise foi=off&gt;&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;Mais en fait non:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Avec plus de décimales ou Python, on voit que le terme de gauche vaut 2541210258614589176288669958142428526657 et celui de droite 2541210259314801410819278649643651567616. Ca fait une gigantesque différence de 700212234530608691501223040959, mais comme elle représente moins d&amp;rsquo;un milliardième des nombres précédents (2.75 10-10 pour être précis), une bête calculatrice du siècle passé qui ne calculait qu&amp;rsquo;avec 9 chiffres significatifs ou en nombres flottants sur 32 bits pouvait considérer ce chiffre comme comparativement négligeable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;figure class="alignright" style="max-width: 420px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2016/images/18-Homer-Simpson_hu_367090b8e829538f.webp" srcset="https://drgoulu.com/posts/2016/images/18-Homer-Simpson_hu_367090b8e829538f.webp 320w, https://drgoulu.com/posts/2016/images/18-Homer-Simpson_hu_5280899a76f54864.webp 480w, https://drgoulu.com/posts/2016/images/18-Homer-Simpson_hu_722eb58d6bcdf88a.webp 620w" sizes="(max-width: 640px) 100vw, 420px" alt="quatre grands problèmes scientifiques résolus sur un seul tableau !" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;figcaption&gt;quatre grands problèmes scientifiques résolus sur un seul tableau !&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;En y regardant de plus près, on voit tout de suite que l&amp;rsquo;égalité est fausse car comme 1782 est pair, 1782¹² l&amp;rsquo;est aussi et comme 1841¹² est impair pour les mêmes raisons, la somme 782¹² + 1841¹² est impaire. Or 1922¹²  est pair&amp;hellip;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Informé de cette dernière objection, David X. Cohen a fait apparaître dans un autre épisode
le tableau noir suivant, sur lequel se trouve un autre faux contre-exemple : 3987¹² + 4365¹² = 4472¹². Belle conscience professionnelle, n&amp;rsquo;est-ce pas ?*&lt;/p&gt;
&lt;p&gt;Cette fois l&amp;rsquo;égalité proposée respecte la parité, et est &amp;ldquo;moins fausse&amp;rdquo; que la précédente puisque la différence ne représente que 1.89 10-11 des termes.&lt;/p&gt;
&lt;p&gt;Je me suis alors posé trois questions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt; y&amp;rsquo;a-t-il beaucoup de tels contre-exemples ?&lt;/li&gt;
&lt;li&gt;y&amp;rsquo;a-t-il une raison particulière au fait  que les deux exemples de David X. Cohen utilisent la puissance 12 ?&lt;/li&gt;
&lt;li&gt;peut-on en trouver qui sont encore moins faux que 1.89 10-11 ?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;J&amp;rsquo;ai donc écrit un
** qui génère les triplets (a,b,c) tels que an+bn=cn est juste à 10-9 près, en balayant les nombres a et b entre 100 et 100'000 et incrémentant n à partir de 3. Ce programme s&amp;rsquo;est révélé productif au point de pouvoir répondre facilement à la question No 1 : oui, il y a des centaines de faux contre-exemples de la qualité de ceux des Simpson pour chaque p et 100 &amp;lt; a,b &amp;lt; 100'000.&lt;/p&gt;
&lt;p&gt;Le plus petit faux contre-exemple trouvé donnant une différence inférieure à 10-9 est &lt;strong&gt;1295³ + 216³ = 1297³&lt;/strong&gt; . La différence entre les deux termes 2181825071 et 2181825073 n&amp;rsquo;est que de 2 !&lt;/p&gt;
&lt;p&gt;Celui ayant la précision relative la plus élevée est  &lt;strong&gt;487674 + 245764 = 495354&lt;/strong&gt;  L&amp;rsquo;erreur relative n&amp;rsquo;est que de 5.1 10-16 soit juste deux fois plus que la précision des nombres flottants sur 64 bits de la plupart des calculatrices actuelles.&lt;/p&gt;
&lt;p&gt;A la puissance 5, le record de précision est 843855  + 834525 = 964035 (à 5.67 10-15 près), ensuite la précision des contre-exemples les moins faux diminue lentement quand la puissance augmente. A la puissance 12 il y a 1931112 + 1882112 = 2021812 (1.95 10-12) qui est meilleur que celui de David X. Cohen, qui s&amp;rsquo;est probablement limité aux nombres de 4 chiffres. Mais je n&amp;rsquo;ai rien remarqué de particulier pour n=12&lt;/p&gt;
&lt;p&gt;Voilà Andrew, comme 99.99% de la population je n&amp;rsquo;ai rien compris à ta prodigieuse démonstration
qui a nécessité 20 ans de vérifications avant que tu reçoive enfin ce prix bien mérité. Je me joins à David et Homer pour te dire juste Bravo !&lt;/p&gt;
&lt;h3 id="notes"&gt;Notes:&lt;/h3&gt;
&lt;p&gt;* la dernière ligne du tableau concerne évidemment la topologie (et non, un donut n&amp;rsquo;est pas isomorphe à une sphère), mais quelqu&amp;rsquo;un sait-il à quoi correspondent les lignes 1 et 3 ? Je doute que Cohen ait sorti ces équations de nulle part&amp;hellip;&lt;/p&gt;
&lt;p&gt;** pourquoi Python ? entre autres parce qu&amp;rsquo;il gère l&amp;rsquo;
de façon transparente : rien de spécial à faire pour manipuler des nombres énormes.&lt;/p&gt;
&lt;h3 id="références"&gt;Références&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span id="ref-1"&gt;&lt;/span&gt;&lt;span class="altmetric-embed" data-badge-type="donut" data-badge-popover="right" data-doi="10.2307/2118559" style="float: right; margin: 0 0 0.5rem 0.5rem;"&gt;&lt;/span&gt;
 Andrew Wiles. &amp;ldquo;Modular elliptic curves and Fermat&amp;rsquo;s Last Theorem&amp;rdquo;, 1995, Annals of Mathematics 142 (3): 443–551. 
. (
)&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-2"&gt;&lt;/span&gt;séquence &amp;ldquo;Homer³&amp;rdquo; dans &amp;ldquo;
&amp;quot;, épisode 6 saison 7, 1995&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-3"&gt;&lt;/span&gt;
, Les Simpson épisode 2 saison 10, 1998&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-4"&gt;&lt;/span&gt;video &amp;ldquo;
&amp;rdquo; de Numberphile sur ce sujet (en anglais)&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Bits en vrac</title><link>https://drgoulu.com/2014/04/09/bits-en-vrac/</link><pubDate>Wed, 09 Apr 2014 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2014/04/09/bits-en-vrac/</guid><description>&lt;p&gt;Quelques découvertes informatiques en vrac&lt;/p&gt;
&lt;h3 id="les-formulaires-google-drive"&gt;Les formulaires Google Drive&lt;/h3&gt;
&lt;p&gt;Le 
 m&amp;rsquo;a permis d&amp;rsquo;expérimenter la puissance et la facilité d&amp;rsquo;utilisation des
 . C&amp;rsquo;est simplement génial :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;dans
, on crée un document de type formulaire&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;on se retrouve dans un éditeur permettant de composer le formulaire. On peut définir le type de chaque champ : texte, choix multiple, cases à cocher, échelle d&amp;rsquo;évaluation, tout y est. On peut ajouter des règles de validation et des actions à effectuer en fonction des réponses&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 480px; width: 100%;"&gt;&lt;a href="https://drgoulu.com/wp-content/uploads/2014/04/form-editor1.png" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2014/images/form-editor1_hu_a9cf01977cab59c3.webp" srcset="https://drgoulu.com/posts/2014/images/form-editor1_hu_a9cf01977cab59c3.webp 320w, https://drgoulu.com/posts/2014/images/form-editor1_hu_2c5aa1c6d7189fc8.webp 480w, https://drgoulu.com/posts/2014/images/form-editor1_hu_f1e314e3652ae458.webp 662w" sizes="(max-width: 640px) 100vw, 480px" alt="Editeur de Formulaire Google Drive" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;Editeur de Formulaire Google Drive&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En cliquant le bouton &amp;ldquo;afficher le formulaire en ligne&amp;rdquo; on peut voir à quoi ça ressemble pour les utilisateurs et même tester le système, car la collecte des réponses est immédiate : rien à faire de particulier !&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lorsque le formulaire  est prêt, il suffit d&amp;rsquo;envoyer le lien disponible par &amp;ldquo;Envoyer le formulaire&amp;rdquo; à des personnes choisies, ou d&amp;rsquo;intégrer la page sur un site web dans un &lt;iframe&gt;. Plusieurs blogs du C@fé des sciences l&amp;rsquo;ont même fait simultanément sans aucun problème car le formulaire n&amp;rsquo;existe en réalité (virtuelle&amp;hellip;) que chez Google.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les réponses sont automatiquement collectées dans un document &amp;ldquo;tableur&amp;rdquo; sur Google Drive : une ligne est créée pour chaque formulaire rempli, chaque colonne correspondant à un champ. Notez la colonne &amp;ldquo;horodateur&amp;rdquo; remplie automatiquement, bien utile.&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 480px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2014/images/googleform1_hu_a6abe314f2fb0325.webp" srcset="https://drgoulu.com/posts/2014/images/googleform1_hu_a6abe314f2fb0325.webp 320w, https://drgoulu.com/posts/2014/images/googleform1_hu_8d5bf332d6b672ce.webp 480w, https://drgoulu.com/posts/2014/images/googleform1_hu_f13ef0042a2a4867.webp 600w" sizes="(max-width: 640px) 100vw, 480px" alt="Table des résultats" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;figcaption&gt;Table des résultats&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Ce que j&amp;rsquo;ai trouvé assez impressionnant est que l&amp;rsquo;on peut modifier le tableau sans perturber les votes suivants. Apparemment chaque champ du formulaire est attaché à une colonne par un lien invisible, mais solide : même si on ajoute ou déplace des colonnes, les réponses suivantes restent cohérentes avec les réponses précédentes. Pour le quiz, j&amp;rsquo;ai ajouté la ligne 2 avec les bonnes réponses ainsi que la colonne D Score. Notez au passage la  géniale formule qui compte le nombre de réponses correctes avec 
 et sumproduct. Elle n&amp;rsquo;est pas de moi, et il parait qu&amp;rsquo;elle est possible aussi en Excel&amp;hellip;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;figure class="alignright" style="max-width: 300px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2014/images/stats_hu_81fae1c181f07c07.webp" srcset="https://drgoulu.com/posts/2014/images/stats_hu_81fae1c181f07c07.webp 320w, https://drgoulu.com/posts/2014/images/stats_hu_64ee39dadb93f1b2.webp 480w, https://drgoulu.com/posts/2014/images/stats_hu_4f036da3e04e65df.webp 600w" sizes="(max-width: 640px) 100vw, 300px" alt="stats" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;figcaption&gt;résumé des réponses&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Une petite dernière pour la route : dans le menu &amp;ldquo;Formulaire&amp;rdquo; on peut &amp;ldquo;afficher le résumé des réponses&amp;rdquo; qui présente les résultats sous une forme graphique qui peut être bien utile.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Les formulaires Google Drive permettent de réaliser facilement des sondages, quiz et concours divers avec toute la puissance et la sécurité (&amp;hellip;) de l&amp;rsquo;infrastructure Google. Ca fait déjà des
dans le C@fé &amp;hellip;&lt;/p&gt;
&lt;h3 id="curation-v30"&gt;Curation V.3.0‎&lt;/h3&gt;
&lt;p&gt;Rien à faire, il n&amp;rsquo;y a toujours pas mieux pour suivre les sites intéressants que les
. J&amp;rsquo;ai longtemps utilisé
avec lequel j&amp;rsquo;ai commencé à faire de la
. En effet, en cochant simplement les articles que je trouvais intéressants, Google Reader les agrégeait dans un flux RSS &amp;ldquo;de sortie&amp;rdquo; que je pouvais publier sur
.&lt;/p&gt;
&lt;p&gt;Puis Google a annoncé la fermeture de Reader (toujours incompréhensible pour moi) et j&amp;rsquo;ai utilisé
. C&amp;rsquo;était une bonne idée : Scoop.it permet d&amp;rsquo;agréger non seulement des flux RSS, mais aussi des tweets, le contenu de pages Facebook et de recherches Google. On peut créer ainsi plusieurs &amp;ldquo;topics&amp;rdquo; thématiques, et de jolis widgets comme celui ci-contre à droite. Mais le point fort de Scoop.it, c&amp;rsquo;est ses possibilités de partage : chaque contenu &amp;ldquo;scoopé&amp;rdquo; peut être partagé automatiquement sur Twitter, Facebook, Gogle+ et Tumblr, entre autres.&lt;/p&gt;
&lt;p&gt;Scoop.it, c&amp;rsquo;est vraiment bien, mais &amp;hellip; il y a un problème rédhibitoire : les liens du contenu partagé sont modifiés pour conduire les visiteurs sur la page Scoop.it du topic, et pas directement vers l&amp;rsquo;article original. Ceci a trois conséquences que je trouve gênantes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;La première n&amp;rsquo;est pas trop grave : les lecteurs doivent cliquer deux fois pour arriver à l&amp;rsquo;article qui les intéresse, une fois sur la page où ils voient le contenu partagé, puis une seconde fois sur la page Scoop.it.&lt;/li&gt;
&lt;li&gt;La seconde fausse les analyses de trafic, qui semble provenir de Scoop.it plutôt que du site de partage. Ainsi par exemple mon site a accueilli plus de 2000 visiteurs passés par Scoop.it en un an sans qu&amp;rsquo;il me soit possible de déterminer où ces 2000 personnes ont initialement découvert l&amp;rsquo;article qui les intéressait.&lt;/li&gt;
&lt;li&gt;La troisième touche le droit d&amp;rsquo;auteur : les outils de partage qui changent les liens diffusent le contenu d&amp;rsquo;autrui en coupant le lien vers la source, qui est parfois le seul élément identifiant l&amp;rsquo;auteur. Je me suis soudain aperçu que
 &amp;ldquo;rebloguait&amp;rdquo; automatiquement les articles que je trouvais intéressants, parfois en me les attribuant implicitement puisqu&amp;rsquo;il n&amp;rsquo;y avait plus de mention du site original.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Je me suis donc mis en chasse de nouveaux outils de curation, et après quelques essais j&amp;rsquo;ai choisi le &amp;ldquo;trio de la curation V.3&amp;rdquo; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
 comme agrégateur de flux. Il offre grosso-modo les fonctionnalités de Google Reader,  une
, plus une
 (en fait un plugin d&amp;rsquo;un agrégateur plus général). Chaque jours je parcours une centaine d&amp;rsquo;articles en sautant d&amp;rsquo;un à l&amp;rsquo;autre en pressant la touche
\[j\], et si je le trouve intéressant je le lis et je presse
\[s\]comme &amp;ldquo;star&amp;rdquo;. Ca le marque comme favori et l&amp;rsquo;ajoute à mon
.&lt;/li&gt;
&lt;li&gt;
Je pourrais utiliser directement CommaFeed pour partager le contenu sur Facebook, Twitter, Google+ et autres (mais pas Tumblr). Mais surtout, il me faudrait le faire manuellement : 6 ou 8 clicks de plus, c&amp;rsquo;est trop. Alors j&amp;rsquo;ai utilisé
, un service qui permet d&amp;rsquo;automatiser des tâches internet en créant des &amp;ldquo;recettes&amp;rdquo; de la forme If This Then That . J&amp;rsquo;ai ainsi créé des &amp;ldquo;recettes&amp;rdquo; qui partagent automatiquement le contenu de mon flux de sortie vers mes pages Facebook, Google+, App.net et Tumblr. Automatiquement. Rien d&amp;rsquo;autre à faire :-)  (Pour Twitter j&amp;rsquo;hésite encore&amp;hellip;)&lt;/li&gt;
&lt;li&gt;Et j&amp;rsquo;utilise toujours Scoop.it pour atteindre les utilisateurs de cette plateforme et profiter des beaux widgets, mais je n&amp;rsquo;utilise plus les outils de partage. En attendant qu&amp;rsquo;IFTTT permette de &amp;ldquo;scooper&amp;rdquo; automatiquement, j&amp;rsquo;utilise le flux de sortie comme unique source dans Scoop.it et je &amp;ldquo;scoope&amp;rdquo; à la main tout ce que j&amp;rsquo;ai préalablement sélectionné dans CommaFeed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tout ça ne me demande en définitive pas plus d&amp;rsquo;efforts que de tourner les pages d&amp;rsquo;un journal en papier, et je peux me concentrer sur la lecture tout en gardant une trace dont vous pouvez profiter où vous le souhaitez.&lt;/p&gt;
&lt;h3 id="networkx"&gt;NetworkX&lt;/h3&gt;
&lt;p&gt;
 est une librairie Python permettant de représenter et traiter des problèmes de graphes. Je l&amp;rsquo;utilise professionnellement assez intensivement ces temps-ci pour un
, mais l&amp;rsquo;autre jour il m&amp;rsquo;a permis de résoudre le
 du
 en quelques lignes seulement. En fait la plupart servent à lire le fichier des données, puis la partie intéressante tient en une seule ligne :&lt;/p&gt;
\[source lang="Python"\]&lt;p&gt;print G.size(weight=&amp;lsquo;weight&amp;rsquo;) - minimum_spanning_tree(G, weight=&amp;lsquo;weight&amp;rsquo;).size(weight=&amp;lsquo;weight&amp;rsquo;)&lt;/p&gt;
\[/source\]&lt;p&gt;Fort non ? Hélas il me semble que peu de problèmes du Project Euler concernent les graphes, donc je ne vais pas pouvoir améliorer mon score rapidement &amp;hellip;&lt;/p&gt;
&lt;h3 id="2048"&gt;2048&lt;/h3&gt;
&lt;p&gt;
Cet article serait paru il y a trois jours si je n&amp;rsquo;étais pas tombé sur
, le jeu addictif du moment. C&amp;rsquo;est un jeu tellement simple qu&amp;rsquo;il aurait du être inventé avant Pac-Man. Et on voit tout de suite comment faire : placer les puissances de 2 les unes à côté des autres pour former une chaîne croissante et propager ainsi les sommes pour arriver à former enfin, après 1024 coups au minimum, la tant convoitée pièce 2048. Il m&amp;rsquo;a fallu 3 jours. Enfin 3 soirs. 3 nuits&amp;hellip;&lt;/p&gt;
&lt;p&gt;A un certain moment j&amp;rsquo;en ai eu marre et voulu utiliser la bonne vieille méthode pour résoudre les problèmes compliqués : programmer. Mais Matt Overlan a été plus rapide et efficace :
 et est très instructif. Je crois que c&amp;rsquo;est la première fois de ma vie qu&amp;rsquo;un ordinateur m&amp;rsquo;apprend à résoudre un casse-tête plutôt que l&amp;rsquo;inverse. Peu après avoir observé le solveur parvenir au 2048, j&amp;rsquo;ai appris à dominer ma tentation d&amp;rsquo;additionner coûte que coûte les nombres les plus élevés et à conserver des lignes ou des colonnes de 4 cases &amp;ldquo;bloquées&amp;rdquo;, et j&amp;rsquo;ai gagné.&lt;/p&gt;
&lt;p&gt;Après certains passent au 
 voire au 
, mais je crois que je vais plutôt attaquer la version &amp;ldquo;
&amp;rdquo; de Valentine. Un peu déroutant de prime abord, mais j&amp;rsquo;aime beaucoup l&amp;rsquo;idée un peu holiste qu&amp;rsquo;il y a là derrière&amp;hellip; Bravo !&lt;/p&gt;</description></item><item><title>La programmation, latin du futur ?</title><link>https://drgoulu.com/2013/09/07/la-programmation-latin-du-futur/</link><pubDate>Sat, 07 Sep 2013 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2013/09/07/la-programmation-latin-du-futur/</guid><description>&lt;p&gt;Dans un récent article
 Anna Lietti fait le point sur une question qui fait son chemin un peu partout:&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;Pour former des citoyens «informatiquement éclairés»*, l’école doit-elle enseigner à tous le b. a.-ba de la programmation?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Selon certains comme
, les enfants du numérique ont une &amp;ldquo;expérience rusée&amp;rdquo; du fonctionnement des machines, mais leur approche intuitive approche vite ses limites et ne leur permet pas de dominer la machine. Or cette domination est nécessaire pour contrôler notre monde, de plus en plus automatisé, numérique et interconnecté. On le voit avec l&amp;rsquo;affaire
 : contrôler
, c&amp;rsquo;est avoir le pouvoir sur ses utilisateurs&amp;hellip;&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;Des précurseurs comme
 (élève de
) se sont intéressés dès les années 1960 à la pédagogie de l&amp;rsquo;informatique et inventé des outils comme le
 pour initier à l&amp;rsquo;algorithmique et à la programmation procédurale dès l&amp;rsquo;enfance. Pourtant, 50 ans plus tard, aucun pays n&amp;rsquo;intègre la programmation au cursus scolaire primaire, peu le font au niveau secondaire, et la branche y est rarement obligatoire.&lt;/p&gt;
&lt;p&gt;En Grande-Bretagne, suite à un rapport de la Royal Society intitulé &amp;ldquo;Shut down or restart&amp;rdquo;
qui jugeait l&amp;rsquo;enseignement de l&amp;rsquo;informatique tellement insatisfaisant qu&amp;rsquo;il vaudrait mieux ne rien faire, la décision a été prise d’initier les enfants dès 5 ans à la programmation dès la rentrée 2014 et que la programmation devienne une branche obligatoire du baccalauréat au même titre que la physique ou la chimie.&lt;/p&gt;
&lt;p&gt;En France aussi, un récent rapport de l’Académie des Sciences
 vient de recommander d&amp;rsquo;aller plus loin que la récente (ré)introduction de la spécialité &amp;ldquo;
&amp;rdquo; en terminale S
, en incluant &amp;ldquo;une initiation aux concepts de l’informatique&amp;rdquo; dès l&amp;rsquo;école primaire , puis &amp;ldquo;un véritable enseignement d’informatique, qui ne soit pas noyé dans les autres enseignements scientifiques et techniques, mais développe des coopérations avec ceux-ci dans une volonté d’interdisciplinarité&amp;rdquo; au collège, puis &amp;ldquo;proposer un enseignement obligatoire d’informatique en seconde&amp;rdquo; au lycée.&lt;/p&gt;
&lt;p&gt;Plusieurs initiatives se développement également  en Suisse, notamment:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;le Prof. Juraj Hromkovic avec son module &amp;ldquo;
&amp;rdquo;, adopté dans une trentaine d’établissements en Suisse alémanique&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Jürg Kohlas, qui promeut l&amp;rsquo;enseignement de l’informatique comme discipline fondamentale au gymnase (=lycée) dans un livre tout récent
, en recommandant de commencer par former les professeurs, un problème qui semble général&amp;hellip;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;figure class="alignright" style="max-width: 232px; width: 100%;"&gt;&lt;a href="http://scratch.mit.edu/" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2013/images/scratch_hu_913ab1dc0d067071.webp" srcset="https://drgoulu.com/posts/2013/images/scratch_hu_913ab1dc0d067071.webp 232w" sizes="(max-width: 640px) 100vw, 232px" alt="un &amp;amp;quot;script&amp;amp;quot; en Scratch" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;un &amp;quot;script&amp;quot; en Scratch&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Manuela Barraud et Olivier Jorand proposent des ateliers de &amp;ldquo;
&amp;rdquo; combinant programmation et robotique ludique dans la continuation de la &amp;ldquo;philosphie Logo&amp;rdquo;, mais ils forment aussi des enseignants à leur approche. Outre Logo, ils utilisent le langage semi graphique 
 développé au MIT pour les enfants dès 7 ans.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour ma part, voici les quelques leçons que je tire de ma maigre expérience de l&amp;rsquo;enseignement de la programmation des deux côtés de la barrière:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pas facile d&amp;rsquo;être prof. quand certains élèves maîtrisent mieux le sujet. Il faut une formation en béton, et si possible conserver le choix des armes&amp;hellip;&lt;/li&gt;
&lt;li&gt;La robotique est très motivante pour les jeunes. Avec juste une boucle et quelques tests on peut faire bouger quelque chose de concret alors que sur un écran il faut beaucoup plus de code pour faire quelque chose d&amp;rsquo;un tant soit peu excitant.&lt;/li&gt;
&lt;li&gt;Mais les robots c&amp;rsquo;est cher et délicat, alors les environnements virtuels en 3D sont un bon compromis : ils conservent un rapport résultat visuel/code élevé tout en ouvrant des possibilités amusantes comme
sans que la SPA ne proteste (
), ou monter un canon sur un robot sans occasionner trop de dégâts (
 testé avec succès au 
 )&lt;/li&gt;
&lt;li&gt;L&amp;rsquo;âge minimum pour s&amp;rsquo;intéresser à la programmation est celui où l&amp;rsquo;enfant est capable de comprendre la notion de
. Je dirais expérimentalement vers 10 ans. Les boucles, les tests, même les sous-programmes et les fonctions peuvent encore passer plus tôt avec des choses comme &amp;ldquo;POUR CARRE : REPETE 4
\[AV 100 TD 90\]: FIN&amp;rdquo;, mais c&amp;rsquo;est peut-être justement une raison de l&amp;rsquo;échec de la programmation au primaire : sans la capacité d&amp;rsquo;abstraction nécessaire pour associer une information (nombre, texte etc&amp;hellip;) à un symbole, on est très vite limité. Or cette
 n&amp;rsquo;est introduite, sauf erreur, que vers 10-12 ans, et n&amp;rsquo;est pas assimilée facilement par tous. Imaginez alors la pagaille dans les esprits si le prof de maths dit que &amp;ldquo;x=2*x-1 a pour solution x=1&amp;rdquo; et l&amp;rsquo;heure d&amp;rsquo;après celui d&amp;rsquo;informatique dit que &amp;ldquo;x=x+1 incrémente la valeur de x&amp;rdquo; &amp;hellip;&lt;/li&gt;
&lt;li&gt;Il est très difficile de découpler l&amp;rsquo;enseignement de la programmation de celui des maths. En particulier pour la robotique ludique (réelle ou virtuelle) on a très rapidement besoin des vecteurs, de la trigonométrie, voire de notions d&amp;rsquo;intégration et dérivation pour passer des vitesses aux positions ou vice-versa.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Donc je ne crois pas à l&amp;rsquo;introduction de la programmation au primaire. Et sans programmation, pour quoi &amp;ldquo;faire de l&amp;rsquo;informatique&amp;rdquo; ? Et plus tard, au collège et au lycée, à quoi bon enseigner la programmation si on ne veut pas former des armées de programmeurs ?&lt;/p&gt;
&lt;h3 id="la-programmation-latin-du-futur-"&gt;La programmation, latin du futur ?&lt;/h3&gt;
&lt;p&gt;C&amp;rsquo;est un paragraphe de l&amp;rsquo;article
qui a particulièrement retenu mon attention :&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;L’idée n’est donc pas de former de futurs programmeurs, mais d’initier les enfants à un langage programmatique** simple pour les familiariser avec la logique informatique. Les adeptes de cet enseignement ne tarissent pas d’éloges sur ses vertus pédagogiques. La programmation apprend à penser un problème jusqu’au bout, à construire des processus qui marchent en apprenant de ses erreurs. (&amp;hellip;)&lt;/p&gt;
&lt;p&gt;Et encore: le langage informatique enseigne à penser logiquement et systématiquement. «Peu de disciplines nécessitent une telle rigueur mentale», observe Jürg Kohlas. Bien sûr, les langues programmatiques** sont multiples et mouvantes. Mais quand on en a appris une, il est facile de se familiariser avec les suivantes.&lt;/p&gt;
&lt;p&gt;Ça ne vous rappelle rien? Ne croirait-on pas entendre parler du latin? «La programmation est bel et bien un langage avec un vocabulaire, une grammaire, une syntaxe, acquiesce Juraj Hromkovic. Mais il y a une grosse différence avec les langues naturelles: la plupart des gens ne savent même pas qu’ils ont affaire à un langage.»&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dans mon esprit de lycéen des années 1980, la programmation n&amp;rsquo;avait rien, mais alors RIEN à voir avec la langue morte infligée aux fils d&amp;rsquo;avocats par des curés nostalgiques. Mais avec le recul, je partage le point de vue de gens qui connaissent le latin et la programmation comme Tyler Plack
,&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;Ecrire en latin ou programmer un ordinateur requièrent tous deux une compréhension qui dépasse la pensée humaine complexe et la simplifie. De tels processus sont ce qui nous permet de penser clairement; ils font de nous qui nous sommes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Donc oui, il faut enseigner la programmation aux lycéens, même si &amp;ldquo;ça ne sert à rien&amp;rdquo;, comme le latin. Faut-il en faire une branche obligatoire du bac ? Certainement, au moins pour ceux qui ne font pas de latin.&lt;/p&gt;
&lt;p&gt;Parce que combiner les deux peut donner des idées trop bizarres. Damian Conway par exemple en a été perturbé au point d&amp;rsquo;écrire un module
 définissant des alias latins pour tous les éléments du langage
, ce qui permet de rendre ce code :&lt;/p&gt;
\[code lang="perl"\]&lt;p&gt; use Lingua::Romana::Perligata; maximum inquementum tum biguttam egresso scribe. meo maximo vestibulo perlegamentum da. da duo tum maximum conscribementa meis listis. dum listis decapitamentum damentum nexto fac sic nextum tum novumversum scribe egresso. lista sic hoc recidementum nextum cis vannementa da listis. cis.&lt;/p&gt;
\[/code\]&lt;p&gt;parfaitement valide et absolument équivalent à celui-ci:&lt;/p&gt;
\[code lang="perl"\]&lt;p&gt; print STDOUT &amp;lsquo;maximum:&amp;rsquo;; my $maxim = ; my (@list) = (2..$maxim); while ($next = shift @list) { print STDOUT $next, &amp;ldquo;\n&amp;rdquo;; @list = grep {$_ % $next} @list; }&lt;/p&gt;
\[/code\]&lt;p&gt;Et si après
,  la programmation permettait de moderniser l&amp;rsquo;enseignement du latin ?&lt;/p&gt;
&lt;h3 id="notes"&gt;Notes:&lt;/h3&gt;
&lt;p&gt;* l’expression est de Jean-Pierre Archambault, président de
 (qui a un site très moche)&lt;/p&gt;
&lt;p&gt;** voilà bien la marque des pédagogues : surtout ne pas utiliser l&amp;rsquo;expression
&amp;rdquo; adopté par l&amp;rsquo;ensemble de la profession&amp;hellip; Ou alors la journaliste n&amp;rsquo;a pas vérifié&amp;hellip; (edit : c&amp;rsquo;est bien ça, Confirmé par anna Lietti&amp;hellip;)&lt;/p&gt;
&lt;h3 id="références"&gt;Références&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span id="ref-1"&gt;&lt;/span&gt;Anna Lietti &amp;ldquo;
&amp;rdquo; 2013, L&amp;rsquo;Hebdo No 34, p. 38-41&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-2"&gt;&lt;/span&gt;&lt;span class="openbook_template5"&gt;&lt;a href="http://openlibrary.org/authors/OL659735A/Jürg_Kohlas" title="Click to view author in Open Library" target="_blank" rel="noopener"&gt;Jürg Kohlas&lt;/a&gt;, &lt;a href="http://openlibrary.org/authors/OL7170750A/Jürg_Schmid" title="Click to view author in Open Library" target="_blank" rel="noopener"&gt;Jürg Schmid&lt;/a&gt;, &lt;a href="http://openlibrary.org/authors/OL3176585A/Carl_August_Zehnder" title="Click to view author in Open Library" target="_blank" rel="noopener"&gt;Carl August Zehnder&lt;/a&gt; (2013). &lt;a href="http://openlibrary.org/books/OL25430204M/informatique_gymnase" title="Click to view title in Open Library" target="_blank" rel="noopener"&gt;informatique@gymnase: Un projet pour la Suisse&lt;/a&gt;. NZZ Libro.&lt;span class="Z3988" title="ctx_ver=Z39.88-2004&amp;amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;amp;rft.genre=book&amp;amp;rft.btitle=informatique%40gymnase%3A+Un+projet+pour+la+Suisse&amp;amp;rft.isbn=9783038238232&amp;amp;rft.au=Ju%CC%88rg+Kohlas&amp;amp;rft.pub=NZZ+Libro&amp;amp;rft.date=2013"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; (
)&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-3"&gt;&lt;/span&gt;Steve Furber &amp;ldquo;
&amp;rdquo; January 2012, Royal Society&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-4"&gt;&lt;/span&gt;Académie des Sciences &amp;ldquo;
&amp;quot;, Rapport de l’Académie des sciences , Mai 2013&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-5"&gt;&lt;/span&gt;Jean-Pierre Archambault &amp;ldquo;
&amp;rdquo;, 2012, l&amp;rsquo;Etudiant&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-6"&gt;&lt;/span&gt;&amp;quot;
&amp;rdquo; 2011, Framablog (trouvé grâce à l&amp;rsquo;image du T-shirt)&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-7"&gt;&lt;/span&gt;Tyler Plack &amp;ldquo;
&amp;rdquo; (sur internet archive)
&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-8"&gt;&lt;/span&gt;Damian Conway, &amp;ldquo;
&amp;rdquo;, 2000, School of Computer Science and Software Engineering, Monash University (internet archive)&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>&amp;quot;jeu de l'année&amp;quot; 2012 et autres : c'est fini.</title><link>https://drgoulu.com/2012/01/18/jeu-de-lannee-2012-et-autres-cest-fini/</link><pubDate>Wed, 18 Jan 2012 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2012/01/18/jeu-de-lannee-2012-et-autres-cest-fini/</guid><description>&lt;p&gt;&lt;em&gt;(mis à jour plusieurs foirs après correction de bugs et améliorations, cf commentaires&amp;hellip;)&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;Je m’apprêtais à passer une soirée tranquille quand je suis tombé sur un tweet de
 disant: &amp;ldquo;Qui va me battre au &amp;ldquo;jeu de l&amp;rsquo;année&amp;rdquo; ? 
&amp;rdquo;.&lt;/p&gt;
&lt;figure class="alignright" style="max-width: 250px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2012/images/09a817e0eb516e6d72357bbf47b564a3_hu_dc589c41448b27fa.webp" srcset="https://drgoulu.com/posts/2012/images/09a817e0eb516e6d72357bbf47b564a3_hu_dc589c41448b27fa.webp 320w, https://drgoulu.com/posts/2012/images/09a817e0eb516e6d72357bbf47b564a3_hu_20b2c74f7bd203f9.webp 480w, https://drgoulu.com/posts/2012/images/09a817e0eb516e6d72357bbf47b564a3_hu_aa032b88a0192bd6.webp 500w" sizes="(max-width: 640px) 100vw, 250px" alt="Python bouffant du matheux" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;figcaption&gt;Python bouffant du matheux&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Un seul click m&amp;rsquo;a torpillé non pas une, mais trois soirées et un certain nombre d&amp;rsquo;heures de réflexion la journée. Mais ma vengeance est terrible : ni ElJj ni aucun autre mathématicien ne passera plus jamais des heures à former les entiers de 1 à 100 en n&amp;rsquo;utilisant que les chiffres de l&amp;rsquo;année (2,0,1,2) une et une seule fois chacun, les opérations de base +,-,*,/,^ et quelques autres. Fi-ni. Et c&amp;rsquo;est rapé aussi pour toutes les années futures ou passées, parce que j&amp;rsquo;ai fait un programme qui résout ce problème une fois pour toute. Amis
, je vous fais ci-dessous économiser des milliers d&amp;rsquo;heures que vous allez pouvoir utiliser pour résoudre de
 (Pensez à moi si vous en résolvez un, merci&amp;hellip;)&lt;/p&gt;
&lt;p&gt;Pour être honnête, la première soirée a été grillée à péniblement trouver 50 formules, ce qui m&amp;rsquo;a à la fois décidé à faire autrement et inspiré beaucoup de respect pour ElJj et les autres fous qui sont parvenus à obtenir des scores de 4000 et quelques points à la main. Bravo !&lt;/p&gt;
&lt;p&gt;Pour 2012, mes solutions sont donc : &lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;\[1, '(((2\*0)-1)^2)', 0\] \[2, '(((2-0)-1)\*2)', 0\] \[3, '(((2-0)-1)+2)', 0\] \[4, '(((2-0)^1)^2)', 0\] \[5, '(((2-0)+1)+2)', 0\] \[6, '(((2-0)+1)\*2)', 0\] \[7, '((2^0)+((1+2)!))', 0\] \[8, '(2^(0+(1+2)))', 0\] \[9, '(((2-0)+1)^2)', 0\] \[10, '((((2+0!)!)-1)\*2)', 0\] \[11, '(((2+0!)!)+(1/.2))', 1\] \[12, '((((2-0)+1)!)\*2)', 0\] \[13, '(2+sqrt((0!+((1/.2)!))))', 1\] \[14, '((((2+0!)!)+1)\*2)', 0\] \[15, '(((2-0)+1)/.2)', 1\] \[16, '(((2+0!)+1)^2)', 0\] \[17, '(((((2+0!)!)-1)!!)+2)', 5\] \[18, '(((2+0!)!)\*(1+2))', 0\] \[19, '((2^0)+(((1+2)!)!!!))', 5\] \[20, '(((2^0)/.1)\*2)', 1\] \[21, '(((((2+0!)!)!!!)+1)+2)', 5\] \[22, '((((2+0!)+1)!)-2)', 0\] \[23, '((.2^(-(0!+1)))-2)', 1\] \[24.0, '((((2-0)^1)^2)!)', 0\] \[25, '((((2+0!)!)-1)^2)', 0\] \[26, '((((2+0!)+1)!)+2)', 0\] \[27, '((2+0!)^(1+2))', 0\] \[28, '(((2+0!)/.1)-2)', 1\] \[29, '(((2+0!)/\[.1\])+2)&amp;rsquo;, 30] \[30, '((((2-0)+1)!)/.2)', 1\] \[31, '(((2+0!)/.1)+(Gamma(2)))', 31\] \[32, '(2^(-(0!-((1+2)!))))', 0\] \[33, '((((2+0!)!)!!)-((1/.2)!!))', 11\] \[34, '(sqrt((2^(0!/.1)))+2)', 1\] \[35, '((((2+0!)!)+1)/.2)', 1\] \[36, '((((2-0)+1)!)^2)', 0\] \[37, '(0!+(((1+2)!)^2))', 50\] \[38, '(((((2+0!)!)!!!)+1)\*2)', 5\] \[39, '(((.2^(-0!))!)-(\[.1\]^(-2)))&amp;rsquo;, 31] \[40, '(((2-0)/.1)\*2)', 1\] \[41, '(0!+(2/(.1/2)))', 51\] \[42, '((((2+0!)!)!!)-((1+2)!))', 5\] \[43, '((((2+0!)!)!!)-(1/.2))', 6\] \[44, '(-((.2-(0!/\[.1\]))/.2))&amp;rsquo;, 32] \[45, '(((((2+0!)!)!!)-1)-2)', 5\] \[46, '(((((2-0)+1)!)!!)-2)', 5\] \[47, '(((((2+0!)!)!!)+1)-2)', 5\] \[48, '((((2+0!)+1)!)\*2)', 0\] \[49, '((((2+0!)!)+1)^2)', 0\] \[50, '((.2^(-(0!+1)))\*2)', 1\]&lt;/th&gt;
&lt;th&gt;\[51, '((.2+(0!/.1))/.2)', 3\] \[52, '(2+(0!/(.1\*.2)))', 2\] \[53, '((((2+0!)!)!!)+(1/.2))', 6\] \[54, '((((2+0!)!)!!!)\*(1+2))', 5\] \[55, '(sqrt((((.2^(-0!))!)+1))/.2)', 2\] \[56, '(((((2+0!)!)+1)!!!)\*2)', 5\] \[57, '((((2+0!)!)!!)+sqrt((\[.1\]&lt;sup&gt;(-2))))&amp;rsquo;, 35] \[58, '((((2+0!)!)/.1)-2)', 1\] \[59, '((((2+0!)!)/.1)-(Gamma(2)))', 31\] \[60, '(((((2+0!)!)-1)!)/2)', 0\] \[61, '((((2+0!)!)/.1)+(Gamma(2)))', 31\] \[62, '((((2+0!)!)/.1)+2)', 1\] \[63, '((((2+0!)!)!!)+((1/.2)!!))', 11\] \[64, '(2^((0+(1+2))!))', 0\] \[65, '(0!+(2^((1+2)!)))', 50\] \[66, '((((2+0!)!)!!)+(((1+2)!)!!!))', 10\] \[67, '((((.2^(-0!))!!)-\[.1\])/\[.2\])&amp;rsquo;, 66] \[68, '(20+(((1+2)!)!!))', 15\] \[69, '((((0!+2)!)!!)+21)', 65\] \[70, '(((((2+0!)!)!)\*.1)-2)', 1\] \[71, 'sqrt((((((2+0!)!)+1)!)+(Gamma(2))))', 30\] \[72, 'sqrt((((((2+0!)!)!)\*.1)^2))', 1\] \[73, '(((((2+0!)!)!)\*.1)+(Gamma(2)))', 31\] \[74, '(((((2+0!)!)!)\*.1)+2)', 1\] \[75, '(((((2+0!)!)-1)!!)/.2)', 6\] \[76, '(-((.2^(-0!))-(\[.1\]&lt;/sup&gt;(-2))))&amp;rsquo;, 31] \[77, '((((2^2)!!)!!!)-sqrt((0!/\[.1\])))&amp;rsquo;, 90] \[78, '((((-2)+(0!/.1))!!!)-2)', 6\] \[79, '(-(2-(0!/(\[.1\]&lt;sup&gt;2))))&amp;rsquo;, 30] \[80, '(-((.2-0!)/(.1^2)))', 2\] \[81, '((((.2^(-0!))!!!)-1)^2)', 6\] \[82, '(2+(((0!/.1)-2)!!!))', 6\] \[83, '(2+(0!/(\[.1\]&lt;sup&gt;2)))&amp;rsquo;, 30] \[84, '((((.2^(-0!))!!!)!!!)\*(.1+.2))', 13\] \[85, '(((((2+0!)!)!!!)-1)/.2)', 6\] \[86, '((.2^(-0!))+(\[.1\]&lt;/sup&gt;(-2)))&amp;rsquo;, 31] \[87, '(((2+0!)!)+(\[.1\]&lt;/sup&gt;(-2)))&amp;rsquo;, 30] \[88, '(-((((2+0!)!)!)\*(.1-\[.2\])))&amp;rsquo;, 31] \[89, '(-((.2-((sqrt((0!/\[.1\]))!)!!!))/.2))&amp;rsquo;, 37] \[90, '(((((2-0)+1)!)!!!)/.2)', 6\] \[91, '(((.2^(-0!))!!!)+(\[.1\]^(-2)))&amp;rsquo;, 36] \[92, '(2\*(((sqrt((0!/\[.1\]))!)!!)-2))&amp;rsquo;, 35] \[93, '93', 500\] \[94, '(-(((2+0!)!)-(.1^(-2))))', 1\] \[95, '(-((.2^(-0!))-(.1^(-2))))', 2\] \[96, '(-((.2-0!)\*((1/.2)!)))', 2\] \[97, '(-(2+(0!-(.1^(-2)))))', 1\] \[98, '(-(2-(0!/(.1^2))))', 1\] \[99, '(-((2^0)-(.1^(-2))))', 1\] \[100, '(((2^0)/.1)^2)', 1\]&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;C&amp;rsquo;est un peu &amp;ldquo;brut de décoffrage&amp;rdquo; et mérite quelques explications. Chaque triplet comporte le nombre à obtenir, la &amp;ldquo;meilleure&amp;rdquo; formule qui le donne, et le coût de cette formule en points calculés selon les règles décrites dans l&amp;rsquo;article d&amp;rsquo;El Jj. Les formules qui utilisent les chiffres 2,0,1,2 dans l&amp;rsquo;ordre et les opérations arithmétiques de base et la factorielle (saviez-vous que 0!=1 ?) ont le coût minimum de 0. L&amp;rsquo;utilisation du point décimal bien utile avec une division ne coute qu&amp;rsquo;un point. Les formules qui utilisent des opérateurs plus compliqués comme les
(notées !! et !!!) et la
 sont pénalisées de 5 points.&lt;/p&gt;
&lt;p&gt;La formule pour 77 est la plus coûteuse (90 points) car elle utilise les chiffres dans le désordre (50 points), le développements décimal périodique &lt;/p&gt;
\[.1\]&lt;p&gt; = 0.11111111&amp;hellip; = 1/9 qui vaut 30 points chacun, plus deux multifactorielles. A noter que l&amp;rsquo;on a eu besoin d&amp;rsquo;inverser l&amp;rsquo;ordre des chiffres que dans 4 cas seulement.&lt;/p&gt;
&lt;p&gt;Et enfin, les nombre pour lesquels on ne trouve pas de solution sont pénalisés de 500 points, ce qui n&amp;rsquo;est le cas pour 93, pour lesquel je suis quasi certain qu&amp;rsquo;il n&amp;rsquo;existe pas de solution avec les opérations autorisées. Mais seulement &amp;ldquo;quasi&amp;rdquo;, pour des raisons que j&amp;rsquo;explique plus loin.&lt;/p&gt;
&lt;p&gt;Le total des pénalités que j&amp;rsquo;obtiens est de 1637 points&lt;/p&gt;
&lt;p&gt;Enfin, les formules ne sont pas très jolies d&amp;rsquo;une part à cause d&amp;rsquo;une &amp;ldquo;surparenthésation&amp;rdquo; qui simplifie l&amp;rsquo;écriture du programme (pas besoin de gérer la
), et d&amp;rsquo;autre part car le choix de la &amp;ldquo;meilleure&amp;rdquo; formule lorsqu&amp;rsquo;on en trouve plusieurs de score égal se fait par la longueur de la chaîne, sans tenir compte de l&amp;rsquo;ordre d&amp;rsquo;insertion ou de la priorité des opérateurs. Donc (((2*0)-1)^2) peut paraître plus compliqué que (((2*0)-1)+2) pour obtenir 1, mais pour une machine, c&amp;rsquo;est le même prix.&lt;/p&gt;
&lt;p&gt;Comme il se fait tard je coupe/colle le programme ci-dessous, je le commenterai plus tard (comme d&amp;rsquo;hab&amp;hellip;)&lt;/p&gt;
\[code lang="python" collapse="true"\]&lt;p&gt; # -*- coding: utf-8 -*- &amp;quot;&amp;quot;&amp;quot; Created on Mon Jan 16 17:19:27 2012&lt;/p&gt;
&lt;p&gt;@author: Philippe Guglielmetti solves
&amp;quot;&amp;quot;&amp;quot;&lt;/p&gt;
&lt;p&gt;import sys&lt;/p&gt;
&lt;p&gt;from math import sqrt,pow from scipy import factorial,factorial2,factorialk from itertools import permutations&lt;/p&gt;
&lt;p&gt;class f: &amp;ldquo;&amp;ldquo;&amp;ldquo;a formula&amp;rdquo;&amp;rdquo;&amp;rdquo; def __init__(self, m,p=0,v=None,parenthesis=False): #print m,&amp;rsquo;=&amp;rsquo;, self.isdigit=isinstance(m, (int, long)) self.math=str(m) #convert to string in case it&amp;rsquo;s a digit self.points=p if v is None: v=eval(self.math) self.isint=isinstance(v, (int,long)) if isinstance(v, float): #try to convert to int self.isint=abs(v-round(v))&amp;lt;1e-9 if self.isint: v=int(round(v)) if isinstance(v, long): #we don&amp;rsquo;t want bignums, for performance if abs(v)&amp;lt;sys.float_info.max: v=float(v) self.isint=True self.value=v&lt;/p&gt;
&lt;p&gt;if parenthesis: self.math=&amp;rsquo;(&amp;rsquo;+self.math+&amp;rsquo;)&amp;rsquo; #print self.value&lt;/p&gt;
&lt;p&gt;def __cmp__(self,other): if self.value&amp;lt;other.value:return -1 if self.value&amp;gt;other.value:return +1 if self.points&amp;lt;other.points:return -1 if self.points&amp;gt;other.points:return +1 if len(self.math)&amp;lt;len(other.math):return -1 if len(self.math)&amp;gt;len(other.math):return +1 return 0&lt;/p&gt;
&lt;p&gt;def __repr__(self): return str(&lt;/p&gt;
\[self.value,self.math,self.points\]&lt;p&gt;);&lt;/p&gt;
&lt;p&gt;class results(dict): &amp;ldquo;&amp;ldquo;&amp;ldquo;dictionary of formulas indexed by their result. we keep only the simplest entry for each result&amp;rdquo;&amp;rdquo;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;def __init__(self): dict.__init__(self)&lt;/p&gt;
&lt;p&gt;def add(self, f): if f.value in self.keys() and f&amp;gt;self&lt;/p&gt;
\[f.value\]&lt;p&gt; : pass else: self&lt;/p&gt;
\[f.value\]&lt;p&gt;=f&lt;/p&gt;
&lt;p&gt;def merge(self,d): for i in d.itervalues(): self.add(i)&lt;/p&gt;
&lt;p&gt;def score(self): return sum(map(lambda x: x.points,self.itervalues()))&lt;/p&gt;
&lt;p&gt;def notfound(self,p=500): return &lt;/p&gt;
\[i for (i,v) in self.iteritems() if v.points&gt;=p\]&lt;p&gt;def refine(self,recurse=2): &amp;ldquo;&amp;ldquo;&amp;ldquo;add combinations of monadic operators&amp;rdquo;&amp;rdquo;&amp;rdquo; r=results() for a in self.itervalues(): if recurse&lt;mark&gt;0 and a.value&amp;lt;&amp;gt;0: r.add(f(&amp;rsquo;-&amp;rsquo;+a.math,a.points,-a.value,True)) if a.isint: if a.value&lt;/mark&gt;0: r.add(f(a.math+&amp;rsquo;!&amp;rsquo;,a.points,1)) # 0! == 1 is very useful&amp;hellip; if a.value&amp;gt;1: s=f(&amp;lsquo;sqrt(&amp;rsquo;+a.math+&amp;quot;)&amp;quot;,a.points,sqrt(a.value)) if s.isint: r.add(s) if a.value&amp;gt;1 and a.value&amp;lt;19: r.add(f(a.math+&amp;rsquo;!&amp;rsquo;,a.points,factorial(int(a.value),True),True)) r.add(f(&amp;lsquo;Gamma(&amp;rsquo;+a.math+&amp;rsquo;)&amp;rsquo;,a.points+30,factorial(int(a.value)-1,True),True)) if a.value&amp;gt;3 and a.value&amp;lt;29: r.add(f(a.math+&amp;rsquo;!!&amp;rsquo;,a.points+5,factorial2(int(a.value),True),True)) if a.value&amp;gt;4 and a.value&amp;lt;39: r.add(f(a.math+&amp;rsquo;!!!&amp;rsquo;,a.points+5,factorialk(int(a.value),3,True),True)) self.merge(r) if recurse&amp;gt;0: self.refine(recurse-1)&lt;/p&gt;
&lt;p&gt;class monadic(results): &amp;ldquo;&amp;ldquo;&amp;ldquo;combinations of monadic operators around a formula&amp;rdquo;&amp;rdquo;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;def __init__(self, a): results.__init__(self) self.add(a) if a.value!=0: if a.isdigit: self.add(f(&amp;rsquo;.&amp;rsquo;+a.math,a.points+1)) if a.value&amp;lt;10: self.add(f(&amp;rsquo;&lt;/p&gt;
\[.'+a.math+'\]&lt;p&gt;&amp;rsquo;,a.points+30,a.value/9.)) self.refine();&lt;/p&gt;
&lt;p&gt;class diadic(results): &amp;ldquo;&amp;ldquo;&amp;ldquo;combinations of diadic operators of 2 operands&amp;rdquo;&amp;rdquo;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;def __init__(self, a,b): results.__init__(self) for i in a.itervalues(): for j in b.itervalues(): if i.isdigit and j.isdigit: if i.value!=0: self.add(f(int(i.math+j.math),10)) self.add(f(i.math+&amp;rsquo;.&amp;rsquo;+j.math,11)) self.add(f(i.math+&amp;rsquo;+&amp;rsquo;+j.math,i.points+j.points,i.value+j.value,True)) self.add(f(i.math+&amp;rsquo;-&amp;rsquo;+j.math,i.points+j.points,i.value-j.value,True)) self.add(f(i.math+&amp;rsquo;*&amp;rsquo;+j.math,i.points+j.points,i.value*j.value,True)) if j.value!=0: self.add(f(i.math+&amp;rsquo;/&amp;rsquo;+j.math,i.points+j.points,float(i.value)/float(j.value),True)) try: #so many things can go wrong with next line&amp;hellip; self.add(f(i.math+&amp;rsquo;^&amp;rsquo;+j.math,i.points+j.points,pow(i.value,j.value),True)) except: pass if i.isint: try: #so many things can go wrong with next line&amp;hellip; self.add(f(&amp;lsquo;root(&amp;rsquo;+i.math+&amp;rsquo;,&amp;rsquo;+j.math+&amp;rsquo;)&amp;rsquo;,i.points+j.points+5,pow(j.value,1./i.value),True)) except: pass if i.isint and j.isint and i.value&amp;gt;=0 and j.value&amp;gt;0 and i.value/j.value&amp;lt;10: try: #so many things can go wrong with next line&amp;hellip; self.add(f(i.math+&amp;rsquo;!&amp;rsquo;+j.math,i.points+j.points+5,factorialk(i.value,j.value),True)) except: pass&lt;/p&gt;
&lt;p&gt;self.refine();&lt;/p&gt;
&lt;p&gt;print &amp;lsquo;building list of monadics&amp;rsquo; m=map(monadic,map(f,range(0,10))) #list of all monadics of digits&lt;/p&gt;
&lt;p&gt;#use @Memoized here to improve performance def d(a,b): return diadic(a,b)&lt;/p&gt;
&lt;p&gt;def year(n,display=True,verbose=True): solution=results() for i in range(1,101): solution.add(f(i,500))&lt;/p&gt;
&lt;p&gt;def addresults(a,p): if verbose : print &amp;lsquo;formulas&amp;rsquo;,len(a), improved=0 found=0 for (i,v) in a.items(): if isinstance(i, (int, long)) and i&amp;gt;0 and i&amp;lt;101: v.points+=p if v&amp;lt;solution&lt;/p&gt;
\[i\]&lt;p&gt;: if solution&lt;/p&gt;
\[i\]&lt;p&gt;.points==500: found+=1 else: improved+=1 solution&lt;/p&gt;
\[i\]&lt;p&gt;=v if verbose: print(&amp;lsquo;found :&amp;rsquo;+str(found)+&amp;rsquo; improved :&amp;rsquo;+str(improved)+&amp;rsquo; score:&amp;rsquo;+str(solution.score()))&lt;/p&gt;
&lt;p&gt;def combine (a,p): m0=m&lt;/p&gt;
\[a\[0\]&lt;p&gt;]; m1=m&lt;/p&gt;
\[a\[1\]&lt;p&gt;]; m2=m&lt;/p&gt;
\[a\[2\]&lt;p&gt;]; m3=m&lt;/p&gt;
\[a\[3\]&lt;p&gt;] if solution.notfound():addresults(d(d(d(m0,m1),m2),m3),p) if solution.notfound():addresults(d(d(m0,d(m1,m2)),m3),p) if solution.notfound():addresults(d(m0,d(m1,d(m2,m3))),p) if solution.notfound():addresults(d(m0,d(d(m1,m2),m3)),p) if solution.notfound():addresults(d(d(m0,m1),d(m2,m3)),p)&lt;/p&gt;
&lt;p&gt;y=&lt;/p&gt;
\[int(i) for i in str(n)\]&lt;p&gt; combine(y,0) y.sort() for i in permutations(y): combine(i,50)&lt;/p&gt;
&lt;p&gt;if display: for i in solution.itervalues():print i print n,solution.score(),solution.notfound()&lt;/p&gt;
&lt;p&gt;year(2012) &lt;/p&gt;
\[/code\]</description></item><item><title>Pavages aléatoires</title><link>https://drgoulu.com/2011/10/03/pavages-aleatoires/</link><pubDate>Mon, 03 Oct 2011 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2011/10/03/pavages-aleatoires/</guid><description>&lt;p&gt;Il devient de plus en plus difficile de choisir un carrelage original pour sa salle de bains.&lt;/p&gt;
&lt;p&gt;Depuis le XVème siècle, 17 types de
 réguliers différents sont utilisés dans les décorations de l&amp;rsquo;
. En 1891, le mathématicien russe Evgraf Fedorov démontre que le nombre de pavages réguliers distincts  vaut &amp;hellip; 17
.  Et ce n&amp;rsquo;est qu&amp;rsquo;entre 1968 et 1984 qu&amp;rsquo;on parvient à classifier toutes les formes de pavés possibles en 19 catégories
. Depuis, les carreleurs ne peuvent se distinguer que par des motifs et des couleurs, plus par la géométrie.&lt;/p&gt;
&lt;p&gt;En 1974, le
crée un choc : il est possible de recouvrir le plan avec des pavés de deux formes différentes arrangés selon des règles rigoureuses, mais ne générant pas de motif périodique. En 1994, Radin et Conway en proposent un autre, le &amp;ldquo;
&amp;rdquo;. Voilà pour le XXème siècle.&lt;/p&gt;
&lt;p&gt;En 2011, c&amp;rsquo;est John Shier, un &amp;ldquo;artiste algorithmique&amp;rdquo; qui vient d&amp;rsquo;ouvrir tout grand la porte à une infinité de nouveaux pavages. Sa méthode permettent de couvrir le plan avec des pavés de presque n&amp;rsquo;importe quelles formes, mais de surface décroissantes
,
. Le principe semble tout simple : on place le plus grand pavé au hasard, puis le suivant en taille au hasard dans une surface libre et ainsi de suite.&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 420px; width: 100%;"&gt;&lt;a href="http://john-art.com/stat_geom.html" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2011/images/400fcf9e5415a8d1b3b559ecdffe0c43_hu_9da502ea25a62906.webp" srcset="https://drgoulu.com/posts/2011/images/400fcf9e5415a8d1b3b559ecdffe0c43_hu_9da502ea25a62906.webp 320w, https://drgoulu.com/posts/2011/images/400fcf9e5415a8d1b3b559ecdffe0c43_hu_bda96f5d30bf8c8.webp 480w, https://drgoulu.com/posts/2011/images/400fcf9e5415a8d1b3b559ecdffe0c43_hu_456ef22a8d18723d.webp 760w" sizes="(max-width: 640px) 100vw, 420px" alt="Le pavage de John Shier le plus simple" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;Le pavage de John Shier le plus simple&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Le problème est que si on réduit la taille des pavés trop vite on ne recouvre pas tout le plan, et si on réduit trop lentement, on risque d&amp;rsquo;être &amp;ldquo;coincé&amp;rdquo; à ne pas pouvoir placer un pavé. L&amp;rsquo;astuce consiste à attribuer au i-ème pavé une surface de A0/ic. Dans ce cas, la surface totale vaut :&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
\[mathjax\]$$A_{total}=A_{0}\sum_{i=0}^{\infty}i^{-c}$$&lt;p&gt;On reconnait en passant la
, qui converge pour c&amp;gt;1. Grâce à cette formule, une fois choisi un c, la formule permet de calculer la surface A0 qui garantit qu&amp;rsquo;il ne restera plus un seul espace libre après avoir placé une infinité de pavés. En pratique on obtient d&amp;rsquo;excellent remplissages avec quelques milliers de pavés, un peu de patience et un bon programme. Paul Bourke décrit tout ceci en détail sur une page
agrémentée de magnifiques exemples:&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;Il a même étendu la méthode à la 3D :&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;Pour ma part, j&amp;rsquo;ai réalisé la petite application ci-dessous en
 (disponible aussi
 avec son code source) pour expérimenter un peu cet algorithme que je trouve spectaculaire:&lt;/p&gt;
&lt;hr&gt;
\[processing sketch="RandomTiling"\]&lt;hr&gt;
&lt;p&gt;En pressant sur les touches 0,1,3,4,5,6 vous pouvez changer la forme des pavés à la volée, et la touche espace relance un pavage. Contrairement à Shier et Bourke, je ne pave pas un tore mais un rectangle, en prenant garde à ce que les pavés ne soient pas &amp;ldquo;coupés&amp;rdquo; par les bords. En plus je me suis amusé à implémenter les pavés en forme d&amp;rsquo;étoiles, en prévision d&amp;rsquo;une carte de Noël. Mignon, n&amp;rsquo;est-ce pas ? Bon, il reste pas mal de noir car la détection d&amp;rsquo;intersection entre étoiles est très lente, il faudrait améliorer ça.&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 600px; width: 100%;"&gt;&lt;a href="images/ee578774ff1f481e54dd991d9e1d7b9e.png" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2011/images/ee578774ff1f481e54dd991d9e1d7b9e_hu_e7ff54c0d05d293e.webp" srcset="https://drgoulu.com/posts/2011/images/ee578774ff1f481e54dd991d9e1d7b9e_hu_e7ff54c0d05d293e.webp 320w, https://drgoulu.com/posts/2011/images/ee578774ff1f481e54dd991d9e1d7b9e_hu_f815510c03a744e0.webp 480w, https://drgoulu.com/posts/2011/images/ee578774ff1f481e54dd991d9e1d7b9e_hu_4a9d5bbaaa2791b.webp 640w" sizes="(max-width: 640px) 100vw, 600px" alt="stars" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;Géantes rouges et naines bleues&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;em&gt;ajout du 8/10/11&lt;/em&gt; : j&amp;rsquo;ai présenté hier un 
 décrivant la conception de ce programme.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;edit du 20/9/13&lt;/em&gt; : l&amp;rsquo;applet utilise maintenant Processing.js : drgoulu.com n&amp;rsquo;a plus besoin de Java !&lt;/p&gt;
&lt;p&gt;Il y a encore (ou déjà&amp;hellip;) 2 bugs connus, si ça vous dit de vous y mettre :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;le pavage bloque parfois, surtout avec les triangles ou étoiles, il faut que j&amp;rsquo;ajoute un moyen d&amp;rsquo;ajuster la constante c&amp;hellip;&lt;/li&gt;
&lt;li&gt;des intersections entre cercles et polygones subsistent. Normal, j&amp;rsquo;ai eu la flemme d&amp;rsquo;implanter ça.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Une autre amélioration intéressante serait de remplir l&amp;rsquo;intérieur des pavés avec d&amp;rsquo;autres pavés&amp;hellip;&lt;/p&gt;
&lt;h3 id="références"&gt;Références:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span id="ref-1"&gt;&lt;/span&gt;Thérèse Eveilleau
&amp;rdquo; avec animations flash&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-2"&gt;&lt;/span&gt;Xavier Hubaut &amp;ldquo;
&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-3"&gt;&lt;/span&gt;John Shier &amp;ldquo;
&amp;quot;, Hyperseeing, summer 2011 issue, pp. 131-140, published by ISAMA (International Society of the Arts, Mathematics, and Architecture).&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-4"&gt;&lt;/span&gt;John Shier &amp;ldquo;
&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-5"&gt;&lt;/span&gt;Paul Bourke &amp;ldquo;
&amp;quot;, July 2011&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Le &amp;quot;Sleep sort&amp;quot;</title><link>https://drgoulu.com/2011/06/19/le-sleep-sort/</link><pubDate>Sun, 19 Jun 2011 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2011/06/19/le-sleep-sort/</guid><description>&lt;p&gt;Tout a commencé* par un
: un anonyme propose un algorithme de tri en 2 lignes de code
:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;function f() {sleep &amp;quot;$1&amp;quot; echo &amp;quot;$1&amp;quot;} while [ -n &amp;quot;$1&amp;quot; ] do f &amp;quot;$1&amp;quot; &amp;amp; shift done wait&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Lorsqu&amp;rsquo;il est appelé avec une liste de N nombres comme dans &lt;code&gt;./sleepsort.bash 5 3 6 3 6 3 1 4 7 ,&lt;/code&gt; ce code lance un processus pour chacun des nombres n. Chaque processus effectue la fonction f, qui utilise la fonction
pour attendre n secondes avant d&amp;rsquo;afficher le nombre n. Dans l&amp;rsquo;exemple, le 7ème processus n&amp;rsquo;attendra qu&amp;rsquo;une seconde avant d&amp;rsquo;afficher &amp;ldquo;1&amp;rdquo;, le 4ème et le 6ème attendront 3 secondes avant d&amp;rsquo;afficher &amp;ldquo;3&amp;rdquo; dans un ordre qui n&amp;rsquo;a aucune importance et ainsi de suite jusqu&amp;rsquo;au dernier processus qui affichera &amp;ldquo;7&amp;rdquo; après 7 secondes. L&amp;rsquo;utilisateur verra ainsi s&amp;rsquo;afficher progressivement les N nombres triés dans l&amp;rsquo;ordre croissant.&lt;/p&gt;
&lt;p&gt;Depuis ce message on voit des implémentations de &amp;ldquo;Sleep sort&amp;rdquo; fleurir dans
programmation en utilisant
, et des
, anglophones surtout pour l&amp;rsquo;instant.&lt;/p&gt;
&lt;p&gt;Prétextant que ce programme mettrait plus de 11 jours à trier les deux nombres 1000000 et 673, certains considèrent le &amp;ldquo;sleep sort&amp;rdquo; comme un bon gag, ce qu&amp;rsquo;il est certainement à l&amp;rsquo;origine. Pour ma part j&amp;rsquo;ai 
de la 
. Voici pourquoi.&lt;/p&gt;
&lt;p&gt;D&amp;rsquo;abord, ce code est simple et fait l&amp;rsquo;éloge d&amp;rsquo;une grande qualité du programmeur : la paresse. Faire quelque chose d&amp;rsquo;utile simplement en attendant, quoi de plus beau ? A ce titre il mérite amplement sa place à côté du 
dont 
en français, du
ou des 
et 
sans intérêt, mais qui ont leur page Wikipédia.&lt;/p&gt;
&lt;figure class="alignright" style="max-width: 240px; width: 100%;"&gt;&lt;a href="http://www.flickr.com/photos/30271386@N04/3016524792/in/photostream/" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2011/images/3016524792_cdb7edf4c8_m-1_hu_3d3e671f745d1e2e.webp" srcset="https://drgoulu.com/posts/2011/images/3016524792_cdb7edf4c8_m-1_hu_3d3e671f745d1e2e.webp 240w" sizes="(max-width: 640px) 100vw, 240px" alt="Photo par Eben Regis sur flickr" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;Photo par Eben Regis sur flickr&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Plus sérieusement, &amp;ldquo;Sleep sort&amp;rdquo; exploite de manière active l&amp;rsquo;écoulement du temps au lieu de le subir, ce qui est déjà intéressant en soi, mais pose également des questions intéressantes sur la
.&lt;/p&gt;
&lt;p&gt;Car le &amp;ldquo;génie&amp;rdquo; de cet algorithme, s&amp;rsquo;il vous avait échappé, est qu&amp;rsquo;il prend en apparence un temps proportionnel à max(n), le plus grand des nombres à trier, pour s&amp;rsquo;exécuter, plus un temps proportionnel à N pour créer les processus. Or les 
existants prennent un temps proportionnel à N.log(N). Il pourrait donc exister des cas où le &amp;ldquo;sleep sort&amp;rdquo; serait plus rapide. Mais est-ce vraiment le cas ?&lt;/p&gt;
&lt;p&gt;Traitons d&amp;rsquo;abord de la partie la plus perceptible du temps d&amp;rsquo;exécution, l&amp;rsquo;attente de max(n) secondes. Sur les machines actuelles,
, et on pourrait probablement passer aux microsecondes. En fait il faut simplement garantir que deux processus associés à deux nombres x et x+1 se réveillent dans le bon ordre et aient le temps de produire leur sortie sans perturber le réveil des processus suivants. Déjà ceci soulève plein de problèmes intéressants au niveau des systèmes d&amp;rsquo;exploitation, de l&amp;rsquo;accès aux ressources critiques etc. Mais quelles que soient les solutions techniques, il reste qu&amp;rsquo;on ne sait pas bien exprimer théoriquement la complexité d&amp;rsquo;un tel algorithme : en principe, une durée d&amp;rsquo;exécution proportionnelle à l&amp;rsquo;une des données conduit à une complexité O(1) supposée largement inférieure à O(N), ce qui n&amp;rsquo;est pas le cas en pratique ici.&lt;/p&gt;
&lt;p&gt;Ensuite la partie &amp;ldquo;proportionnelle à N&amp;rdquo; dans laquelle on crée les N processus est elle vraiment O(N) ? En principe oui, mais il existe une partie invisible : la gestion interne de la fonction système &amp;ldquo;sleep&amp;rdquo;. Dans tous les systèmes d&amp;rsquo;exploitation que je connais (au moins deux&amp;hellip;), &amp;ldquo;sleep&amp;rdquo; provoque l&amp;rsquo;insertion du processus dans une liste de tous les processus suspendus en attente de l&amp;rsquo;échéance d&amp;rsquo;un certain temps. Et pour éviter de parcourir toute la liste à chaque interruption du timer pour trouver quels processus doivent être réveillés, on la maintient triée dans l&amp;rsquo;ordre des réveils programmés. &amp;ldquo;Triée&amp;rdquo; ? Et oui&amp;hellip; : à chaque instruction &amp;ldquo;sleep&amp;rdquo;, rencontrée le processus est inséré au bon endroit. &amp;ldquo;Inséré&amp;rdquo; ? Et re-oui&amp;hellip; : l&amp;rsquo;exécution des N &amp;ldquo;sleep&amp;rdquo; revient à un &amp;ldquo;
&amp;rdquo;, d&amp;rsquo;une complexité O(N²) rédhibitoire.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Sleep sort&amp;rdquo; n&amp;rsquo;est donc pas un tri linéaire, du moins sur un ordinateur ayant beaucoup moins de N processeurs. Mais il soulève plein de questions intéressantes sur les algorithmes, les systèmes d&amp;rsquo;exploitation, l&amp;rsquo;architecture des ordinateurs et la psychologie des programmeurs.
!&lt;/p&gt;
&lt;p&gt;Note* : en fait l&amp;rsquo;idée est plus ancienne comme le montre ce post &amp;ldquo;
&amp;rdquo; datant de 2006&lt;/p&gt;</description></item><item><title>les décorateurs, ou pourquoi j'aime toujours la programmation</title><link>https://drgoulu.com/2010/12/04/les-decorateurs-python/</link><pubDate>Sat, 04 Dec 2010 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2010/12/04/les-decorateurs-python/</guid><description>&lt;p&gt;Je programme des ordinateurs depuis 30 ans, et tous les 5 ans environ je me demande pourquoi je continue à aimer ça. Et à chaque fois je découvre quelque chose qui provoque un &amp;ldquo;éclair haha&amp;rdquo;, une de ces illuminations cérébrales où l&amp;rsquo;on entrevoit le Génie dans toute sa Pureté avant de retomber sur sa chaise motivé pour les 5 ans suivants.&lt;/p&gt;
&lt;p&gt;Le dernier a été provoqué cette semaine par les &amp;ldquo;décorateurs&amp;rdquo; de Python, dont je vous parlerai plus bas.&lt;/p&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2010/images/1e6c2b5ad4fd77ee9c967945b326090c_hu_e001748075368d38.webp 320w, https://drgoulu.com/posts/2010/images/1e6c2b5ad4fd77ee9c967945b326090c_hu_a064c69313869d17.webp 350w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2010/images/1e6c2b5ad4fd77ee9c967945b326090c_hu_e001748075368d38.webp"
width="350"
height="311"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
Ma première extase informatique date donc de 1980 environ, je m&amp;rsquo;en souviens comme si c&amp;rsquo;était hier. Mon
2001 se programmait en BASIC, un langage qu&amp;rsquo;on a bien fait d&amp;rsquo;oublier. Mais une astuce (ou plutôt une horreur) sur le PET permettait de faire en sorte que le programme s&amp;rsquo;ajoute des lignes de programme à lui-même ! J&amp;rsquo;avais ainsi modifié le jeu &amp;ldquo;
&amp;rdquo; de
pour qu&amp;rsquo;il &amp;ldquo;apprenne&amp;rdquo; de nouveaux animaux de façon permanente. Un programme qui s&amp;rsquo;améliore lui-même, ça me fait encore rêver, 30 ans après&amp;hellip;&lt;/p&gt;
&lt;p&gt;Le second flash date de 1985, la grande époque de
. Un jour j&amp;rsquo;ai vu quelque chose comme ça:&lt;/p&gt;
\[pascal\]&lt;p&gt;function factorielle(n: integer): integer; begin if n &amp;lt;= 1 then result := 1 else result := n*factorielle(n-1); end;&lt;/p&gt;
\[/pascal\]&lt;p&gt;Une fonction qui s&amp;rsquo;appelle elle même ! Merveilleuse
, chaque fois que je te revois, je me rappelle mon émoi à notre première rencontre.&lt;/p&gt;
&lt;p&gt;Les années 1990 sont riches en &amp;ldquo;haha&amp;quot;s plus rapprochés mais moins intenses pendant mes études à l&amp;rsquo;EPFL : la
 en LISP, le moteur d&amp;rsquo;inférence de
,  la
 en d&amp;rsquo;ADA, qui semblait à l&amp;rsquo;époque bien plus importante que la programmation orientée objet, juste entrevue.  Et
, précurseur de la programmation parallèle trop tôt disparu.&lt;/p&gt;
&lt;p&gt;Un peu avant 1995, je découvre
et le flash se produit lorsque je comprends que c&amp;rsquo;est un véritable langage de programmation complet&amp;hellip; sans code ! Ou plus exactement que le langage graphique de LabView permet de programmer directement au niveau sémantique. Adieu &amp;ldquo;syntax error&amp;rdquo; ! Quel dommage que
vende cette merveille si cher et l&amp;rsquo;aie blindé de brevets défendus avec vigueur : un des concepts les plus innovants en programmation reste confiné à un cercle d&amp;rsquo;initiés alors qu&amp;rsquo;il aurait pu révolutionner l&amp;rsquo;informatique.&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 821px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2010/images/f364f53ba469dc47f8253d2c53b9d310_hu_686879f385f928bd.webp" srcset="https://drgoulu.com/posts/2010/images/f364f53ba469dc47f8253d2c53b9d310_hu_686879f385f928bd.webp 320w, https://drgoulu.com/posts/2010/images/f364f53ba469dc47f8253d2c53b9d310_hu_2452d5fa1fbd9acd.webp 480w, https://drgoulu.com/posts/2010/images/f364f53ba469dc47f8253d2c53b9d310_hu_379f97455f41ee57.webp 760w" sizes="(max-width: 640px) 100vw, 821px" alt="un programme LabView avec blocs concurrents, boucles, tests etc." loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;figcaption&gt;un &amp;quot;programme&amp;quot; LabView avec blocs concurrents, boucles, tests etc.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Vers 2000, je constate qu&amp;rsquo;on m&amp;rsquo;avait menti : C++ est beaucoup plus qu&amp;rsquo;un C amélioré. C&amp;rsquo;est un grand festival de &amp;ldquo;haha&amp;rdquo; en quelques jours : les
, la
, l&amp;rsquo;
, la
, les
, le
, mais surtout la
(STL). Java et .NET ont des librairies de classes et fonctions à tout faire, mais C++ a une &amp;ldquo;méta-librairie&amp;rdquo;, un système qui produit du code très optimisé pour chaque opération spécifique, en utilisant notamment le concept d&amp;rsquo;
.&lt;/p&gt;
&lt;p&gt;En 2005, je lis &lt;span class="openbook_template5"&gt;&lt;a href="http://openlibrary.org/authors/OL2670915A/Andrei_Alexandrescu" title="Click to view author in Open Library" target="_blank" rel="noopener"&gt;Andrei Alexandrescu&lt;/a&gt; (2001). &lt;a href="http://openlibrary.org/books/OL22119374M/Modern_C_plus_plus_design" title="Click to view title in Open Library" target="_blank" rel="noopener"&gt;Modern C [plus plus] design: generic programming and design patterns applied&lt;/a&gt;. Addison-Wesley.&lt;span class="Z3988" title="ctx_ver=Z39.88-2004&amp;amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;amp;rft.genre=book&amp;amp;rft.btitle=Modern+C+%5Bplus+plus%5D+design%3A+generic+programming+and+design+patterns+applied&amp;amp;rft.isbn=0201704315&amp;amp;rft.au=Andrei+Alexandrescu&amp;amp;rft.pub=Addison-Wesley&amp;amp;rft.date=2001"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;. Flash d&amp;rsquo;illumination : c&amp;rsquo;est génial, mais j&amp;rsquo;ai pas tout compris. Je le relis: re-flash: c&amp;rsquo;est encore plus génial que je pensais. Je le lis une troisième fois (à part &amp;ldquo;Les Robots&amp;rdquo; d&amp;rsquo;Asimov je n&amp;rsquo;ai jamais lu un livre 3 fois) : ça y&amp;rsquo;est je suis converti au &amp;ldquo;
&amp;rdquo;, une approche révolutionnaire de la programmation autorisée par une exploitation transcendantale de la combinaison C++, STL, et #macros. Les C++istes trouveront un petit
qui les convaincra à la fois de la puissance de cette approche, et de sa lourdeur d&amp;rsquo;écriture&amp;hellip;&lt;/p&gt;
&lt;p&gt;Et nous voici donc en 2010 où, poursuivant
, je tombe sur ça:&lt;/p&gt;
\[python\]&lt;p&gt;@cache() def fib(n): if n &amp;lt; 2: return 1 return fib(n-1) + fib(n-2)&lt;/p&gt;
\[/python\]&lt;p&gt;Même ceux qui ne parlent pas Python reconnaîtront une fonction récursive calculant le n-ième terme de la suite de Fibonacci, mais il y a une astuce : le @cache().&lt;/p&gt;
&lt;p&gt;Ca s&amp;rsquo;appelle un &amp;ldquo;décorateur&amp;rdquo; et en l’occurrence, le @cache() ajoute un comportement de
 (déjà mentionné
) à la fonction : si on appelle la fonction fib pour un n déjà calculé précédemment, le @cache() va renvoyer le résultat mémorisé avec un gain de vitesse appréciable plutôt que de recalculer la fonction, et ceci sans rien changer à la fonction elle-même!&lt;/p&gt;
&lt;p&gt;Et bien sur, le décorateur est lui-même écrit en Python : c&amp;rsquo;est
, et c&amp;rsquo;est une version simplifiée d&amp;rsquo;un
avec la librairie Python. Une
très variés est en train de naître (voyez par exemple les
, chers collègues&amp;hellip;), mais il me semble que les décorateurs permettent surtout de réaliser des choses ressemblant beaucoup aux &amp;ldquo;politiques&amp;rdquo; d&amp;rsquo;Alexandrescu avec une syntaxe plus simple qu&amp;rsquo;en C++. (Pythonistes, voyez 
)&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est pour cela que j&amp;rsquo;aime toujours la programmation : les langages gagnent en pouvoir d&amp;rsquo;abstraction en même temps que moi, et vice-versa. Chaque fois que je programme dans un nouveau langage, tout est plus simple, plus clair et plus vite juste que dans le précédent, et, luxe suprême,  je dois presser moins de touches. Les ordinateurs sont restés des esclaves qui camouflent leur stupidité derrière une vitesse stupéfiante, mais les concepteurs de langages, eux sont devenus vraiment malins. Merci
, grâce à toi j&amp;rsquo;en reprends pour 5 ans.&lt;/p&gt;</description></item><item><title>Calculateur d&amp;#039;(in)égalité</title><link>https://drgoulu.com/2009/10/11/calculateur-dinegalite/</link><pubDate>Sun, 11 Oct 2009 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2009/10/11/calculateur-dinegalite/</guid><description>&lt;p&gt;Les inégalités de revenu sont un sujet d&amp;rsquo;actualité politique brûlant. En Suisse, les
viennent de lancer une initiative populaire visant à limiter le salaire maximal dans les entreprises à 12 fois le salaire minimal.Dans une petite boite c&amp;rsquo;est presque toujours le cas, mais plus on travaille dans une grande entreprise, plus on aimerait gagner en une année ce que gagne notre CEO en un mois&amp;hellip;&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est le problème du rapport max/min : il ne tient pas compte de tous les revenus intermédiaires. Dans une entreprise de 100 personnes, 98% des salaires sont compris entre celui du patron et celui de la technicienne de surface. Comment mesurer les inégalités de revenu en tenant compte de tous les revenus d&amp;rsquo;une société ?&lt;/p&gt;
&lt;p&gt;La mesure d&amp;rsquo;(in)égalité des revenus la plus utilisée au niveau international s&amp;rsquo;appelle &amp;ldquo;coefficient (ou indice) de Gini&amp;rdquo;. J&amp;rsquo;en ai déjà parlé dans
. L&amp;rsquo;indice de Gini vaut 0 si les revenus d&amp;rsquo;une société sont divisées de façon parfaitement égale, et 1 (ou 100%) si un seul esclavagiste empoche la totalité du revenu. En pratique, l&amp;rsquo;indice de Gini de la plupart des pays membre de l&amp;rsquo;OCDE se situe entre 0.5 et 0.4, mais les impôts réduisent les inégalités pour obtenir un Gini du revenu disponible entre 0.25 et 0.35 .&lt;/p&gt;
&lt;p&gt;Le coefficient de Gini pourrait facilement être utilisé au niveau des entreprises. J&amp;rsquo;ai d&amp;rsquo;ailleurs créé une
permettant de le calculer en ligne pour des entreprises de moins de 100 personnes*. C&amp;rsquo;est tout simple : copiez/coller les montants des salaires de votre entreprise dans la première colonne, triez-la dans l&amp;rsquo;ordre croissant, et voilà !&lt;/p&gt;
&lt;p&gt;Le petit graphique associé (dont il faut changer l&amp;rsquo;échelle horizontale à la main au besoin) trace en bleu la
qui montre la progressivité des revenus. L&amp;rsquo;indice de Gini est défini par la fraction de la surface entre la courbe bleue et la droite rouge par la surface sous la droite rouge.&lt;/p&gt;
&lt;p&gt;En jouant avec cet outil, vous constaterez que l&amp;rsquo;initiative &amp;ldquo;1:12&amp;rdquo; des jeunesses socialistes n&amp;rsquo;implique pas du tout une distribution équitable des revenus. Comme le montrent les cas extrêmes ci-dessous, le coefficient de Gini peut varier énormément même si le salaire le plus élevé vaut 12x le salaire minimal:&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 454px; width: 100%;"&gt;&lt;a href="https://drgoulu.com/wp-content/uploads/HLIC/f2cec9deffecb61c69a24e0fa13bb3b7.png" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2009/images/f2cec9deffecb61c69a24e0fa13bb3b7_hu_84cdf33c8a4fb06f.webp" srcset="https://drgoulu.com/posts/2009/images/f2cec9deffecb61c69a24e0fa13bb3b7_hu_84cdf33c8a4fb06f.webp 320w, https://drgoulu.com/posts/2009/images/f2cec9deffecb61c69a24e0fa13bb3b7_hu_5744b58f49c3851b.webp 454w" sizes="(max-width: 640px) 100vw, 454px" alt="Lorenz 1-12-1" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;société de 10 personnes ou les 9 employés ont un salaire égal et le patron un revenu 12 fois supérieur. Indice de Gini = 0.52&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure class="aligncenter" style="max-width: 455px; width: 100%;"&gt;&lt;a href="https://drgoulu.com/wp-content/uploads/HLIC/c69c69aa7491ec6b0c8d49f93197af76.png" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2009/images/c69c69aa7491ec6b0c8d49f93197af76_hu_ded2ebe0e12f8484.webp" srcset="https://drgoulu.com/posts/2009/images/c69c69aa7491ec6b0c8d49f93197af76_hu_ded2ebe0e12f8484.webp 320w, https://drgoulu.com/posts/2009/images/c69c69aa7491ec6b0c8d49f93197af76_hu_c920838fadd08f2a.webp 455w" sizes="(max-width: 640px) 100vw, 455px" alt="Lorenz 1-12-2" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;société de 10 personnes ou 9 cadres ont un salaire égal, et un employé un salaire 12x moins élevé. Indice de Gini = 0.1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Pour des revenus réellement équitables, il faudrait que le coefficient de Gini des entreprises corresponde, ou soit même inférieur à celui du pays considéré. Ceci laisse encore une grande flexibilité à la politique salariale. Voici par exemple quelques distributions de revenus donnant un indice de Gini = 0.33, le même que celui de la Suisse entière (avant impôts):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;10% du personnel touche un salaire 6x supérieur aux 90%&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;50% du personnel touche un salaire 4x supérieur aux autres 50%&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
des salaires : 10% touchent un salaire de base, 10% touchent 2x plus, 10% touchent 3x plus etc jusqu&amp;rsquo;aux 10% qui touchent 10x le salaire de base:&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 457px; width: 100%;"&gt;&lt;a href="https://drgoulu.com/wp-content/uploads/HLIC/4a57146795bddaf647e74921f592a4c3.png" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2009/images/4a57146795bddaf647e74921f592a4c3_hu_ec92e6cc03bf8f1e.webp" srcset="https://drgoulu.com/posts/2009/images/4a57146795bddaf647e74921f592a4c3_hu_ec92e6cc03bf8f1e.webp 320w, https://drgoulu.com/posts/2009/images/4a57146795bddaf647e74921f592a4c3_hu_f857b0bc2701e7fe.webp 457w" sizes="(max-width: 640px) 100vw, 457px" alt="Lorenz 1-12-3" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;distribution uniforme des revenus : Gini = 0.33&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On voit au passage que la courbe de Lorenz permettent d&amp;rsquo; illustrer de manière fine la politique salariale des entreprises. En particulier, les différences de statut entre employés provoquent des &amp;ldquo;cassures&amp;rdquo; dans la courbe, alors que des revenus abusifs dans le haut de l&amp;rsquo;échelle sont détectables par la pente de la courbe à droite.&lt;/p&gt;
&lt;p&gt;Il serait très intéressant de connaitre le coefficient de Gini des entreprises. je n&amp;rsquo;en ai trouvé aucun sur internet, pourtant je suis persuadé que les grandes entreprises (et les grands patrons) pourraient défendre leur politique de rémunération en publiant ce chiffre, qui est beaucoup plus parlant que le rapport max/min ou le montant total de la rémunération de la direction.&lt;/p&gt;
&lt;p&gt;Si vous connaissez celui de votre entreprise ou si vous le calculez à l&amp;rsquo;aide de ma
, je vous serais très reconnaissant de le communiquer à l&amp;rsquo;aide des commentaires ci-dessous. Pas besoin de nommer l&amp;rsquo;entreprise, le secteur d&amp;rsquo;activité et la région suffisent. Merci d&amp;rsquo;avance !&lt;/p&gt;
&lt;p&gt;Note : &lt;em&gt;cette 
&lt;/em&gt; &lt;em&gt;est mise à disposition gratuitement uniquement pour utilisation privée, non commerciale. Je m&amp;rsquo;en réserve tous les droits pour les autres usages. Veuillez me contacter en déposant un commentaire ci-dessous si vous envisagez utiliser cette feuille professionnellement.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>La fraternité des nombres</title><link>https://drgoulu.com/2009/09/28/la-fraternite-des-nombres/</link><pubDate>Mon, 28 Sep 2009 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2009/09/28/la-fraternite-des-nombres/</guid><description>&lt;p&gt;Vu l&amp;rsquo;autre jour sur un blog¹ une &amp;ldquo;question bête&amp;rdquo;, donc intrigante : existe-t-il des nombres entre lesquels les mathématiciens ne connaissent aucune relation ?&lt;/p&gt;
&lt;p&gt;La question est &amp;ldquo;bête&amp;rdquo; puisqu&amp;rsquo;on peut toujours trouver une relation entre deux nombres entiers. Mais elle m&amp;rsquo;a rappelé ma quête initiée avec les 
: tous les nombres ont de nombreuses propriétés répertoriées en particulier dans l’
 de Sloane, mais certains en ont nettement
que d&amp;rsquo;
.&lt;/p&gt;
&lt;p&gt;En utilisant la même approche (la base de données de Sloane digérée par quelques lignes de Python), j&amp;rsquo;ai établi le lien de &amp;ldquo;fraternité&amp;rdquo; entre les entiers de 1 à 1024, en comptant pour chaque paire (a.b) possible  le nombre de suites comportant ces deux nombres, que j&amp;rsquo;appelle la fraternité f(a,b).&lt;/p&gt;
&lt;p&gt;Par exemple, 456 et 789 ont une fraternité f(456,789) = 32, car
et partagent donc autant de propriétés répertoriées.&lt;/p&gt;
&lt;p&gt;Les nombres les plus fraternels sont évidemment
, qui sont présents dans 133529 séries répertoriées à ce jour. A l&amp;rsquo;inverse, **les deux plus petits entiers qui ne partagent aucune propriété sont
**².&lt;/p&gt;
&lt;p&gt;
 sont les plus petits nombres ayant une seule propriété commune, en l&amp;rsquo;occurence
&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai représenté les fraternités  f(a,b) pour a et b variant de 1 à 1024 dans l&amp;rsquo;image ci-dessous. Le point (1,1) est en bas à gauche. Les fraternités f(a,b)&amp;gt;100 sont représentées par des pixels rouges et les fraternités inférieures à 10 sont en bleu foncé. Les quelques pixels noirs dénotent les fraternités f(a,b)=0.&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 384px; width: 100%;"&gt;&lt;a href="https://drgoulu.com/wp-content/uploads/HLIC/39a3a9b0caf38144b5ce54f423dc0b54.png" target="_blank" rel="noopener"&gt;&lt;img src="https://drgoulu.com/posts/2009/images/39a3a9b0caf38144b5ce54f423dc0b54_hu_80ce7a25aeeb0f10.webp" srcset="https://drgoulu.com/posts/2009/images/39a3a9b0caf38144b5ce54f423dc0b54_hu_80ce7a25aeeb0f10.webp 320w, https://drgoulu.com/posts/2009/images/39a3a9b0caf38144b5ce54f423dc0b54_hu_c25be1a185d1fff7.webp 480w, https://drgoulu.com/posts/2009/images/39a3a9b0caf38144b5ce54f423dc0b54_hu_bcad9be31b8e6b60.webp 760w" sizes="(max-width: 640px) 100vw, 384px" alt="fraternité f(a,b) des nombres entre 1 et 1024" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;/a&gt;&lt;figcaption&gt;fraternité f(a,b) des nombres entre 1 et 1024. cliquer pour agrandir.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;On remarque l&amp;rsquo;apparition de quelques motifs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les lignes horizontales et verticales claires correspondent à des nombres particulièrement
, les sombres aux
&lt;/li&gt;
&lt;li&gt;les lignes claires à 45° sont plus surprenantes. Elles semblent indiquer que des nombres consécutifs ont tendance à être plus proches d&amp;rsquo;autres nombres consécutifs séparés par des constantes. Je m&amp;rsquo;attendais à voir apparaître des lignes à 30° et 60° liant les nombres à leurs doubles, mais ce n&amp;rsquo;est pas le cas.&lt;/li&gt;
&lt;li&gt;Sur la diagonale (coloriée en rouge par convention), on distingue des petites taches autour de groupes de nombres particulièrement intéressants comme les fortement composites (160, 320) et les puissance de 2 (256, 512), qui forment aussi des taches aux intersections hors diagonale.&lt;/li&gt;
&lt;li&gt;Les motifs les plus étranges sont les groupes de 9 points clairs visibles le long des bords bleus, et en particulier au coin supérieur droit. Ils correspondent aux nombres 1010±10 et 110±10, ce qui peut s&amp;rsquo;expliquer par les nombreuses suites faisant intervenir des nombres binaires, mais on en trouve aussi à 210±10. Est-ce l&amp;rsquo;effet du ternaire, ou d&amp;rsquo;autre chose ?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Résultat provisoire de ma recherche aussi excitante qu&amp;rsquo;inutile : les nombres ne sont décidément  pas tous égaux devant les mathématiques.&lt;/p&gt;
&lt;h3 id="notes"&gt;Notes:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;je ne retrouve plus la source de la &amp;ldquo;question bête&amp;rdquo;. Elle a été posée il y a une semaine sur un blog&amp;hellip; Si vous savez où, merci de me l&amp;rsquo;indiquer en commentaire&amp;hellip;&lt;/li&gt;
&lt;li&gt;Le moteur de recherche de l&amp;rsquo;Encyclopédie de Sloane peut soit trouver des termes consécutifs dans la série, soit des nombres présents dans tout l&amp;rsquo;article dédié à chaque suite. C&amp;rsquo;est pourquoi la recherche de
fournit plusieurs résultats, mais si vous regardez bien, les nombres 48 et 857 ne sont jamais présents ensemble dans les séries.&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Combien de nombres palindromes &lt; N ?</title><link>https://drgoulu.com/2009/09/26/combien-de-nombres-palindromes-n/</link><pubDate>Sat, 26 Sep 2009 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2009/09/26/combien-de-nombres-palindromes-n/</guid><description>&lt;p&gt;Les problèmes du
devenant vraiment très ardus, j&amp;rsquo;ai été content de trouver
 un petit challenge intéressant : déterminer rapidement le nombre de nombres palindromes inférieurs à un maximum donné.&lt;/p&gt;
&lt;figure class="alignright" style="max-width: 148px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2009/images/37b10823a4bb4b9808e544fa55dc514d.gif" alt="17371, un nombre palindrome" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" /&gt;&lt;figcaption&gt;un nombre palindrome&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Un 
se lit indifféremment de gauche à droite ou de droite à gauche, comme 1234321 ou 567765. Outre leur aspect esthétique, ces nombres ont aussi des
.&lt;/p&gt;
&lt;p&gt;La première idée qui vient à l&amp;rsquo;esprit est de les compter (c&amp;rsquo;est du
):&lt;/p&gt;
\[sourcecode language="delphi"\]&lt;p&gt; function NumberOfPalindromes(const maxNumber : integer) : integer; var i:Integer; s:string; begin Result:=0; for i := 1 to maxNumber do begin s:=IntToStr(i); if s=ReverseString(s) then Inc(Result); end; end; &lt;/p&gt;
\[/sourcecode\]&lt;p&gt;Ca marche, mais c&amp;rsquo;est très lent : pour maxNumber=1000000000, il faut un milliard de conversions en chaine de caractères, un milliard d&amp;rsquo;inversions de chaîne, et un milliard de comparaisons. Or le résultat n&amp;rsquo;est que de 109998. Comme l&amp;rsquo;
(mais c&amp;rsquo;est de moi) :&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;Si ta boucle ne fait rien 99% du temps, c&amp;rsquo;est que tu n&amp;rsquo;utilises pas le bon algorithme.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;De plus, notre boucle génère tous les nombres palindromes sous forme de chaine, et on les jette.&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;Si tu jettes 99% des résultats, c&amp;rsquo;est que tu n&amp;rsquo;utilises pas le bon algorithme.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une autre approche, que beaucoup utilisent avant même de programmer, voire de réfléchir, est de
. C&amp;rsquo;est une excellente approche. On trouve immédiatement une
, avec une formule qui offre sur un plateau le nombre a(n) de nombres palindromes inférieurs à 10n&lt;/p&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;&lt;img alt=""
src="https://drgoulu.com/posts/2009/images/e75fb46011bd71a4c4c1acbc3fdda2b9.gif"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
La formule n&amp;rsquo;est valable que pour n entier, mais on peut tout de même la convertir en une petite fonction Delphi:&lt;/p&gt;
\[sourcecode language="delphi"\]&lt;p&gt; function NumberOfPalindromes(const maxNumber : integer) : integer; const pow10:array&lt;/p&gt;
\[0..9\]&lt;p&gt; of integer=(1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000); var n:Integer; begin n:=Round(log10(maxNumber)); if Odd(n) then Result:=11*pow10&lt;/p&gt;
\[(n-1)div 2\]&lt;p&gt;-2 else Result:=2*pow10&lt;/p&gt;
\[n div 2\]&lt;p&gt;-2; end; &lt;/p&gt;
\[/sourcecode\]&lt;p&gt;Comme il s&amp;rsquo;avère  que le
ne teste les algorithmes proposés qu&amp;rsquo;avec une puissance de 10, vous avez ci dessus une solution victorieuse, mais typique de la programmation agile : elle ne fonctionne (bien) que pour les tests ;-)&lt;/p&gt;
&lt;p&gt;Tentons maintenant de rendre notre programme correct quel que soit N, si possible sans le ralentir. On va même commencer par le rendre encore plus rapide en poussant le vice de la programmation agile (= paresse) encore plus loin:&lt;/p&gt;
\[sourcecode language="delphi"\]&lt;p&gt; function NumberOfPalindromes(const maxNumber : integer) : integer; const A050250:array&lt;/p&gt;
\[0..9\]&lt;p&gt; of integer=(0,9, 18, 108, 198, 1098, 1998, 10998, 19998, 109998); begin Result:=A050250&lt;/p&gt;
\[Round(log10(maxNumber))\]&lt;p&gt;; end; &lt;/p&gt;
\[/sourcecode\]&lt;p&gt;Le vecteur
contient directement les résultats de la formule pour n=(0),1,2,..,9. Son nom provient de
.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;algorithme ci-dessous commence par utiliser cette série pour compter les palindromes inférieurs à la puissance de 10 juste inférieure à maxNumber, puis considère successivement les chiffres de maxNumber en partant du plus significatif et compte le nombre de palindromes possibles sur les digits intermédiaires.&lt;/p&gt;
&lt;p&gt;Par exemple pour maxNumber=5832476 :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;on compte 1998 palindromes inférieurs à 1000000, le plus grand étant 999999&lt;/li&gt;
&lt;li&gt;on ajoute (5-1) fois le nombre de palindromes de 5 chiffres, soit 1000 (de 000|00 à 999|99), ce qui donne le nombre de palindromes jusqu&amp;rsquo;à 4999994&lt;/li&gt;
&lt;li&gt;on ajoute 8 fois le nombre de palindromes de 3 chiffres, soit 100. On a donc compté les palindromes jusqu&amp;rsquo;à 5799975&lt;/li&gt;
&lt;li&gt;on ajoute 2 fois les 10 nombres possibles au centre, ce qui compte jusqu&amp;rsquo;à 5829285&lt;/li&gt;
&lt;li&gt;reste à ajouter les (2+1) nombres palindromes obtenus en changeant le chiffre central : 5830385, 5831385 et 5832385&lt;/li&gt;
&lt;/ol&gt;
\[sourcecode language="delphi"\]&lt;p&gt; function NumberOfPalindromes(const maxNumber : integer) : integer; const A050250:array&lt;/p&gt;
\[0..18\]&lt;p&gt; of integer =(0,9, 18, 108, 198, 1098, 1998, 10998, 19998, 109998, 199998, 1099998, 1999998, 10999998, 19999998, 109999998, 199999998, 1099999998, 1999999998); const pow10:array&lt;/p&gt;
\[0..9\]&lt;p&gt; of integer =(1,10,100,1000,10000,100000, 1000000,10000000,100000000,1000000000); var n,i,j,k:Integer; d:array&lt;/p&gt;
\[0..18\]&lt;p&gt; of integer; // digits begin i:=0; n:=maxNumber; while n&amp;gt;0 do begin // extract digits d&lt;/p&gt;
\[i\]&lt;p&gt;:=n mod 10; n:=n div 10; inc(i); end; n:=i-1; // n=Trunc(log10(maxNumber)) Result:=A050250&lt;/p&gt;
\[n\]&lt;p&gt;; i:=n; j:=0; k:=n div 2; dec(d&lt;/p&gt;
\[n\]&lt;p&gt;); // because we counted palindromes to 1000..00 while i-j&amp;gt;=2 do begin // loop from outer digits to inner Result:=result+d&lt;/p&gt;
\[i\]&lt;p&gt;*(pow10&lt;/p&gt;
\[k\]&lt;p&gt;); dec(i); inc(j); dec(k); end; inc(Result,d&lt;/p&gt;
\[i\]&lt;p&gt;); // handle 1 or 2 center digits if d&lt;/p&gt;
\[j\]&lt;p&gt;&amp;gt;=d&lt;/p&gt;
\[i\]&lt;p&gt; then inc(Result); end; &lt;/p&gt;
\[/sourcecode\]&lt;p&gt;Cet algorithme étant nettement plus rapide et compact que les solutions existantes du challenge, je viens de le soumettre au
bien qu&amp;rsquo;il y ait encore une petit bulle&amp;hellip; Pour certains maxNumber &amp;ldquo;rares&amp;rdquo;, le résultat est 1 de trop. Saurez-vous trouver pourquoi avant moi ?&lt;/p&gt;</description></item><item><title>la Résurrection du Jeu de la Vie</title><link>https://drgoulu.com/2009/03/29/la-resurrection-du-jeu-de-la-vie/</link><pubDate>Sun, 29 Mar 2009 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2009/03/29/la-resurrection-du-jeu-de-la-vie/</guid><description>&lt;p&gt;Le
imaginé par
en 1970 est un automate cellulaire célébrissime pour au moins deux raisons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;figure class="alignright" style="max-width: 250px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2009/images/a470c29cf6c88b820cc608831b61f545.gif" alt="Un canon à planeurs" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" /&gt;&lt;figcaption&gt;Un &amp;quot;canon à planeurs&amp;quot;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;A partir de règles toutes simples, le jeu de la vie génère une &amp;ldquo;vie&amp;rdquo; artificielle étrangement complexe et imprévisible, posant toutes sortes de questions intéressantes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le Jeu de la Vie étant très facile à programmer, des générations d&amp;rsquo;étudiants ont codé des programmes &amp;ldquo;Life&amp;rdquo; dans tous les langages imaginables.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Après une flambée d&amp;rsquo;intérêt dans les années 1980 où on a même vu apparaitre des processeurs spécialisés dans l&amp;rsquo;exécution d&amp;rsquo;automates cellulaires, le soufflé est retombé dans la décennie suivante car la simulation de grands automates demandait beaucoup de puissance de calcul et de mémoire.&lt;/p&gt;
&lt;p&gt;Mais comme nous l&amp;rsquo;apprend Jean-Paul Delahaye dans le dernier &amp;ldquo;Pour la Science&amp;rdquo;
, il y a du nouveau. En 2005 est apparu &amp;ldquo;
&amp;rdquo;, un logiciel Open Source utilisant &amp;ldquo;
&amp;quot;, un algorithme accélérant le calcul des automates cellulaires d&amp;rsquo;une manière phénoménale. Hashlife a été imaginé en 1984 déjà par
, un des premiers &amp;ldquo;hacker&amp;rdquo; du Xerox Park de Palo Alto. Mais pour une étrange raison, ce n&amp;rsquo;est qu&amp;rsquo;en 2004 Tomas Rokicki l&amp;rsquo;a implanté en C et décrit dans un article intitulé &amp;ldquo;un algorithme pour compresser le temps et l&amp;rsquo;espace&amp;rdquo;
.&lt;/p&gt;
&lt;p&gt;Hashlife combine en effet deux techniques de programmation :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;une partition de l&amp;rsquo;espace qui permet d&amp;rsquo;une part d&amp;rsquo;ignorer les grandes zones de cellules vides et d&amp;rsquo;autre part de reconnaitre les copies identiques de groupes de cellules&lt;/li&gt;
&lt;li&gt;la &amp;ldquo;
&amp;rdquo;, qui consiste à mémoriser des résultats précédemment calculés afin de les restituer immédiatement lorsque la même situation se représente.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ainsi, hashlife ne calcule qu&amp;rsquo;une seule fois l&amp;rsquo;évolution d&amp;rsquo;un groupe de cellules qui serait présent à des milliers d&amp;rsquo;exemplaires dispersés sur un immense jeu de la vie, et n&amp;rsquo;a besoin de mémoire que pour stocker chacune des étapes d&amp;rsquo;un cycle au lieu de millions de cellules.&lt;/p&gt;
&lt;p&gt;Hashlife parvient ainsi à calculer des milliers de générations par seconde de &amp;ldquo;Jeux de la Vie&amp;rdquo; comportant 10&lt;sup&gt;50 cellules sur un PC ordinaire doté de 10&lt;/sup&gt;9 octets de mémoire !&lt;/p&gt;
&lt;p&gt;Voici par exemple &amp;ldquo;
&amp;rdquo; en action sur le &amp;ldquo;breeder&amp;rdquo;, la première structure générant un nombre de cellules augmentant comme le carré du nombre de générations :&lt;/p&gt;
&lt;div class="my-6 mx-auto" style="max-width: 640px; width: 100%;"&gt;
&lt;div class="w-full relative rounded-lg overflow-hidden shadow-md bg-black" style="padding-bottom: 56.25%; height: 0;"&gt;
&lt;iframe
src="https://www.youtube-nocookie.com/embed/FVP58qsG0MY"
title="YouTube video player"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
loading="lazy"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;On voit comment un groupe de &amp;ldquo;fusées&amp;rdquo; se déplace vers la droite en générant des &amp;ldquo;canons à planeurs&amp;rdquo;. En quelques secondes, 400'000 générations ont été calculées (même pas à vitesse maximale) , générant 160 millions de cellules actives.&lt;/p&gt;
&lt;p&gt;Cette vitesse permet de visualiser confortablement d&amp;rsquo;autres structures extraordinaires découvertes récemment, comme les &amp;ldquo;métacellules&amp;rdquo;:&lt;/p&gt;
&lt;div class="my-6 mx-auto" style="max-width: 640px; width: 100%;"&gt;
&lt;div class="w-full relative rounded-lg overflow-hidden shadow-md bg-black" style="padding-bottom: 56.25%; height: 0;"&gt;
&lt;iframe
src="https://www.youtube-nocookie.com/embed/wkOEeQsKEvU"
title="YouTube video player"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
loading="lazy"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;On voit ici un tableau de 15x15 métacellules, dont chacune se comporte comme une cellule du Jeu de la Vie ! En 30'000 générations environ, chaque métacellule compte le nombre de ses voisins &amp;ldquo;vivants&amp;rdquo; et devient elle-même vivante en se remplissant de planeurs en suivant la règle de Conway !&lt;/p&gt;
&lt;p&gt;Le &amp;ldquo;Jeu de la Vie&amp;rdquo; est donc capable d&amp;rsquo;exécuter un programme jouant au &amp;ldquo;Jeu de la Vie&amp;rdquo;. Mais quels autres programmes peut-il exécuter ? On connait depuis 1984 des structures calculant les nombres premiers, et d&amp;rsquo;autres &amp;ldquo;écrivant&amp;rdquo; en clair comme celle-ci :&lt;/p&gt;
&lt;div class="my-6 mx-auto" style="max-width: 640px; width: 100%;"&gt;
&lt;div class="w-full relative rounded-lg overflow-hidden shadow-md bg-black" style="padding-bottom: 56.25%; height: 0;"&gt;
&lt;iframe
src="https://www.youtube-nocookie.com/embed/Rj3va_5qcM4"
title="YouTube video player"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
loading="lazy"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Mais en 2000, Paul Rendell a réussi a créer une  &amp;ldquo;
&amp;rdquo; en Jeu de la Vie
, ce qui signifie que ce petit jeu aux  règles extraordinairement simple est capable, avec une astucieuse programmation, de réaliser toutes les opérations d&amp;rsquo;un ordinateur usuel.&lt;/p&gt;
&lt;p&gt;Outre le jeu de la Vie, Golly peut exécuter d&amp;rsquo;autres automates cellulaires en utilisant le fantastique algorithme Hashlife, notamment
, un système simulant les circuits électroniques digitaux.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Hashlife&amp;rdquo; est bien un algorithme qui compresse l&amp;rsquo;espace et le temps, comme le dit Rokicki, et il  est même d&amp;rsquo;un usage assez général. Je ne serais pas étonné s&amp;rsquo;il trouvait prochainement des applications &amp;ldquo;sérieuses&amp;rdquo;, en simulation notamment.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;adore les rubriques de Jean-Paul Delahaye dans &amp;ldquo;Pour la Science&amp;rdquo;. Surtout celle du mois prochain&amp;hellip;&lt;/p&gt;
&lt;h2 id="références"&gt;Références:&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span id="ref-1"&gt;&lt;/span&gt;Jean-Paul Delahaye &amp;ldquo;
&amp;rdquo;, Pour la Science, avril 2009, p. 86-91&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-2"&gt;&lt;/span&gt;Tomas G. Rokicki &amp;ldquo;
&amp;rdquo;, Dr. Dobbs Journal, avril 2006&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-3"&gt;&lt;/span&gt;&lt;span class="altmetric-embed" data-badge-type="donut" data-badge-popover="right" data-doi="10.1016/0167-2789(84)90251-3" style="float: right; margin: 0 0 0.5rem 0.5rem;"&gt;&lt;/span&gt;
William Gosper &amp;ldquo;Exploiting Regularities in Large Cellular Spaces&amp;rdquo;, 1984, Physica D. Nonlinear Phenomena, Vol 10, pp. 75-80 
&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-4"&gt;&lt;/span&gt;Paul Rendell &amp;quot; 
&amp;rdquo;, 2000&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-5"&gt;&lt;/span&gt;Paul Callahan &amp;ldquo;Wonders of Math : 
&amp;rdquo; sur Math.com&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-6"&gt;&lt;/span&gt;
, un blog dédié aux nouvelles découvertes sur le Jeu de la Vie&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-7"&gt;&lt;/span&gt;Un &amp;ldquo;
&amp;rdquo; en Java, utilisant l&amp;rsquo;algorithme Hashlife implanté dans ce langage, en open source.&lt;/li&gt;
&lt;li&gt;&lt;span id="ref-8"&gt;&lt;/span&gt;David Bau &amp;ldquo;
&amp;rdquo;, une implantation (simplifiée) de Hashlife en Python&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Programmer pour le fun</title><link>https://drgoulu.com/2009/02/23/project_euler/</link><pubDate>Mon, 23 Feb 2009 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2009/02/23/project_euler/</guid><description>&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2009/images/a9192f1b2a56a4bbaee679259c557e57_hu_63e352f6a676822a.webp 230w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2009/images/a9192f1b2a56a4bbaee679259c557e57_hu_63e352f6a676822a.webp"
width="230"
height="230"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
Amis des casse-tête mathématiques ardus et de la programmation d&amp;rsquo;algorithmes optimisés, bonjour!&lt;/p&gt;
&lt;p&gt;Je viens de découvrir
, et j&amp;rsquo;ai honte de ne pas l&amp;rsquo;avoir trouvé avant. Ce site propose 233 problèmes (et environ un de plus chaque semaine environ) pouvant parfois être résolus avec un papier et un crayon propulsé par un cerveau en ébullition, mais pour la plupart requièrent  quelques lignes de code bien pensées et un stupide esclave électronique pour les exécuter.&lt;/p&gt;
&lt;p&gt;Une fois inscrit sur le site, vous pouvez soumettre vos solutions aux problèmes dans l&amp;rsquo;ordre qui vous plait et chaque bonne réponse vous apporte instantanément:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la possibilité d&amp;rsquo;accéder à un forum où les solutions sont comparées et discutées. C&amp;rsquo;est en général là qu&amp;rsquo;on commence à avoir mal au front, quand on découvre des algorithmes 1000x plus rapides que ceux qu&amp;rsquo;on s&amp;rsquo;est escrimé à mettre au point, ou pire, la petite formule qui tue&amp;hellip;&lt;/li&gt;
&lt;li&gt;un bon point. Après 25 bonnes réponses vous entrez dans le tableau des
et pouvez espérer rejoindre un jour la
qui ont résolu tous les problèmes jusqu&amp;rsquo;ici.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il faut dire que les premiers problèmes sont relativement simples, par exemple les 17 que j&amp;rsquo;ai déjà résolus sont :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;additionner tous les entiers intérieurs à 1000 qui sont multiples de 3 ou 5&lt;/li&gt;
&lt;li&gt;trouver la somme de tous les nombres pairs de la
inférieurs à 4'000'000&lt;/li&gt;
&lt;li&gt;trouver le plus grand facteur premier de 600'851'475'143&lt;/li&gt;
&lt;li&gt;trouver le plus grand palindrome formé par le produit de 2 nombres de 3 chiffres&lt;/li&gt;
&lt;li&gt;quel est le plus petit nombre divisible par tous les entiers de 1 à 20 ? (facile. celui là je l&amp;rsquo;ai fait à la main)&lt;/li&gt;
&lt;li&gt;quelle est la différence entre le carré de la somme des 100 premiers entiers et la somme du carré de ces même nombres ?&lt;/li&gt;
&lt;li&gt;trouver le 10001ème nombre premier&lt;/li&gt;
&lt;li&gt;trouver le plus grand produit de 5 chiffres consécutifs dans un nombre à 1000 chiffres&lt;/li&gt;
&lt;li&gt;trouver le seul
dont la somme a+b+c=1000&lt;/li&gt;
&lt;li&gt;calculer la somme des nombres premiers inférieurs à 2'000'000&lt;/li&gt;
&lt;li&gt;quel est le premier
ayant plus de 500 diviseurs ?&lt;/li&gt;
&lt;li&gt;quels sont les 10 premiers chiffres de la somme de 100 nombre de 50 chiffres donnés?&lt;/li&gt;
&lt;li&gt;trouver le nombre inférieur à 1'000'000 générant la plus longue
&lt;/li&gt;
&lt;li&gt;en partant d&amp;rsquo;un coin d&amp;rsquo;une grille de 20x20, combien y&amp;rsquo;a-t-il de chemins au coin opposé ? (
&amp;hellip;)&lt;/li&gt;
&lt;li&gt;quelle est la somme des chiffres de  21000?&lt;/li&gt;
&lt;li&gt;quel est le premier terme supérieur à 101000 de la suite de Fibonacci ? (et si je vous disais qu&amp;rsquo;on peut le trouver sans calculer les termes précédents ?)&lt;/li&gt;
&lt;li&gt;trouver la somme des chiffres de 100! (factorielle&amp;hellip;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Certains de ces problèmes exigent de pouvoir manipuler de grands nombres, ce qui est une force du langage
, que j&amp;rsquo;aime de plus en plus. On peut par exemple obtenir la somme des chiffres de la factorielle de 100 en une seule ligne* combinant la
et la fonction
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;reduce(lambda x, y: x + y, [int(i) for i in str(reduce(lambda x, y: x * y, range(1, 100)))])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bon, jusqu&amp;rsquo;ici j&amp;rsquo;ai fait le facile : même avec une approche un peu brutale, on s&amp;rsquo;en sort. Mais rapidement la complexité fait son apparition au carré : au niveau mathématique et au niveau algorithmique, condamnant le programmeur peu subtil à patienter des minutes, des heures ou des siècles devant un sablier virtuel &amp;hellip;&lt;/p&gt;
&lt;p&gt;Je vois encore quelques problèmes liés à des sujets déjà abordés sur Dr.Goulu comme:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;trouver le polynôme _n_² + &lt;em&gt;an&lt;/em&gt; + &lt;em&gt;b&lt;/em&gt;, où|&lt;em&gt;a&lt;/em&gt;| &amp;lt; 1000 et|&lt;em&gt;b&lt;/em&gt;| &amp;lt; 1000 qui produit le plus de
&lt;/li&gt;
&lt;li&gt;quel nombre premier inférieur à 1'000'000 est la
?&lt;/li&gt;
&lt;li&gt;combien existe-t-il de
inférieurs à 10'000 ?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il y a encore environ entre 20 et 50 problèmes que j&amp;rsquo;espère pouvoir résoudre à raison d&amp;rsquo;un  par soirée.&lt;/p&gt;
&lt;p&gt;Après, ce sera &lt;strong&gt;l&amp;rsquo;enfer&lt;/strong&gt; mais j&amp;rsquo;espère vous y retrouver, ami lecteur &amp;hellip; (insérer un rire
ici)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note* dans le forum on découvre une solution en 13 caractères seulement, en
évidemment: +/&amp;quot;.&amp;ldquo;0&amp;rdquo;:!100x&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2009/images/Dr_Goulu_hu_e37231ec7db728c0.webp 200w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2009/images/Dr_Goulu_hu_e37231ec7db728c0.webp"
width="200"
height="60"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;</description></item><item><title>Démosaïquification</title><link>https://drgoulu.com/2008/12/03/demosaiquification/</link><pubDate>Wed, 03 Dec 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/12/03/demosaiquification/</guid><description>&lt;p&gt;
C&amp;rsquo;est très facile de faire une
comme celle ci-contre. Des sites comme
en quelques secondes des centaines d&amp;rsquo;images pour approximer une image de base.&lt;/p&gt;
&lt;p&gt;Par exemple, voici un détail du goulot du bécher ci-contre:&lt;/p&gt;
&lt;p&gt;
Mais combien de petites images distinctes sont utilisées pour produire la mosaïque ? Pour répondre à cette question, j&amp;rsquo;ai développé un petit programme avec
en utilisant la
&lt;/p&gt;
&lt;p&gt;Le programme produit un
, avec à côté toutes les copies de cette image identifiées par le programme.&lt;/p&gt;
&lt;p&gt;Le programme Python est ci-dessous, il est relativement simple, à l&amp;rsquo;exception de la fonction permettant de comparer les images pour laquelle j&amp;rsquo;ai pas mal ramé, et il reste un seuil numérique à ajuster au cas par cas, mais dans l&amp;rsquo;ensemble ça marche&amp;hellip;&lt;/p&gt;
&lt;p&gt;A quoi ça sert tout ça ? Outre à tester le traitement d&amp;rsquo;image en Python avec PIL, c&amp;rsquo;est pour gagner un concours, mais je ne vous dirai pas (encore) lequel
&lt;/p&gt;
\[code lang="python"\]&lt;p&gt;import Image; #PIL import ImageChops; import ImageStat; import math;&lt;/p&gt;
&lt;p&gt;im = Image.open(&amp;ldquo;mosaic.jpg&amp;rdquo;) smallx=40; smally=40;&lt;/p&gt;
&lt;p&gt;border=1; #ignore border of picture print im.size&lt;/p&gt;
\[0\]&lt;p&gt;,im.size&lt;/p&gt;
\[1\]&lt;p&gt; n=(im.size&lt;/p&gt;
\[0\]&lt;p&gt;/smallx)*(im.size&lt;/p&gt;
\[0\]&lt;p&gt;/smally) nx=math.sqrt(n)&lt;/p&gt;
&lt;p&gt;res=Image.new(im.mode,(smallx*nx,smally*n)) L=[]; jmax=0; y=0; while y&amp;lt;im.size&lt;/p&gt;
\[1\]&lt;p&gt;: x=0; while x&amp;lt;im.size&lt;/p&gt;
\[0\]&lt;p&gt;: box = (x+border, y+border, x+smallx-border, y+smally-border) mini = im.crop(box) mininb=ImageOps.equalize(mini.convert(&amp;lsquo;L&amp;rsquo;)) min=1000; for i in range(len(L)): rms=ImageStat.Stat( ImageChops.difference( mininb,L&lt;/p&gt;
\[i\]\[0\]&lt;p&gt; ) ).mean&lt;/p&gt;
\[0\]&lt;p&gt; if rms&amp;lt;min: f=i; min=rms; if min&amp;lt;30: #this must be tuned for each case &amp;hellip; j=L&lt;/p&gt;
\[f\]\[1\]&lt;p&gt; L&lt;/p&gt;
\[f\]\[1\]&lt;p&gt;=j+1 else: j=0 f=len(L) L.append(&lt;/p&gt;
\[mininb,1\]&lt;p&gt;) if j&amp;gt;jmax: jmax=j; box = (smallx*j+border, smally*f+border) res.paste(mini,box); x=x+smallx print &amp;lsquo;.&amp;rsquo;, y=y+smally&lt;/p&gt;
&lt;p&gt;res.crop((0,0,(jmax+1)*smallx,len(L)*smally)).save(&amp;lsquo;result.jpg&amp;rsquo;) print &amp;lsquo;DONE!&amp;rsquo; print len(L),&amp;lsquo;different images over&amp;rsquo;,n,&amp;lsquo;max&amp;rsquo;,jmax+1,&amp;lsquo;copies&amp;rsquo;&lt;/p&gt;
&lt;p&gt;res.crop((0,0,(jmax+1)*smallx,len(L)*smally)).save(&amp;lsquo;result.jpg&amp;rsquo;) print len(L),&amp;lsquo;different images over&amp;rsquo;,n,&amp;lsquo;max&amp;rsquo;,jmax+1,&amp;lsquo;copies&amp;rsquo;&lt;/p&gt;
\[/code\]</description></item><item><title>Le Problème à N corps</title><link>https://drgoulu.com/2008/11/16/le-probleme-a-n-corps/</link><pubDate>Sun, 16 Nov 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/11/16/le-probleme-a-n-corps/</guid><description>&lt;p&gt;Le &amp;ldquo;problème à N corps&amp;rdquo; consiste à déterminer le mouvement de N masses sous l&amp;rsquo;effet des forces d&amp;rsquo;attraction gravitationnelles entre elles.&lt;/p&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;&lt;img alt=""
src="https://drgoulu.com/posts/2008/images/2aafbc7c07256efd594fb07d17ea858d.gif"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
Pour N=2, Newton savait déjà que les
décrivent des ellipses autour de leur centre de gravité commun.&lt;/p&gt;
&lt;p&gt;Pour N=3,
 : une toute petite différence dans les positions et vitesses initiales des corps pouvait causer de très importantes différences dans la trajectoire des corps. Cependant, malgré ce que beaucoup croient, il existe une solution analytique au problème des trois corps découverte en 1909 par
. Elle n&amp;rsquo;est cependant pas utilisable en pratique pour des calculs.&lt;/p&gt;
&lt;p&gt;Pour plus de 3 corps, il n&amp;rsquo;existe pas de solution analytique. Ceci signifie entre autres qu&amp;rsquo;il n&amp;rsquo;est pas possible de démontrer la stabilité d&amp;rsquo;un système avec quelques corps, comme le Système Solaire par exemple. Des mathématiciens comme
ou
s&amp;rsquo;y sont cassés les dents : rien ne prouve que les planètes suivront toujours leurs orbites actuelles dans quelques centaines de millions d&amp;rsquo;années. Encore moins qu&amp;rsquo;un astéroïde viennent percuter notre belle planète beaucoup plus tôt.&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 430px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2008/images/f6524d761bd5b7f92d5262ab33448a77_hu_9e54bb6b15e3cc74.webp" srcset="https://drgoulu.com/posts/2008/images/f6524d761bd5b7f92d5262ab33448a77_hu_9e54bb6b15e3cc74.webp 320w, https://drgoulu.com/posts/2008/images/f6524d761bd5b7f92d5262ab33448a77_hu_a2ce086bf66faf75.webp 430w" sizes="(max-width: 640px) 100vw, 430px" alt="Simulation du Système Solaire sur Univers Sandbox, N~20" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;figcaption&gt;Simulation du Système Solaire sur Univers Sandbox, N~20&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Il est aujourd&amp;rsquo;hui facile de simuler quelques millions d&amp;rsquo;années d&amp;rsquo;évolution du Système Solaire sur un PC, par exemple avec
, le chouette programme dont j&amp;rsquo;ai
. Comme on connait avec une très grande précision la position, la vitesse et la masse des planètes et de leurs principaux satellites, on estime que l&amp;rsquo;on peut calculer leur position dans 5 millions d&amp;rsquo;années à 150m près. Pour arriver à cette précision, mais aussi tout simplement pour réaliser une simulation réaliste, il faut tout particulièrement veiller à la
utilisée, pour garantir la conservation de l&amp;rsquo;énergie totale du système. Selon
, la méthode de
donne les meilleurs résultats.&lt;/p&gt;
&lt;p&gt;D&amp;rsquo;autre part, pour chacun des N corps, il faut calculer les N-1 forces exercées par les autres corps. Au total, il faudra calculer &lt;/p&gt;
\[N.(N-1)\]&lt;p&gt;/2 forces (le /2 vient du fait qu&amp;rsquo;il suffit de ne calculer qu&amp;rsquo;une fois la force entre deux corps). On dit que la complexité est O(N²) : il faut effectuer un nombre d&amp;rsquo;opérations proportionnel au carré de N. Pour quelques dizaines de corps, ça ne pose aucun problème, mais si l&amp;rsquo;on veut simuler des galaxies ou même la collision de galaxies avec N=1'000'000, on se retrouve avec mille milliards de forces à évaluer, ce qui nécessite beaucoup de temps de calcul.&lt;/p&gt;
&lt;figure class="aligncenter" style="max-width: 480px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2008/images/7d7300972c3b4db5108dd38e6d611c10_hu_42203dbb0daba09a.webp" srcset="https://drgoulu.com/posts/2008/images/7d7300972c3b4db5108dd38e6d611c10_hu_42203dbb0daba09a.webp 320w, https://drgoulu.com/posts/2008/images/7d7300972c3b4db5108dd38e6d611c10_hu_21ba598f0ae3132f.webp 480w, https://drgoulu.com/posts/2008/images/7d7300972c3b4db5108dd38e6d611c10_hu_1f031c8dd41f5e50.webp 480w" sizes="(max-width: 640px) 100vw, 480px" alt="Simulation de la future collision de la Voie Lactée et dAndromède, N=100000000" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" data-zoomable /&gt;&lt;figcaption&gt;Simulation de la future collision de la Voie Lactée et d&amp;rsquo;Andromède, N=100'000'000&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;On pourrait se dire qu&amp;rsquo;une petite étoile à un bout de la galaxie n&amp;rsquo;attire pratiquement pas une autre petite étoile très distante, mais négliger cette force n&amp;rsquo;est pas une bonne idée. D&amp;rsquo;une part, l&amp;rsquo;énergie totale du système ne serait plus conservée, et d&amp;rsquo;autre part il faudrait trouver un critère permettant de savoir quelles forces sont négligeables, sans les calculer.&lt;/p&gt;
&lt;p&gt;
ont proposé en 1986 un algorithme dont la complexité est O(N.log N). Pour N=1'000'000, il n&amp;rsquo;y a environ que 20'000'000 de forces à évaluer, ce qui rend le calcul possible. L&amp;rsquo;algorithme consiste à diviser l&amp;rsquo;espace en une structure arborescente appelée
 et à y répartir les corps. On ne calcule les forces qu&amp;rsquo;entre les corps situé dans la même zone de l&amp;rsquo;octree, puis l&amp;rsquo;algorithme calcule les interactions entre les zones. Reste une difficulté : en se déplaçant, les corps changent de zone, et l&amp;rsquo;algorithme nécessite d&amp;rsquo;adapter l&amp;rsquo;octree de l&amp;rsquo;adapter à la distribution des corps.&lt;/p&gt;
&lt;p&gt;&lt;div class="my-6 mx-auto" style="max-width: 760px; width: 100%;"&gt;
&lt;div class="w-full relative rounded-lg overflow-hidden shadow-md bg-black" style="padding-bottom: 56.25%; height: 0;"&gt;
&lt;iframe
src="https://www.youtube-nocookie.com/embed/0TuWDVB-V-E"
title="YouTube video player"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
loading="lazy"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
interaction de 2 amas de 50 galaxies. N=160'000&lt;/p&gt;
&lt;p&gt;Dès 1987,
a développé un algorithme baptisé &amp;ldquo;
&amp;rdquo; (FMM), dont la complexité est O(N) seulement, et qui ne nécessite pas d&amp;rsquo;adaptation de la division de l&amp;rsquo;espace utilisée. Il est assez facile d&amp;rsquo;
, mais en 3D l&amp;rsquo;interaction entre zones est beaucoup plus complexe.&lt;/p&gt;
&lt;p&gt;La FMM est considérée par certains comme l&amp;rsquo;un des algorithmes les plus importants du XXième siècle, car il peut être appliqué à des problèmes beaucoup plus généraux que les N corps, comme certains problèmes de
ou de
. Inutile de dire que je vais regarder ça de plus près &amp;hellip;&lt;/p&gt;
&lt;h3 id="références"&gt;Références:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
, le logiciel développé par Barnes et Hut, site avec énormément de liens sur le domaine&lt;/li&gt;
&lt;li&gt;Dossier &amp;ldquo;
&amp;rdquo; sur AstroSurf&lt;/li&gt;
&lt;li&gt;
 sur la Wikipedia&lt;/li&gt;
&lt;li&gt;
à Berkeley&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
: code VPython&lt;/li&gt;
&lt;li&gt;
 sur Wikipedia&lt;/li&gt;
&lt;li&gt;Guy Blelloch and Girija Narlikar &amp;ldquo;
&amp;rdquo; Parallel Algorithms. Series in Discrete Mathematics and Theoretical Computer Science, Volume 30, 1997.&lt;/li&gt;
&lt;li&gt;
, une librairie de simulation N corps parallélisée sur GPU (processeur graphique)&lt;/li&gt;
&lt;li&gt;
: comparaisons et implémentation sur super ordinateurs&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="logiciels-n-corps-sur-pc"&gt;Logiciels N corps sur PC:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
 : le plus beau et le plus fun&lt;/li&gt;
&lt;li&gt;
: utilise l&amp;rsquo;alogrithme de Barnes Hut&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
, un peu ancien&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Python(x,y)</title><link>https://drgoulu.com/2008/10/17/pythonxy/</link><pubDate>Fri, 17 Oct 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/10/17/pythonxy/</guid><description>&lt;p&gt;
 est un langage très puissant, mais livré dans un état un peu brut. Pour l&amp;rsquo;exploiter de façon efficace, il faut y ajouter des libraires graphiques, de calcul spécialisé ou d&amp;rsquo;accès à des bases de données par exemple. Certaines ne sont que des interfaces vers des librairies en C ou C++, ce qui implique souvent des étapes d&amp;rsquo;installation, voire de compilation. De plus on se heurte souvent à des conflits de version entre les librairies et Python lui-même, ce qui ne simplifie pas les choses. Enfin et surtout, un bon IDE (Environnement de Développement Intégré, à l&amp;rsquo;envers en anglais&amp;hellip;) est indispensable pour programmer au XXIème siècle.&lt;/p&gt;
&lt;p&gt;
 résout tout ces problèmes en proposant un installeur unique de la Parfaite Panoplie du Petit Programmeur Scientifique. Elle inclut:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
, évidemment (version 2.5.2 actuellement)&lt;/li&gt;
&lt;li&gt;
, le meilleur IDE de la Galaxie. Concu initialement pour Java, Eclipse permet de développer dans pratiquement tous les langages connus à l&amp;rsquo;aide de plugins.
est celui qui supporte Python.&lt;/li&gt;
&lt;li&gt;
, le &amp;ldquo;Minimalist GNU for Windows&amp;rdquo; qui comprend le célèbre compilateur C++ &amp;ldquo;GCC&amp;rdquo;. Grâce au plugin Eclipse
également fourni, Python(x,y) est donc en même temps un environnement de développement C++ très complet&lt;/li&gt;
&lt;li&gt;
pour exploiter
, le framework d&amp;rsquo;applications multiplateforme de Nokia. Intégré à Eclipse, l&amp;rsquo;ensemble permet de créer des GUI (Interfaces Utilisateur Graphiques, à l&amp;rsquo;envers en anglais)&lt;/li&gt;
&lt;li&gt;une myriade de librairies scientifiques pour le traitement du signal et d&amp;rsquo;images, le calcul symbolique, la visualisation graphique 2D et 3D, le calcul parallèle etc. La liste complète est
 et le tout est résumé dans ce beau &amp;ldquo;mind map&amp;rdquo; :&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2008/images/6d05e9aa0deff401627a1d6e6ceeabae_hu_5b6b5253ed0380f0.webp 320w, https://drgoulu.com/posts/2008/images/6d05e9aa0deff401627a1d6e6ceeabae_hu_ee4eb05afd00dd83.webp 480w, https://drgoulu.com/posts/2008/images/6d05e9aa0deff401627a1d6e6ceeabae_hu_568877ee7f7eca28.webp 706w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2008/images/6d05e9aa0deff401627a1d6e6ceeabae_hu_5b6b5253ed0380f0.webp"
width="706"
height="468"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Un avantage non négligeable de Python(x,y) est qu&amp;rsquo;elle est une oeuvre de Pierre Raybaut. Je ne le connais pas, mais c&amp;rsquo;est un français, donc toute la documentation et le support de la distribution sont dans la langue de Molière.&lt;/p&gt;
&lt;p&gt;Que vous vouliez vous initier à Python, simplement utiliser des libriaires qui vous donneront accès à un équivalent de Matlab ou vous lancer dans le développement d&amp;rsquo;une grosse application Python, je ne peux que vous recommander chaudement d&amp;rsquo;installer Python(x,y)&lt;/p&gt;</description></item><item><title>Python : un petit Sudoku pour commencer</title><link>https://drgoulu.com/2008/10/12/python/</link><pubDate>Sun, 12 Oct 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/10/12/python/</guid><description>&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2008/images/c2281c83670e31d8aaab7cb642b824db_hu_8f3a76d4d0cffefc.webp 320w, https://drgoulu.com/posts/2008/images/c2281c83670e31d8aaab7cb642b824db_hu_ff85c168c6ba8746.webp 480w, https://drgoulu.com/posts/2008/images/c2281c83670e31d8aaab7cb642b824db_hu_230bd27ab1f5d3ef.webp 601w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2008/images/c2281c83670e31d8aaab7cb642b824db_hu_8f3a76d4d0cffefc.webp"
width="601"
height="203"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
Ces temps-ci, je découvre
, un langage de programmation très apprécié en particulier dans la communauté scientifique. Ce &amp;ldquo;
&amp;rdquo; intègre des concepts développés dans plusieurs langages récents, ce qui en fait peut-être le langage le plus complet disponible actuellement.&lt;/p&gt;
&lt;p&gt;Pour une première approche de ce langage, je vous propose l&amp;rsquo;analyse du&amp;hellip;&lt;/p&gt;
&lt;h3 id="plus-court-solveurde-sudoku"&gt;Plus Court Solveur de Sudoku&lt;/h3&gt;
&lt;p&gt;Voici un  programme en Python de 173 caractères seulement qui serait le plus court
connu actuellement :&lt;/p&gt;
\[sourcecode lang="python"\]&lt;p&gt;def r(a): i=a.find(&amp;lsquo;0&amp;rsquo;) if i&amp;lt;0:print a &lt;/p&gt;
\[m in\[(i-j)%9\*(i/9^j/9)\*(i/27^j/27|i%9/3^j%9/3)or a\[j\]&lt;p&gt;for j in range(81)]or r(a&lt;/p&gt;
\[:i\]&lt;p&gt;+m+a&lt;/p&gt;
\[i+1:\]&lt;p&gt;)for m in`14**7*9`]r(raw_input())&lt;/p&gt;
\[/sourcecode\]&lt;p&gt;Ce programme est extrêmement compact et condensé, voire cryptique à l&amp;rsquo;instar des
. Ce n&amp;rsquo;est pas forcément la meilleure façon de programmer, mais ça révèle souvent la puissance cachée de certains langages. Ce programme est décrit en anglais et en détail
, mais voici son principe en gros et en français:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;def r(a): ... r(raw_input())&lt;/code&gt; // définit la fonction &amp;ldquo;r&amp;rdquo; qui résout le sudoku, puis on l&amp;rsquo;appelle en passant en paramètre ce que l&amp;rsquo;utilisateur a entré au clavier. Ca doit être une chaine de 81 caractères contenant ligne par ligne les chiffres de 1 à 9 donnés, et des 0 aux emplacements vides.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;i=a.find('0') if i&amp;lt;0:print a&lt;/code&gt; // au début de la fonction, on cherche le premier emplacement vide. Si on ne le trouve pas, on imprime le sudoku résolu&lt;/p&gt;
&lt;p&gt;la partie principale de la fonction utilise deux concepts puissants de Python:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;la &amp;ldquo;lazy evaluation&amp;rdquo; qui fait que l&amp;rsquo;expression &amp;ldquo;a or b&amp;rdquo; est équivalente à &amp;ldquo;if not(a):b&amp;rdquo;&lt;/li&gt;
&lt;li&gt;la &amp;ldquo;compréhension de liste&amp;rdquo; qui permet de créer une liste en écrivant une boucle à l&amp;rsquo;intérieur de
\[crochets\]. Par exemple &amp;ldquo;l =
\[x\*\*2 for x in range(10)\]&amp;rdquo; crée la liste des carrés des 10 premiers nombres entiers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ainsi cette expression &lt;code&gt;[(i-j)%9*(i/9^j/9)*(i/27^j/27|i%9/3^j%9/3)or a[j]for j in range(81)]&lt;/code&gt; fournit la &amp;ldquo;liste d&amp;rsquo;exclusion&amp;rdquo; contenant les chiffres qui ne peuvent pas figurer dans le trou à la position i. On l&amp;rsquo;obtient en parcourant toutes les celllules et en ajoutant à la liste la valeur des cases a&lt;/p&gt;
\[j\]&lt;p&gt; situées sur la même ligne, la même colonne ou dans le même bloc que i. Le grand test compliqué détermine ces conditions en utilisant les opérateurs modulo (%), ou binaire (|) et ou exclusif (^).&lt;/p&gt;
&lt;p&gt;Finalement, le &lt;code&gt;[m in [...] or r(a[:i]+m+a[i+1:])for m in`14**7*9`]&lt;/code&gt; remplit successivement la grille avec les chiffres possibles en utilisant la &amp;rsquo;lazy evaluation&amp;rsquo; une fois de plus : ce n&amp;rsquo;est que si le chiffre m n&amp;rsquo;est pas dans la liste d&amp;rsquo;exclusion qu&amp;rsquo;on execute la partie droite du or, laquelle appelle récursivement la fonction r en lui passant la grille en paramètre la grille &lt;code&gt;a[:i]+m+a[i+1:]&lt;/code&gt;. Ici , l&amp;rsquo;opérateur + sert à concaténer des listes : d&amp;rsquo;abord les i-èmes premières cases, puis le chiffre m proposé pour la case vide, puis les cases à partir de la i+1 ème.&lt;/p&gt;
&lt;p&gt;Ce programme utilise donc une approche &amp;ldquo;force brute&amp;rdquo; loin d&amp;rsquo;être optimale en temps de calcul : on essaie les chiffres possibles dans chaque case vide jusqu&amp;rsquo;à ce que ça marche.&lt;/p&gt;
&lt;p&gt;Reste à découvrir une astuce de geek que je ne connaissais pas : 14**7*9 vaut 948721536, un nombre qui contient les chiffres 123456789, dans le désordre, mais ça va aussi pour notre application. Les backquotes ´&amp;hellip;´ servent à former une chaine, comme d&amp;rsquo;ailleurs la fonction str(). L&amp;rsquo;avantage de ´14**7*9´sur ´123456789´ ? ben c&amp;rsquo;est évident : il faut deux bytes de moins &amp;hellip;&lt;/p&gt;</description></item><item><title>Sommes Egales de Nombres Premiers Consécutifs</title><link>https://drgoulu.com/2008/06/03/sommes-egales-de-nombres-premiers-consecutifs/</link><pubDate>Tue, 03 Jun 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/06/03/sommes-egales-de-nombres-premiers-consecutifs/</guid><description>&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2008/images/389c66e7ddab342c9a24fd6e80fd3c65_hu_fd262a323e2485f5.webp 320w, https://drgoulu.com/posts/2008/images/389c66e7ddab342c9a24fd6e80fd3c65_hu_b848df796048d1a5.webp 480w, https://drgoulu.com/posts/2008/images/389c66e7ddab342c9a24fd6e80fd3c65_hu_24c0678be981a15f.webp 512w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2008/images/389c66e7ddab342c9a24fd6e80fd3c65_hu_fd262a323e2485f5.webp"
width="512"
height="512"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
Le quatrième et dernier problème de la
mérite un article à lui tout seul. (J&amp;rsquo;ai parlé des trois autres dans
)&lt;/p&gt;
&lt;p&gt;Il s&amp;rsquo;agit de trouver le plus petit
P qui soit en même temps :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la somme de 9 nombres premiers consécutifs&lt;/li&gt;
&lt;li&gt;la somme de 119 nombres premiers consécutifs&lt;/li&gt;
&lt;li&gt;la somme de 215 nombres premiers consécutifs&lt;/li&gt;
&lt;li&gt;et la somme de 675 nombres premiers consécutifs !&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(les nombres 9, 119, 215 et 675 sont différents pour chaque concurrent&amp;hellip;)&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est étonnant, mais beaucoup de nombres premiers sont des sommes de nombres premiers consécutifs (abrégé SNPC ci après), par exemple :&lt;/p&gt;
&lt;p&gt;5+7+11+13+17 = 53 7+11+13+17+19 =67 11+13+17+19+23 =83&lt;/p&gt;
&lt;p&gt;De plus, il est fréquent qu&amp;rsquo;un même nombre premier soit égal à plusieurs SNPC. Par exemple sur
on mentionne:&lt;/p&gt;
&lt;p&gt;34421 = 269 + … + 709 (71 nombres premiers) 34421 = 1429 + … + 1571 (23 nombres premiers) 34421 = 3793 + … + 3853 (9 nombres premiers) 34421 = 4889 + … + 4937 (7 nombres premiers) 34421 = 11467 + … + 11483 (3 nombres premiers)&lt;/p&gt;
&lt;p&gt;Le nombre P recherché n&amp;rsquo;est donc peut-être pas très grand, d&amp;rsquo;autant que la somme des 675 premiers nombres premiers ne vaut que 1'578'242. Il n&amp;rsquo;y a probablement pas besoin de calculer en &amp;ldquo;bigint&amp;rdquo;, les entiers sur 32 bits, voire 64 disponibles avec n&amp;rsquo;importe quel langage de programmation devraient suffire. Par contre, il est pratique de disposer de fonctions prédéfinies pour manipuler des nombres premiers, c&amp;rsquo;est pourquoi j&amp;rsquo;ai choisi d&amp;rsquo;utiliser
.&lt;/p&gt;
&lt;p&gt;Les fonctions suivantes suffisent pour résoudre le problème posé: &lt;em&gt;(code modifié le 4/6/8 suite aux commentaires de b0z0)&lt;/em&gt;&lt;/p&gt;
\[gist id="0e35207dedf4e337c937"\]&lt;p&gt;La fonction SCP (Sum of Consecutive Primes) renvoie la somme des n nombres premiers consécutifs en commençant par le i-ème nombre premier en utilisant la fonction prédéfinie Prime&lt;/p&gt;
\[j\]&lt;p&gt; qui renvoie directement le j-ème nombre premier.&lt;/p&gt;
&lt;p&gt;Cette somme n&amp;rsquo;étant pas forcément un nombre premier, la fonction PSP (Prime Sum of Primes) appelle répétitivement SCP en augmentant i jusqu&amp;rsquo;à ce que la somme soit un nombre premier, vérifié grâce au test de primalité
, une fonction non triviale bien utile ici. Pour une raison expliquée plus bas, PSP renvoie une paire de résultats : la somme, et l&amp;rsquo;indice du premier nombre premier de la somme.&lt;/p&gt;
&lt;p&gt;Enfin, la fonction CPSP (Compound Prime Sum of Primes) implante l&amp;rsquo;algorithme que j&amp;rsquo;ai inventé pour la circonstance. Elle prend en paramêtre la liste des nombres de nombres premiers consécutifs sommés. Pour résoudre notre problème, on appellera  CPSP&lt;/p&gt;
\[{675, 215, 119, 9}\]&lt;ol&gt;
&lt;li&gt;on initialise une liste p avec les n résultats de PSP obtenus pour chacun des nombres de nombres premiers consécutifs à additioner. Ainsi, pour CPSP
\[{675, 215, 119, 9}\], p est initialisé à {{1583291,2},{149993,15},{41641,10},{127,2}}. Autrement dit, 1583291 est le plus petit nombre premier qui soit la somme de 675 nombres premiers consécutifs, et cette somme commence avec le 2ème nombre premier. 149993 est le plus petit nombre premier qui soit la somme de 215 nombres premiers, en commençant par le 15ème, et ainsi de suite&lt;/li&gt;
&lt;li&gt;par paresse (qualité indispensable chez les programmeurs&amp;hellip;) , la détection de la fin de l&amp;rsquo;algorithme est réduite au minimum vital : dès que la liste p n&amp;rsquo;est plus modifiée par l&amp;rsquo;algorithme, on arrête&lt;/li&gt;
&lt;li&gt;Pour chaque élément de la liste p en commençant par le deuxième, on regarde si la somme est inférieure à la somme du premier indice. Si c&amp;rsquo;est le cas, on calcule une somme supérieure en incrémentant l&amp;rsquo;indice correspondant, jusqu&amp;rsquo;à ce que la somme soit égale à la première, ou la dépasse. Après cette étape, la liste p devient {{1583291,10},{1600981,840},{1589563,1526},{1584829,15997}} : on voit que les sommes 2,3 et 4 ont dépassé la somme 1&lt;/li&gt;
&lt;li&gt;Si la somme 1 est plus petite que la somme 2, on augmente la somme 1 jusqu&amp;rsquo;à ce que&amp;rsquo;elle atteigne ou dépasse la somme 2. On arrive ainsi à {{1623917,10},{1600981,840},{1589563,1526},{1584829,15997}}. On boucle au point 2&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Les trois dernières boucles donnent les listes suivantes qui montrent bien le fonctionnement de l&amp;rsquo;algorithme:&lt;/p&gt;
&lt;p&gt;{{8256361,1127},{8112103,3883},{8115539,6728},{8112787,71376}} {{8275409,1130},{8259353,3947},{8264171,6833},{8256383,72536}} {{8275409,1130},{8275409,3954},{8275409,6841},{8275409,72696}}&lt;/p&gt;
&lt;p&gt;et voilà : 8'275'409 est égale à la somme des:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;675 nombres premiers consécutifs à partir du 1130-ème (9109)&lt;/li&gt;
&lt;li&gt;215 nombres premiers consécutifs à partir du 3954-ème (37339)&lt;/li&gt;
&lt;li&gt;119 nombres premiers consécutifs à partir du 6841-ème (68821)&lt;/li&gt;
&lt;li&gt;9 nombres premiers consécutifs à partir du 72696-ème (919421)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Quelques minutes pour choisir le bon outil (Mathematica) + quelques minutes de programmation + 30 secondes de calcul, c&amp;rsquo;est gagné !&lt;/p&gt;</description></item><item><title>Recrutement et Casse-Tête</title><link>https://drgoulu.com/2008/05/17/recrutement-et-casse-tete/</link><pubDate>Sat, 17 May 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/05/17/recrutement-et-casse-tete/</guid><description>&lt;p&gt;Si vous souhaitez travailler chez Google ou facebook, voici un petit tuyau : cultivez l&amp;rsquo;art de résoudre des casse-tête, et montrez vos talents sur internet.&lt;/p&gt;
&lt;p&gt;
, on testera votre raisonnement logique dès les premières minutes du premier interview téléphonique, puis on vous cuisinera sur de nombreux autres problèmes plus mathématico-informatiques lors des interviews suivants. En parallèle, vous recevrez un e-mail qui vous incitera à participer aux
, un site extraordinaire sponsorisé par de nombreuses entreprises qui recherchent à la fois des solutions originales à des problèmes très pointus et des développeurs de haut niveau. Un très bon endroit pour se faire remarquer (pas seulement par Google) si vous êtes un mordu d&amp;rsquo;algorithmes. Dommage qu&amp;rsquo;on doive s&amp;rsquo;engager à ne pas parler des problèmes à l&amp;rsquo;extérieur du site TopCoder, parce qu&amp;rsquo;ils sont très jolis.&lt;/p&gt;
&lt;p&gt;Google lance aussi des &amp;ldquo;chasses au trésor&amp;rdquo; sur internet. Là je viens de commencer à participer à
, qui commence très fort: si le robot ci-dessous ne peut aller que vers la droite ou vers le bas, combien y&amp;rsquo;a-t-il de chemins distincts qui le mènent au but ?&lt;/p&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2008/images/a257750efe5059e695eed9af28ef2bc4_hu_2c4d2a69bd9a618e.webp 320w, https://drgoulu.com/posts/2008/images/a257750efe5059e695eed9af28ef2bc4_hu_bbb066b352bf2cd7.webp 480w, https://drgoulu.com/posts/2008/images/a257750efe5059e695eed9af28ef2bc4_hu_5dde9e8079e39906.webp 548w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2008/images/a257750efe5059e695eed9af28ef2bc4_hu_2c4d2a69bd9a618e.webp"
width="548"
height="251"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Vous avez trouvé ? En comptant à la main ? Bien. Mais en fait, pour la chasse au trésor, il faut répondre pour un damier de 56x32 cases (le nombre change pour chaque participant) &amp;hellip; Dans ce cas, la réponse est 232059241971866600926656, ce qui suppose de
et de disposer d&amp;rsquo;une bonne calculatrice &amp;hellip;&lt;/p&gt;
&lt;p&gt;Si c&amp;rsquo;est facebook qui vous tente, il faut visiter
, chosir un des jolis problèmes qui s&amp;rsquo;y trouvent, le résoudre avec un programme en C++, Java, JavaScript, OCaml/SML, Perl, PHP ou Python, ce qui montre bien que les langages de programmation n&amp;rsquo;ont que peu d&amp;rsquo;importance pour ceux qui savent ce qu&amp;rsquo;est un algorithme, et que toutes ces jolis sites web ne sont que du vernis.  Ensuite, il faut envoyer la réponse à { (0xFACEB00C &amp;raquo; 2) en décimal } @ facebook.com.
.&lt;/p&gt;</description></item><item><title>Génération de polices bitmap de haute qualité</title><link>https://drgoulu.com/2008/05/10/imagemagick/</link><pubDate>Sat, 10 May 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/05/10/imagemagick/</guid><description>&lt;p&gt;Voici comment générer rapidement et automatiquement des polices de caractères bitmap avec canal alpha, donnant un anti-aliasing parfait quel que soit la texture de fond utilisée. Toutes les polices vectorielles peuvent être utilisées et combinées avec une infinité d&amp;rsquo;effets graphiques.
&lt;/p&gt;
&lt;p&gt;Le logiciel réalisant 99% du travail est 
, un programme de traitement d’images open-source gratuit que je considère comme un &amp;ldquo;Photoshop sans GUI&amp;rdquo; : aussi puissant que l&amp;rsquo;outil d&amp;rsquo;Adobe, ImageMagick s&amp;rsquo;utilise uniquement depuis un autre programme, voire simplement la ligne de commande du shell. A installer d&amp;rsquo;urgence.&lt;/p&gt;
&lt;p&gt;Voici par exemple le petit fichier batch qui crée quelques fichiers contenant des mots, dont le fichier font.png contenant le mot &amp;ldquo;font&amp;rdquo; de l&amp;rsquo;image ci-dessus :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@echo off rem Function: Create transparent background, aliased texts from a list of words rem Author: Philippe Guglielmetti rem Requires: ImageMagick v.6 or later (www.imagemagick.org) set texts=OK Abort Cancel font &amp;quot;This is Great !&amp;quot; set params=-background none -font Bauhaus-93 -pointsize 72 -density 300 -fill blue -blur 0x5 for %%a in (%texts%) do convert.exe %params% label:%%a %%a.png set texts= set params=&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Les &amp;ldquo;params&amp;rdquo; définissent la police à réaliser:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;-background none est essentiel pour dessiner la police sur un fond transparent (canal alpha)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;-font Bauhaus-93 définit la police vectorielle à utiliser (dont le nom n&amp;rsquo;est parfois pas identique à celui apparaissant dans le dossier &amp;ldquo;Fonts&amp;rdquo; de Windows&amp;hellip;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;-pointsize 72 -density 300 spécifient que la police doit faire 72pt de haut à 300dpi. La taille du bitmap sera donc supérieure à l&amp;rsquo;écran, mais il pourra être imprimé ou utilisé comme texture dans un jeu 3D ou une démo Demoniak3D avec un résultat d&amp;rsquo;excellente qualité&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2008/images/zoomo_hu_219ee9b15f2bcaa5.webp 320w, https://drgoulu.com/posts/2008/images/zoomo_hu_e0bea340ff0971e1.webp 320w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2008/images/zoomo_hu_219ee9b15f2bcaa5.webp"
width="320"
height="200"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
-fill blue -blur 0x5 sont deux petits effets de base : on remplit le caractère en bleu, et on adoucit le tracé de la lettre, qui est d&amp;rsquo;un pixel de noir par défaut. Ceci crée des pixels semi-transparents au bord des caractères, ce qui permet une découpe parfaite des caractères quel que soit le fond, comme on le voit sur le zoom ci-contre:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour placer la police sur la texture de fond afin de vérifier sa qualité, on utilise un autre module d&amp;rsquo;ImageMagick;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;composite.exe -tile back.png -compose Dst_Over font.png test.jpg&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Une fois ce test réalisé, on peut s&amp;rsquo;attaquer à la génération de tous les caractères de la police. Si seuls quelques caractères sont nécessaires, on peut utiliser le batch ci-dessus en définissant par exemple&lt;/p&gt;
&lt;p&gt;&lt;code&gt;set texts=0 1 2 3 4 5 6 7 8 9&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Mais ceci est fastidieux pour une police complète, et pour des raisons de programmation de l&amp;rsquo;application finale, il peut être utile de nommer les fichiers d&amp;rsquo;après le code ASCII de chaque caractère. Comme cette fonctionnalité n&amp;rsquo;est pas disponible dans le langage de commande Windows, il faut programmer ceci dans un langage évolué. Par exemple en LUA:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;params=&amp;quot;-background none -font Bauhaus-93 -pointsize 72 -density 300 -fill white -blur 0x5 &amp;quot; for i=32,167 do os.execute(&amp;quot;convert.exe &amp;quot;..params..&amp;quot;label:&amp;quot;..string.char(i)..&amp;quot; &amp;quot;..i..&amp;quot;.png&amp;quot;) end&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Ces 2 lignes génèrent automatiquement 130 fichiers de belles lettres prêtes à être utilisées comme textures dans votre jeu. A noter que ces fichiers pèsent déjà 10 Mb au total, soit plus que l&amp;rsquo;exécutable d&amp;rsquo;ImageMagick : il peut donc être intéressant d&amp;rsquo;inclure ImageMagick à votre produit et de l&amp;rsquo;utiliser pour créer les polices nécessaires lors de l&amp;rsquo;installation plutôt que d&amp;rsquo;alourdir votre distribution&amp;hellip;&lt;/p&gt;
&lt;p&gt;Enfin, si vous trouvez les polices ci-dessus un peu trop carrées, visitez 
 qui vous donnera une petite idée des effets possibles, et explorez 
 pour une vision plus complète.&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;</description></item><item><title>Google ouvre son infrastructure</title><link>https://drgoulu.com/2008/04/08/google-ouvre-son-infrastructure/</link><pubDate>Tue, 08 Apr 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/04/08/google-ouvre-son-infrastructure/</guid><description>&lt;p&gt;Stupéfaction : Google vient de permettre à 10'000 programmeurs d&amp;rsquo;utiliser
, un environnement permettant de développer (en Python) des applications qui fonctionneront directement sur les serveurs de Google, en utilisant certaines technologies propriétaires de Google, et tout ça gratuitement.&lt;/p&gt;
&lt;p&gt;Jusqu&amp;rsquo;ici, Google gardait jalousement sa technologie permettant de stocker et d&amp;rsquo;indexer pratiquement toute l&amp;rsquo;information du web sur des milliers d&amp;rsquo;ordinateurs disséminés à travers le monde. On connaissait cependant l&amp;rsquo;architecture et les principales briques du système :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;le
(GFS), permettant de gérer d&amp;rsquo;énormes fichiers répartis et redondants&lt;/li&gt;
&lt;li&gt;
, la base de données &amp;ldquo;orienté colonnes&amp;rdquo; et reposant sur GFS. Bigtable est utilisé par énormément d&amp;rsquo;applications Google, l&amp;rsquo;index du moteur de recherche n&amp;rsquo;étant pas le moindre : c&amp;rsquo;est Bigtable qui retrouve en quelques secondes toutes les pages internet contenant des mots donnés&amp;hellip;&lt;/li&gt;
&lt;li&gt;
 est un programme général permettant de faire simultanément 2 choses avec un très grand nombre de données : une transformation de chaque donnée (Map) et une agrégation des résultats (Reduce). MapReduce sert par exemple à compter le nombre de liens pointant vers chaque page (web link graph reversal), information utilisée pour calculée le
.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tout ceci est expliqué cette passionnante vidéo d&amp;rsquo;une heure, à regarder absolument si vous voulez comprendre.&lt;/p&gt;
&lt;div class="my-6 mx-auto" style="max-width: 640px; width: 100%;"&gt;
&lt;div class="w-full relative rounded-lg overflow-hidden shadow-md bg-black" style="padding-bottom: 56.25%; height: 0;"&gt;
&lt;iframe
src="https://www.youtube-nocookie.com/embed/oRwFpQKgRps"
title="YouTube video player"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
loading="lazy"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Pourquoi Google met-il ceci à disposition gratuitement ? Lorsqu&amp;rsquo;on sait qu&amp;rsquo; ils n&amp;rsquo;arrivent pas à recruter autant qu&amp;rsquo;ils aimeraient, que les 10'000 comptes ont été réservés en quelques minutes, et qu&amp;rsquo;ils ont les moyens de contrôler puis de racheter toute application intéressante qui résulterait de cette initiative, on peut commencer à apprécier ce coup à sa juste valeur&amp;hellip;&lt;/p&gt;
&lt;p&gt;sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Michael Arrington &amp;ldquo;
, TechCrunch, 5 avril 2008&lt;/li&gt;
&lt;li&gt;Fay Chang &amp;amp; al, &amp;ldquo;
&amp;rdquo;,
&lt;/li&gt;
&lt;li&gt;Jeffrey Dean and Sanjay Ghemawat, &amp;ldquo;
&amp;rdquo;, OSDI 2004&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Proce55ing</title><link>https://drgoulu.com/2008/04/03/processing/</link><pubDate>Thu, 03 Apr 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/04/03/processing/</guid><description>&lt;p&gt;
est un langage de programmation, et même un environnement de développement d&amp;rsquo;applications graphiques temps réel interactives. Créé initialement par
et
pour des applications de visualisation de données, Processing est également apprécié de créateurs comme qui en tirent des oeuvres graphiques magnifiques.&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;
de
Cliquez sur l&amp;rsquo;image pour la version interactive&lt;/em&gt;&lt;/p&gt;
\[vimeo 658158\]&lt;p&gt;&lt;em&gt;
de
musique &amp;ldquo;Lovely Head&amp;rdquo; de Goldfrapp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;La
réalisées avec Proce55ing est réellement impressionnante. On trouve beaucoup d&amp;rsquo;autres
ou sur flickr
ou
.&lt;/p&gt;
&lt;p&gt;
s&amp;rsquo;y est mis aussi et a achevé de me convaincre de regarder Processing de plus près.&lt;/p&gt;
&lt;p&gt;Le langage Processing est fortement inspiré de Java, le système de développement est basé sur Java, et on peut exporter les applications sous forme d&amp;rsquo;applet Java. Pour commencer, on peut se débrouiller sans maitriser cette danse, juste avec des bases de programmation, mais pour faire des choses aussi sophistiquées que les exemples ci-dessus, il faut bien connaitre le graphisme 2D et 3D, voire OpenGL et les maths, mais surtout avoir un talent de graphiste pour que le résultat soit joli.&lt;/p&gt;
&lt;p&gt;Ma première application Processing est une version simplifiée et 2D de ma fameuse
.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Mise à jour du 15.1.2011)&lt;/em&gt; : Elle était depuis longtemps sur
, mais je peux enfin l&amp;rsquo;intégrer directement à ce blog :&lt;/p&gt;
\[processing width="600" height="400" file="/wp-content/uploads/2008/04/Galaxy.jar"\]&lt;p&gt;Chargement&lt;/p&gt;
\[/processing\]&lt;p&gt;En pressant sur les touches curseur vous pourrez modifier l&amp;rsquo;ellipsité et la torsion de la galaxie en temps réel. Cette première oeuvre est assez moche, heureusement quelqu&amp;rsquo;un en a beaucoup amélioré l&amp;rsquo;esthétique
.&lt;/p&gt;
&lt;p&gt;Pour vous mettre à Processing vous aussi :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;lancez-vous à partir des nombreux exemples fournis&lt;/li&gt;
&lt;li&gt;consultez la liste des
pour éviter de réinventer la roue et devenir un vrai gourou&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Galaxie Spirale et Séquence Principale</title><link>https://drgoulu.com/2008/02/08/galaxie-spirale-et-sequence-principale/</link><pubDate>Fri, 08 Feb 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/02/08/galaxie-spirale-et-sequence-principale/</guid><description>&lt;p&gt;Suite à
, je m&amp;rsquo;étais lancé dans la réalisation d&amp;rsquo;une
en temps réel basée sur
.&lt;/p&gt;
&lt;p&gt;
L&amp;rsquo;idée était principalement d&amp;rsquo;illustrer le fait que les bras spiraux des galaxies ne tournent pas : se sont des &amp;ldquo;ondes de pression&amp;rdquo; dans lesquels la densité d&amp;rsquo;étoiles est plus élevée qu&amp;rsquo;ailleurs en raison du fait que les étoiles suivent &amp;ldquo;en moyenne&amp;rdquo; des orbites elliptiques décalées, comme illustré sur le graphique ci-contre, où les spirales apparaissent clairement.&lt;/p&gt;
&lt;p&gt;Je viens de réaliser une nouvelle version de cette simulation que vous pouvez
et exécuter sur votre propre PC (doté d&amp;rsquo;une carte 3D décente) pour voir 15'000 étoiles tourner devant vos yeux ébahis:&lt;/p&gt;
&lt;div class="my-6 mx-auto" style="max-width: 760px; width: 100%;"&gt;
&lt;div class="w-full relative rounded-lg overflow-hidden shadow-md bg-black" style="padding-bottom: 56.25%; height: 0;"&gt;
&lt;iframe
src="https://www.youtube-nocookie.com/embed/MzlJg_e6518"
title="YouTube video player"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
loading="lazy"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A noter qu&amp;rsquo;à ma connaissance c&amp;rsquo;est la seule simulation de Galaxie en temps réel qui révèle les bras spiraux. Ceci est possible car on ne simule pas la physique de la gravitation, mais seulement la géométrie en résultant.&lt;/p&gt;
&lt;h3 id="vie-et-mort-des-étoiles"&gt;Vie et mort des étoiles&lt;/h3&gt;
&lt;p&gt;Dans cette nouvelle version , j&amp;rsquo;ai commencé à implanter un autre phénomène fascinant : le cycle de vie des étoiles. Comme expliqué dans
, les étoiles naissent au rythme d&amp;rsquo;une par jour (!) dans la Voie Lactée, principalement dans les bras spiraux. Puis elles vieillissent et meurent (une par jour aussi !) après n&amp;rsquo;avoir effectué que quelques tours de la Galaxie. Pour visualiser ceci &amp;ldquo;à l&amp;rsquo;échelle&amp;rdquo; dans ma simulation, j&amp;rsquo;ai fait le calcul suivant :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ma galaxie contient environ 10^6 x moins d&amp;rsquo;étoiles qu&amp;rsquo;une galaxie spirale réelle (je veux un processeur 10'000'000 de fois plus puissant !)&lt;/li&gt;
&lt;li&gt;mais elle tourne environ 10^13 x plus vite&lt;/li&gt;
&lt;li&gt;donc les étoiles de ma simulation doivent naitre et mourir 10^(13-6) soit 10'000'000 x plus souvent qu&amp;rsquo;une fois par jour, ce qui fait 116 x par seconde !&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="la-séquence-principale"&gt;La séquence principale&lt;/h3&gt;
&lt;p&gt;La vie des étoiles se déroule de gauche à droite dans le diagramme ci-dessous:&lt;/p&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt="rtemagicc_hrgenericsml.jpg"
srcset="https://drgoulu.com/posts/2008/images/117e7e4fff1b044c8c45263bfcd691eb_hu_d71ae4adf6040cec.webp 320w, https://drgoulu.com/posts/2008/images/117e7e4fff1b044c8c45263bfcd691eb_hu_cfe89de4e41f1304.webp 450w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2008/images/117e7e4fff1b044c8c45263bfcd691eb_hu_d71ae4adf6040cec.webp"
width="450"
height="464"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Les étoiles supergéantes (
) naissent bleues. Après une vie brève passée à briller 10'000x plus que le Soleil, elles deviennent rouges et meurent brutalement en
, brillant comme des millions de soleils pendant quelques heures et laissant une étoile à neutrons, un
voire un
au centre d&amp;rsquo;une
&lt;/p&gt;
&lt;p&gt;Les étoiles naines restent toute leur longue vie bleues/blanches et jaunissent en s&amp;rsquo;éteignant lentement. 10'000x moins lumineuses que le Soleil, elles deviennent des naines brunes pratiquement invisibles.&lt;/p&gt;
&lt;p&gt;La plupart des étoiles, dont le Soleil, suivent la &amp;ldquo;séquence principale&amp;rdquo; : elles naissent bleues et lumineuses, et meurent rouges, tout en devenant 1 milliard de fois moins lumineuses qu&amp;rsquo;au début.&lt;/p&gt;
&lt;p&gt;Dans mon programme, je considère pour l&amp;rsquo;instant que toutes les étoiles suivent la séquence principale. Je simule le vieillissement en regroupant les étoiles en 6 étapes de la séquence. Il y a aussi une étape 0 &amp;ldquo;nébuleuse&amp;rdquo; qui correspond au gaz qui forme une étoile jeune et qui résulte de la mort de l&amp;rsquo;étoile vieille, ce qui permet de définir un cycle. Pour des raisons techniques et pour correspondre à la réalité, le nombre d&amp;rsquo;étoiles à chaque étape doit rester le même. La simulation permute donc 7 &amp;ldquo;étoiles&amp;rdquo; choisies au hasard dans chacune des étapes : une nébuleuse prise au hasard devient une bleue de type O5, une bleue O5 prise au hasard devient BO et ainsi de suite jusqu&amp;rsquo;à une étoile de type M0 prise au hasard, qui meurt pour donner une nébuleuse.&lt;/p&gt;
&lt;p&gt;Ainsi les étoiles vieillissent, mais pas toutes à la même vitesse, ce qui est conforme à la réalité.&lt;/p&gt;
&lt;h3 id="prochaines-étapes"&gt;Prochaines étapes:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;rendre les transitions de couleur plus douces&lt;/li&gt;
&lt;li&gt;faire naître les étoiles dans les bras spiraux : c&amp;rsquo;est là que ça se passe en réalité car les nébuleuses y sont &amp;ldquo;comprimées&amp;rdquo;&lt;/li&gt;
&lt;li&gt;simuler la trajectoire des étoiles du noyau galactique en 3D. permettre de varier la taille du noyau pour faire des galaxies elliptiques&lt;/li&gt;
&lt;li&gt;trouver comment faire des galaxies spirales &amp;ldquo;barrées&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="références"&gt;Références&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Cignatures</title><link>https://drgoulu.com/2008/02/05/cignatures/</link><pubDate>Tue, 05 Feb 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/02/05/cignatures/</guid><description>&lt;p&gt;Tombé par hasard sur
qui liste de minuscules programmes en C utilisés comme signatures d&amp;rsquo;e-mails par des programmeurs fous, ou de génie c&amp;rsquo;est la même chose. C est un langage de programmation tellement dense qu&amp;rsquo;il peut en devenir cryptique, ce qui fait qu&amp;rsquo;il est impossible de deviner ce que font ces programmes sans les lancer. Exemples:&lt;/p&gt;
\[code lang="C"\]&lt;p&gt;main(){char*i=&amp;ldquo;L0&lt;/p&gt;
\[B0BCA7G0BFACIW0BfRAAB0BCACAFR0\[BCAFE0LCCAFR0",j,k=0;for(;\*i; \*++i==48&amp;&amp;puts(""))do for(j=\*i-48&gt;&gt;k&amp;7;j--;)putchar(k+32);while(k^=3);}\[/code\]&lt;p&gt;fait :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ###
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ##### ##
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## ## ## ##
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## ## ## ## ### ####
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## ###### #### ## ## ##
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ## ## ## ## ## ## ####
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ##### ## ## ## ## ##
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ### ## ## ## ## ####
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Celui-ci fait un jeu de pendu dont la solution est le nom de l&amp;rsquo;auteur !&lt;/p&gt;
\[code lang="C"\]&lt;p&gt;main(){char s[]=&amp;quot;.bg`z`lE)gc`}{hD-|\/OI:retteL&amp;gt;nn&amp;rdquo;,k;long w=32,r,_,y ,i,b,g,p[]={63l&amp;laquo;16,37968,15,32,896,2048,24576,37449,2,12546,3074,19138 ,3586,585,0},t;b=g=r=0;while((b&amp;lt;7)&amp;amp;&amp;amp;(g&amp;lt;65278)){for(_=16;_+10;)putchar(_ &amp;ndash;&amp;gt;0?_&amp;amp;7?g&amp;raquo;_&amp;amp;1?s&lt;/p&gt;
\[\_\]&lt;p&gt;^9:46:w:s&lt;/p&gt;
\[\_+w\]&lt;p&gt;);while((k=getchar())&amp;lt;65);for(_=15,t= g;_;)if((s&lt;/p&gt;
\[\_--\]&lt;p&gt;^9|w)&lt;mark&gt;(k|w))g|=2&amp;laquo;_;if(t&lt;/mark&gt;g)r|=p&lt;/p&gt;
\[b++\]&lt;p&gt;;for(y=9,t=0;y&amp;ndash;;) for(_=9;_;)putchar(&amp;ndash;_?(i=p&lt;/p&gt;
\[y+6\]&lt;p&gt;&amp;raquo;24-3*_&amp;amp;7)?r&amp;raquo;t++&amp;amp;1?s&lt;/p&gt;
\[i+15\]&lt;p&gt;:w:w:10);}}&lt;/p&gt;
\[/code\]&lt;p&gt;&amp;gt;Letter:g&amp;mdash;- | : | O/ | I | | &amp;mdash;&amp;mdash;&lt;/p&gt;
&lt;p&gt;Martijn .ei.in.&lt;/p&gt;
&lt;p&gt;celui-ci&lt;/p&gt;
\[code lang="C"\]&lt;p&gt;int a&lt;/p&gt;
\[1817\]&lt;p&gt;;main(){int z=5,p=5,q=5,r=5; for(p=80;q+p-80;p-=2*a&lt;/p&gt;
\[p\]&lt;p&gt;)for(z=9;z&amp;ndash;;)q=3&amp;amp;(r=time(0) +r*57)/7,q=q?q-1?q-2?1-p%79?-1:0:p%79-77?1:0:p&amp;lt;1659?79:0:p&amp;gt;158?-79:0,q?!a&lt;/p&gt;
\[p+q\*2 \]&lt;p&gt;?a&lt;/p&gt;
\[p+=a\[p+=q\]&lt;p&gt;=q]=q:0:0;for(;q++-1817;)printf(q%79?&amp;quot;%c&amp;quot;:&amp;quot;%cn&amp;quot;,&amp;quot;#&amp;quot;&lt;/p&gt;
\[!a\[q-1\]&lt;p&gt;]);}&lt;/p&gt;
\[/code\]&lt;p&gt;fait un labyrinthe dans ce genre :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ######### ### ### ####### # # ### ### # # # ####### # # ######### ####### ###
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # ##### ####### ##### # ############# ####### # ####### ########### ####### #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # ### # # # ####### # ##### ### ### # ### ### ### ### ### # ### # # #####
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ####### ##### ### # # ##### # # # ####### ### ##### # # ### ######### ### # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ####### # # # ############### ####### # ##### # # # ####### ##### # # # ### #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ##### ### ##### # ######### ##### # # ####### ### ##### ### # # ### ### ### #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ##### # ####### # ##### # # ##### # ### # # ########### ### ### # ### #######
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # ####### ### # ### ##### # ##### ### ### ### # ### ### # # ##### # # ###
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # ### ### # ##### # # # ### ### ### ### ####### # ####### ### # # ####### # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ############# ####### # ##### ### ### ######### ##### # # # ##### # ### #####
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # # # # # # # # # # # # # # # # # # # # # # # # # #
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # ##### ##### ### ####### # ##### ##### # # # ##### ### ##### ######### # # #
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Une discipline particulière concerne l&amp;rsquo;ensemble de Mandelbrot :&lt;/p&gt;
\[code lang="C"\]&lt;p&gt;main(){char*c=&amp;quot; _.+=#n)rezneuM drahnreB(xx.xxx@xxx&amp;quot;;int x,t,y;float a, b,d;for(y=0;y&amp;lt;25;y++){for(x=0;x&amp;lt;80;x++){t=b=d=0;do{a=b*b-d*d-2.1+.035*x ;d=2*b*d+.088*y-1.1;b=a;t++;}while(t&amp;lt;32&amp;amp;&amp;amp;b*b+d*d&amp;lt;4);putchar(c&lt;/p&gt;
\[x&gt;79?6:y&gt; 23&amp;&amp;x&lt;28?34-x:t&gt;31?0:t&gt;&gt;4?5:t&gt;&gt;3?4:t&gt;&gt;2?3:t&gt;&gt;;1?2:1\]&lt;p&gt;);}}} /*xxx@xxx.xx*/&lt;/p&gt;
\[/code\]&lt;p&gt;donne :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_____________.................................++++++++==+++++++++...............
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;___________...............................+++++++++++++=#====+++++++............
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;__________............................++++++++++++++++=== ==+++++++++++.........
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_________..........................++++++++++++++++=### #=#=++++++++++........
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;________........................+++++++++++++++++++== ==+++++++++++......
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_______......................+++++++++++++=###=== =### ##=== ==++=#=+++.....
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;______....................++++++++++++++++==# # = ##+++++...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_____................+++++++++++++++++++===# #==++++++..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;____...........+++++++++==+++++=++++++====# #===++++..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;____.....++++++++++++++===##===##=======# #=+++++.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;____..+++++++++++++++++===# #== #=+++++.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;___.+++++++++++++++======# # #=+++++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;___+++++++=+++======= =+++++++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;___+++++++=+++======= =+++++++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;___.+++++++++++++++======# # #=+++++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;____..+++++++++++++++++===# #== #=+++++.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;____.....++++++++++++++===##===##=======# #=+++++.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;____...........+++++++++==+++++=++++++====# #===++++..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_____................+++++++++++++++++++===# #==++++++..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;______....................++++++++++++++++==# # = ##+++++...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_______......................+++++++++++++=###=== =### ##=== ==++=#=+++.....
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;________........................+++++++++++++++++++== ==+++++++++++......
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_________..........................++++++++++++++++=### #=#=++++++++++........
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;__________............................++++++++++++++++=== ==+++++++++++.........
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xxx@xxx.xx(Bernhard Muenzer)..............+++++++++++++=#====+++++++............
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;on peut même faire plus court :&lt;/p&gt;
\[code lang="C"\]&lt;p&gt;main(){int c;float t,x,y,b=-2,a=b;for(;b-=a&amp;gt;2?.1/(a=-2):0,b&amp;lt;2;putchar(30+ c),a+=.0503)for(x=y=c=0;++c&amp;lt;90&amp;amp;x*x+y*y&amp;lt;4;y=2*x*y+b,x=t)t=x*x-y*y+a;} &lt;/p&gt;
\[/code\]&lt;p&gt;Il y en a encore plein d&amp;rsquo;autres, mais mon préféré reste cet extraordinaire programme :&lt;/p&gt;
\[code lang="C"\]&lt;p&gt;int a&lt;/p&gt;
\[52514\]&lt;p&gt;,b,c=52514,d,e,f=1e4,g,h;main() {for(;b=c-=14;h=printf(&amp;quot;%04d&amp;quot;,e+d/f)) for(e=d%=f;g=&amp;ndash;b*2;d/=g)d=d*b+f*(h?a&lt;/p&gt;
\[b\]&lt;p&gt;:f/5),a&lt;/p&gt;
\[b\]&lt;p&gt;=d%&amp;ndash;g;}&lt;/p&gt;
\[/code\]&lt;p&gt;Que fait-il ? Je vous défie de le deviner.
&lt;/p&gt;
&lt;p&gt;Une description de l&amp;rsquo;algorithme utilisé est
&lt;/p&gt;</description></item><item><title>Perlisismes : les dictons informatiques d'Alan Perlis</title><link>https://drgoulu.com/2008/01/21/perlisismes-les-dictons-informatiques-dalan-perlis/</link><pubDate>Mon, 21 Jan 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/01/21/perlisismes-les-dictons-informatiques-dalan-perlis/</guid><description>&lt;figure class="alignright" style="max-width: 180px; width: 100%;"&gt;&lt;img src="https://drgoulu.com/posts/2008/images/729d55b21652db629f4b0da141be7852.gif" alt="Alan Jay Perlis" loading="lazy" class="rounded-lg shadow-sm w-full h-auto" /&gt;&lt;figcaption&gt;Alan Jay Perlis&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;En préparant un autre article, je suis tombé sur quelques citations d&amp;rsquo;
, un précurseur de la programmation et célèbre professeur à Carnegie Mellon et Yale. Les dictons informatiques dont il émaillait ses cours ont été publiés &lt;/p&gt;
\[1\]&lt;p&gt; et sont passés à la postérité sous le nom de &amp;ldquo;Perlisismes&amp;rdquo;, mais ne sont disponibles qu&amp;rsquo;en anglais. Ne les ayant pas trouvé en français, je me suis fendu (de rire) d&amp;rsquo;une traduction, en les reclassant par thèmes subjectifs et en les classant selon mes préférences. Régalez vous !&lt;/p&gt;
&lt;h2 id="philosophie"&gt;Philosophie&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;La constante d&amp;rsquo;une personne est la variable d&amp;rsquo;une autre.&lt;/li&gt;
&lt;li&gt;Les inconscients ignorent la complexité. Les pragmatistes en souffrent. Certains parviennent à l&amp;rsquo;éviter. Les génies la suppriment.&lt;/li&gt;
&lt;li&gt;En poursuivant l&amp;rsquo;inaccessible, la simplicité se trouve en travers du chemin.&lt;/li&gt;
&lt;li&gt;La simplicité ne précède pas la complexité, elle la suit.&lt;/li&gt;
&lt;li&gt;Vous ne pouvez pas communiquer la complexité, juste en faire prendre conscience.&lt;/li&gt;
&lt;li&gt;N&amp;rsquo;ayez pas de bonnes idées si vous n&amp;rsquo;êtes pas prêt à en être responsable.&lt;/li&gt;
&lt;li&gt;L&amp;rsquo;optimisation entrave l&amp;rsquo;évolution.&lt;/li&gt;
&lt;li&gt;Souvent les moyens justifient la fin : le but fait avancer la technique, et la technique survit même quand le but s&amp;rsquo;effondre.&lt;/li&gt;
&lt;li&gt;On ne peut pas aller de l&amp;rsquo;informel au formel par des moyens formels.&lt;/li&gt;
&lt;li&gt;Slogan pour un labo de recherche : Nous travaillons aujourd&amp;rsquo;hui sur ce à quoi d&amp;rsquo;autres vont penser demain (What we work on today, others will first think of tomorrow.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="informatique"&gt;Informatique&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Dans la symbiose homme-machine, c&amp;rsquo;est l&amp;rsquo;homme qui doit s&amp;rsquo;adapter parce que la machine ne peut pas.&lt;/li&gt;
&lt;li&gt;En informatique, les invariants sont éphémères.&lt;/li&gt;
&lt;li&gt;La preuve de la valeur d&amp;rsquo;un système informatique est son existence.&lt;/li&gt;
&lt;li&gt;Le contact prolongé avec les ordinateurs transforme les mathématiciens en comptables et vice versa.&lt;/li&gt;
&lt;li&gt;L&amp;rsquo;informatique (Computer Science) est gênée par les ordinateurs.&lt;/li&gt;
&lt;li&gt;L&amp;rsquo;ordinateur est le pollueur ultime : ses fèces sont indistinguables de la nourriture qu&amp;rsquo;il produit.&lt;/li&gt;
&lt;li&gt;Les systèmes ont des sous-systèmes, et les sous-systèmes ont des sous-sous-systèmes et ainsi de suite à l&amp;rsquo;infini. C&amp;rsquo;est la raison pour laquelle nous recommençons chaque fois de zéro.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="intelligence-artificielle"&gt;Intelligence artificielle&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Une année de travail sur l&amp;rsquo;intelligence artificielle est suffisante pour vous faire croire en Dieu.&lt;/li&gt;
&lt;li&gt;Dans un ordinateur, le langage naturel n&amp;rsquo;est pas naturel.&lt;/li&gt;
&lt;li&gt;Si votre ordinateur parle anglais, il a probablement été fabriqué au Japon.&lt;/li&gt;
&lt;li&gt;Quand nous écrivons des programmes qui &amp;ldquo;apprennent&amp;rdquo;, ce qui arrive c&amp;rsquo;est que nous apprenons, et eux pas.&lt;/li&gt;
&lt;li&gt;Il y aura toujours des choses que nous aimerions dire dans nos programmes, mais qui ne peuvent être que mal dites avec tous les langages connus.&lt;/li&gt;
&lt;li&gt;La seule théorie constructive liant les neurosciences et la psychologie surviendra de l&amp;rsquo;étude du logiciel.&lt;/li&gt;
&lt;li&gt;Le but de l&amp;rsquo;informatique est l&amp;rsquo;émulation de nos facultés de synthèse, pas la compréhension des facultés analytiques.&lt;/li&gt;
&lt;li&gt;L&amp;rsquo;ordinateur le plus important est celui qui bouillonne dans nos crânes et recherche de nouvelles satisfactions extérieures. La standardisation des ordinateurs serait un désastre, donc ça n&amp;rsquo;arrivera probablement pas.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="programmation"&gt;Programmation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Il y a deux manières d&amp;rsquo;écrire des programmes sans erreurs. Seule la troisième marche.&lt;/li&gt;
&lt;li&gt;Le 11ème commandement était &amp;ldquo;Tu programmeras&amp;rdquo; ou &amp;ldquo;Tu ne programmeras pas&amp;rdquo;, je ne me souviens plus au juste.&lt;/li&gt;
&lt;li&gt;Programmer est un acte contre nature.&lt;/li&gt;
&lt;li&gt;Tout programme a (au moins) deux buts : celui pour lequel il a été écrit, et celui pour lequel il ne l&amp;rsquo;a pas été.&lt;/li&gt;
&lt;li&gt;Il est plus facile de changer la spécification pour qu&amp;rsquo;elle corresponde au programme que le contraire.&lt;/li&gt;
&lt;li&gt;Adapter de vieux programmes à de nouvelles machines signifie habituellement adapter les nouvelles machines pour qu&amp;rsquo;elles se comportent comme les anciennes.&lt;/li&gt;
&lt;li&gt;En informatique, passer de l&amp;rsquo;évident à l&amp;rsquo;utile est une définition vivante du mot &amp;ldquo;frustration&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;La documentation est comme une assurance-vie : le bénéficiaire n&amp;rsquo;est presque jamais celui qui l&amp;rsquo;a signée.&lt;/li&gt;
&lt;li&gt;On ne manquera jamais de choses à programmer aussi longtemps qu&amp;rsquo;il y aura un seul programme.&lt;/li&gt;
&lt;li&gt;le meilleur livre grand public sur la programmation est &amp;ldquo;Alice au Pays des Merveilles&amp;rdquo;, parce que c&amp;rsquo;est le meilleur livre grand public sur tous les sujets.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="code"&gt;Code&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Chaque programme est un bout d&amp;rsquo;un autre programme qui convenait mal.&lt;/li&gt;
&lt;li&gt;Tout doit être construit de haut en bas (top-down), sauf la première fois.&lt;/li&gt;
&lt;li&gt;Si vous avez une fonction avec 10 paramètres, vous en avez probablement oublié.&lt;/li&gt;
&lt;li&gt;Un programme sans boucle et sans structure de donnée ne vaut pas la peine d&amp;rsquo;être écrit.&lt;/li&gt;
&lt;li&gt;Rendre quelque chose variable est facile. Le problème, c&amp;rsquo;est de contrôler la durée de la constance.&lt;/li&gt;
&lt;li&gt;A long terme, tout programme devient
, puis des gravats.&lt;/li&gt;
&lt;li&gt;La récursion est la racine du calcul car elle échange la description contre du temps.&lt;/li&gt;
&lt;li&gt;Un programme qui manipule un grand nombre de données le fait d&amp;rsquo;un petit nombre de manières.&lt;/li&gt;
&lt;li&gt;C&amp;rsquo;est mieux d&amp;rsquo;avoir 100 fonctions travaillant sur une structure de données que 10 fonctions pour 10 structures.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="programmeurs"&gt;Programmeurs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Une fois que vous comprenez comment écrire un programme, trouvez quelqu&amp;rsquo;un d&amp;rsquo;autre pour l&amp;rsquo;écrire.&lt;/li&gt;
&lt;li&gt;Pour comprendre un programme, vous devez devenir à la fois la machine et le programme.&lt;/li&gt;
&lt;li&gt;Il est plus facile d&amp;rsquo;écrire un programme incorrect que d&amp;rsquo;en comprendre un correct.&lt;/li&gt;
&lt;li&gt;Si votre interlocuteur hoche la tête pendant que vous lui expliquez votre programme, réveillez-le!&lt;/li&gt;
&lt;li&gt;Quand deux programmeurs se rencontrent pour critiquer leurs programmes, les deux sont silencieux.&lt;/li&gt;
&lt;li&gt;Peut-être que si nous écrivions des programmes depuis notre enfance, nous pourrions les lire à l&amp;rsquo;age adulte.&lt;/li&gt;
&lt;li&gt;En programmation, tout ce que nous faisons est un cas particulier de quelque chose de plus général, et souvent nous nous en apercevons très vite.&lt;/li&gt;
&lt;li&gt;Vous pouvez mesurer les perspectives d&amp;rsquo;avenir d&amp;rsquo;un programmeur par son attitude par rapport à la vitalité de FORTRAN.&lt;/li&gt;
&lt;li&gt;Il ne faut pas évaluer les programmeurs par leur ingéniosité ou leur logique, mais par l&amp;rsquo;étendue (completeness) de leur étude de cas (case analysis).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="langages"&gt;Langages&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Il ne vaut pas la peine de connaitre un langage qui ne modifie pas votre façon de penser la programmation.&lt;/li&gt;
&lt;li&gt;Certains langages de programmation arrivent à absorber des changements, mais résistent au progrès.&lt;/li&gt;
&lt;li&gt;Sur une période de 5 ans on trouve un superbe langage de programmation. Mais on ne sait pas quand cette période de 5 ans aura lieu.&lt;/li&gt;
&lt;li&gt;Un langage de programmation est &amp;ldquo;bas niveau&amp;rdquo; quand il nécessite de faire attention à ce qui n&amp;rsquo;a aucune importance.&lt;/li&gt;
&lt;li&gt;Un bon système ne peut pas avoir un langage de commande faible.&lt;/li&gt;
&lt;li&gt;Si quelqu&amp;rsquo;un dit &amp;ldquo;je veux un langage de programmation dans lequel je n&amp;rsquo;aurais qu&amp;rsquo;à dire ce qui doit être fait&amp;rdquo;, donnez lui une sucette.&lt;/li&gt;
&lt;li&gt;Alors que les chinois devraient adorer
, ils investissent dans FORTRAN.&lt;/li&gt;
&lt;li&gt;Un programmeur LISP connait la valeur de tout, mais le cout (cost) de rien.&lt;/li&gt;
&lt;li&gt;Au cours des siècles, les Indiens ont développé un langage de signes pour communiquer des phénomènes intéressants. les programmeurs des différentes tribus (FORTRAN, LISP, ALGOL, SNOBOL, etc.) auraient pu en utiliser un pour éviter de transporter un tableau noir sur leur poneys.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="bons-conseils"&gt;Bons conseils:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;la symétrie est un concept réduisant la complexité : utilisez la partout.&lt;/li&gt;
&lt;li&gt;Entrez tôt dans une routine : faites la même chose de la même façon. Accumulez les tournures (idioms). Standardisez. la seule différence (!) entre Shakespeare et vous est la liste de ses tournures, pas la taille de son vocabulaire.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="enseignement"&gt;Enseignement&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Enseigner la programmation va à l&amp;rsquo;encontre de l&amp;rsquo;éducation moderne : Quel est le plaisir à planifier, se discipliner à organiser ses pensées, faire attention aux détails et apprendre à être autocritique ?&lt;/li&gt;
&lt;li&gt;On n&amp;rsquo;apprend pas l&amp;rsquo;informatique avec une calculatrice de poche, mais on peut oublier l&amp;rsquo;arithmétique.&lt;/li&gt;
&lt;li&gt;La plupart des gens trouvent le concept de la programmation évident, mais la réalisation impossible.&lt;/li&gt;
&lt;li&gt;Tout le monde peut apprendre à sculpter : on aurait du dire à
comment ne pas le faire.  C&amp;rsquo;est la même chose avec les grands programmeurs. &lt;em&gt;(édité le 23.11.11 à partir de WikiQuote)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Vous croyez savoir quand vous apprenez, vous en êtes sur quand vous écrivez, persuadé quand vous enseignez, mais certain seulement quand vous programmez.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="jeux-de-mots-intraduisibles"&gt;Jeux de mots intraduisibles&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Syntactic sugar causes cancer of the semicolon. (Le
cause le cancer du point-virgule)&lt;/li&gt;
&lt;li&gt;Editing is a rewording activity. (L&amp;rsquo;édition est une activité de rephrasage (rewOrding) récompensante (rewArding))&lt;/li&gt;
&lt;li&gt;Like punning, programming is a play on words.&lt;/li&gt;
&lt;li&gt;In software systems, it is often the early bird that makes the worm.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous trouverez encore sur
que je n&amp;rsquo;ai pas traduits, soit parce que je ne les trouvais pas terribles, soit parce que je ne les ai pas compris &amp;hellip;&lt;/p&gt;
&lt;h2 id="référence-"&gt;Référence :&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
\[altmetric doi="10.1145/947955.1083808" float="right"\]Alan J. Perlis &amp;ldquo;
&amp;rdquo;, SIGPLAN Notices Vol. 17, No. 9, September 1982, pages 7 - 13 
&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Bugman blogifié</title><link>https://drgoulu.com/2008/01/12/bugman-bientot-blogifie/</link><pubDate>Sat, 12 Jan 2008 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2008/01/12/bugman-bientot-blogifie/</guid><description>&lt;p&gt;Depuis longtemps je suis un fan du
, un incroyable ramassis de choses épatantes sur des sujets comme la physique, les maths, les fractales et les papillons, le tout illustré par de magnifiques images et animations faites avec
et
principalement.&lt;/p&gt;
&lt;p&gt;Le seul problème est que ce site était devenu affreusement lourd, à la fois graphiquement et par la taille des énormes pages sur lesquelles on frisait l&amp;rsquo;indigestion à la première visite et on ne retrouvait plus rien à la seconde&amp;hellip;&lt;/p&gt;
&lt;p&gt;Je me suis donc mis à &amp;ldquo;forcer la main&amp;rdquo; de Paul en lui créant un
qui lui a beaucoup plu, et sur lequel je vais l&amp;rsquo;aider à migrer tout son passionnant contenu.&lt;/p&gt;
&lt;p&gt;Abonnez-vous à
pour suivre toutes les choses merveilleuses qui vont être (re) publiées sur le blog deBugman, vous ne le regretterez pas !&lt;/p&gt;
&lt;p&gt;Quelques exemples accessibles via les jolis gif animés ci dessous :&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;</description></item><item><title>La montée en puissance des GPUs</title><link>https://drgoulu.com/2007/11/02/la-montee-en-puissance-des-gpus/</link><pubDate>Fri, 02 Nov 2007 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2007/11/02/la-montee-en-puissance-des-gpus/</guid><description>&lt;p&gt;Dans les ordinateurs vendus depuis 2003 environ, le microprocesseur (CPU) fourni par Intel ou AMD n&amp;rsquo;est plus le composant le plus puissant, et souvent plus le plus couteux non plus. Désormais c&amp;rsquo;est le GPU, le Graphics Processing Unit, qui détermine largement la puissance d&amp;rsquo;un PC. Strictement limités au graphisme il y a peu, ces processeurs sont désormais capables d&amp;rsquo;effectuer certains calculs nettement plus vite que les processeurs classiques. Actuellement, la puissance de calcul du G80 de nVidia est 5 à 6 fois supérieure à celle du Core 2 Duo d&amp;rsquo;Intel, voire plus (1, 2).&lt;/p&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt="img0019319.jpg"
srcset="https://drgoulu.com/posts/2007/images/92d9996311ff6934d737ff74313187d6_hu_5e8f21c0ed4dd39.webp 320w, https://drgoulu.com/posts/2007/images/92d9996311ff6934d737ff74313187d6_hu_dd5ef2d1cce7eb8.webp 480w, https://drgoulu.com/posts/2007/images/92d9996311ff6934d737ff74313187d6_hu_a5bc6d76c9befdfa.webp 542w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2007/images/92d9996311ff6934d737ff74313187d6_hu_5e8f21c0ed4dd39.webp"
width="542"
height="316"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
&lt;em&gt;puissance de calcul des GPU et CPU (
)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="conséquence-immédiate-"&gt;Conséquence immédiate :&lt;/h3&gt;
&lt;p&gt;Si vous achetez un ordinateur pour y faire fonctionner les applications les plus exigeantes, c&amp;rsquo;est-à-dire les jeux vidéo, il faut faire plus attention au choix du GPU qu&amp;rsquo;au CPU. Vous ne gagnerez que quelques pourcents de performance avec un CPU plus rapide qui vous coûtera quelques centaines de francs, alors que la même somme investie dans une carte graphique basée sur un GPU plus récent ou puissant peut doubler le nombre d&amp;rsquo;images / seconde (fps) de vos applications favorites.&lt;/p&gt;
&lt;h3 id="un-peu-darchitecture-des-processeurs"&gt;Un peu d&amp;rsquo;architecture des processeurs&lt;/h3&gt;
&lt;p&gt;Cette situation est la conséquence de cahiers des charges différents assignés aux deux composants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;le CPU est &amp;ldquo;généraliste&amp;rdquo; : il doit être capable d&amp;rsquo;exécuter plusieurs programmes différents quasi simultanément, de réagir aux actions de l&amp;rsquo;utilisateur et de gérer les nombreux périphériques de l&amp;rsquo;ordinateur, fonctionnant à des vitesses différentes&lt;/li&gt;
&lt;li&gt;le GPU est historiquement spécialisé : sa tâche est de produire des images à une cadence régulière, ce qu&amp;rsquo;il peut faire en exécutant le même programme simple sur des données différentes, correspondant par exemple à des objets 3D distincts ou à des portions distinctes de l&amp;rsquo;écran.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ceci a conduit à des architectures différentes pour les deux types de processeurs :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les CPU comportent aujourd&amp;rsquo;hui 2 ou 4 &amp;ldquo;coeurs&amp;rdquo; complexes accédant aux données à travers une grande mémoire cache, le tout synchronisé par une importante logique de contrôle&lt;/li&gt;
&lt;li&gt;Sur la même surface de silicium, un GPU moderne contient jusqu&amp;rsquo;à 128 unités de calcul simples, mais très peu de mémoire cache et de logique de contrôle.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt="img0019320.jpg"
srcset="https://drgoulu.com/posts/2007/images/5f8d34d07bdd8aff1ff47d09bf9b05a5_hu_a977ad561a2c0959.webp 320w, https://drgoulu.com/posts/2007/images/5f8d34d07bdd8aff1ff47d09bf9b05a5_hu_dd993cf6cd5c6a33.webp 477w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2007/images/5f8d34d07bdd8aff1ff47d09bf9b05a5_hu_a977ad561a2c0959.webp"
width="477"
height="186"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;architecture des GPU et CPU (
)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cette différence d&amp;rsquo;architecture fait qu&amp;rsquo;il n&amp;rsquo;est pas possible d&amp;rsquo;exécuter sur le GPU un programme &amp;ldquo;classique&amp;rdquo;, écrit pour le CPU car:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les unités de calcul (ALU) du GPU sont individuellement moins puissantes qu&amp;rsquo;un coeur de CPU.&lt;/li&gt;
&lt;li&gt;Un GPU est un processeur SIMD, ou &amp;ldquo;Single Instruction Multiple Data&amp;rdquo; : toutes les ALU d&amp;rsquo;un GPU doivent exécuter le même programme en même temps, alors que chaque coeur de CPU peut exécuter des programmes distincts de façon asynchrone (MIMD)&lt;/li&gt;
&lt;li&gt;les échanges de données entre les ALU de GPU sont beaucoup plus limités qu&amp;rsquo;entre des coeurs de CPU&lt;/li&gt;
&lt;li&gt;la structure &amp;ldquo;pipeline&amp;rdquo; des GPU fait que leurs performances sonttrès dégradées dès qu&amp;rsquo;il y a des tests dans le programme. Il faut programmer les GPU sans &amp;ldquo;if &amp;hellip; then .. &amp;quot; !&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La principale conséquence de ces différences hardware est que les langages de programmation usuels ne sont pas adaptés à la programmation des GPU. Des langages spécifiques ont été définis, initialement pour la programmation des &amp;ldquo;shaders&amp;rdquo;, programmes réalisant tous les effets graphiques des cartes modernes. Mais ces langages permettent aussi la &amp;ldquo;programmation générale des GPU&amp;rdquo; (ou
), dont j&amp;rsquo;ai déjà parlé
,
, et
:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;nVidia a défini le langage
comme &amp;ldquo;C pour graphiques&amp;rdquo;&lt;/li&gt;
&lt;li&gt;ATI a plutôt soutenu le standard
défini par le standard
&lt;/li&gt;
&lt;li&gt;Microsoft a encore une fois grandement contribué aux progrès de l&amp;rsquo;humanité en dotant son système maison Direct3D d&amp;rsquo;un langage de shader dont l&amp;rsquo;innovation essentielle consiste à changer une lettre au standard . C&amp;rsquo;est HLSL. (Non, pas de lien pour eux, z&amp;rsquo;avez qu&amp;rsquo;à chercher.)&lt;/li&gt;
&lt;li&gt;nVidia a par contre fait un réel pas en avant en proposant son système
 qui permet de développer directement ses GPU haut de gamme en C &amp;ldquo;classique&amp;rdquo; , à l&amp;rsquo;aide de librairies spécifiques.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="perspectives"&gt;Perspectives&lt;/h3&gt;
&lt;p&gt;Du point de vue matériel, les processeurs du futur combineront sans doute les avantages respectifs des GPU et des CPU. Voici la stratégie probable des principaux acteurs du marché :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Après le rachat d&amp;rsquo;ATI, AMD a tout en main pour combiner les deux types de processeurs de façon optimale&lt;/li&gt;
&lt;li&gt;intel, dont les GPUs ont des performances lamentables, essaie de multiplier le nombre de coeurs de ses CPU tout en s&amp;rsquo;inspirant de certaines techniques des GPU&lt;/li&gt;
&lt;li&gt;nVidia va logiquement tenter de généraliser ses GPU pour leur permettre d&amp;rsquo;exécuter du code de CPU&lt;/li&gt;
&lt;li&gt;On l&amp;rsquo;oublie souvent, mais le processeur
  d&amp;rsquo;IBM développé en collaboration avec Toshiba et Sony pour la Playstation 3 est probablement le précurseur de cette nouvelle génération de processeurs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Du point de vue logiciel, deux tendances s&amp;rsquo;affrontent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la définition de langages spécifiques comme GLSL, ou prenant en compte explicitement le parallélisme à la manière des librairies de multithreading existantes&lt;/li&gt;
&lt;li&gt;le développement de compilateurs capables de générer du code GPU optimisé à partir de sources en langages classiques, à la manière de CUDA&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il est probable que dans un premier temps les langages comme GLSL jouent le rôle d&amp;rsquo; &amp;ldquo;assembleur des GPU&amp;rdquo; utilisé pour la création de librairies, que des applications en C utiliseront de manière transparente.&lt;/p&gt;
&lt;h3 id="sources"&gt;Sources:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Damien Triolet &amp;ldquo;
&amp;rdquo;, BeHardware, March 21, 2007&lt;/li&gt;
&lt;li&gt;Jean Etienne, &amp;ldquo;
&amp;rdquo;, Futura-Sciences, 31 octobre 2007&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>La bonne manière de calculer des trucs</title><link>https://drgoulu.com/2007/10/11/la-bonne-maniere-de-calculer-des-trucs/</link><pubDate>Thu, 11 Oct 2007 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2007/10/11/la-bonne-maniere-de-calculer-des-trucs/</guid><description>&lt;p&gt;
 est une page pour informaticiens dans mon genre : elle contient des petits &amp;ldquo;snippets&amp;rdquo; de code utile pour contourner certains pièges tendus par les maths et la géométrie.&lt;/p&gt;
&lt;p&gt;Par exemple, si on veut calculer sin(x)/x, il faut faire attention à ce qui se passe pour x=0, sinon on obtiendra une erreur de &amp;ldquo;division by zero&amp;rdquo; au lieu du résultat attendu, qui est 1. Un bon programmeur prévoira le coup en écrivant (en C++) :&lt;/p&gt;
\[sourcecode lang="cpp"\]&lt;p&gt;if (x == 0.) return 1. else return sin(x)/x;&lt;/p&gt;
\[/sourcecode\]&lt;p&gt;mais ce n&amp;rsquo;est peut-être pas suffisant. Si x est très petit, la division de deux nombres très petits approximés par nos chers ordinateurs a des chances d&amp;rsquo;être assez fausse. Pour des raisons expliquées en détail sur la page, il faut s&amp;rsquo;assurer en fait que x2 est encore un nombre numériquement assez grand par rapport à 1, donc un très bon programmeur écrira ceci :&lt;/p&gt;
\[sourcecode lang="cpp"\]&lt;p&gt;if (1. + x*x == 1.) return 1. else return sin(x)/x;&lt;/p&gt;
\[/sourcecode\]&lt;p&gt;ce qui parait mathématiquement absurde puisqu&amp;rsquo;on imagine pas que 1+x2 puisse valoir 1 pour x≠0. Mais informatiquement, c&amp;rsquo;est très possible.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;article donne ainsi une série de recettes pour calculer des expressions dangereuses, par exemple :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1-cos(x) → 2*sin(x/2)2&lt;/li&gt;
&lt;li&gt;acos(1-x) → 2*asin(sqrt(x/2))&lt;/li&gt;
&lt;li&gt;et bien d&amp;rsquo;autres&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mais les recettes les plus intéressantes (en tout cas pour moi) concernent la géométrie.&lt;/p&gt;
&lt;p&gt;Pour calculer l&amp;rsquo;angle entre 2 vecteurs u et v, l&amp;rsquo; &amp;ldquo;approche pachyderme&amp;rdquo; comme disait Burgi consiste à évaluer acos(dot(u,v)), dot étant la fonction renvoyant le produit scalaire des 2 vecteurs. mais si u ou v ne sont pas parfaitement normalisés et que dot renvoie un résultat un pouillème plus grand que 1 : crash.&lt;/p&gt;
&lt;p&gt;une deuxième approche est: 2*atan2(abs(u-v),abs(u+v)). Pas mal mais couteux en temps de calcul. La meilleure implémentation est&lt;/p&gt;
\[sourcecode lang="cpp"\]&lt;p&gt;if (dot(u,v) &amp;lt; 0.) return M_PI - 2*asin(abs(-v-u)/2) else return 2*asin(abs(v,u)/2);&lt;/p&gt;
\[/sourcecode\]&lt;p&gt;La partie vraiment intéressante concerne l&amp;rsquo;
. (&lt;em&gt;Comme c&amp;rsquo;est assez spécifique à la 3D, je publie aussi ce qui suit
&lt;/em&gt; )&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;orientation d&amp;rsquo;un corps dans l&amp;rsquo;espace à 3 dimension est défini par 3 angles tout comme la position d&amp;rsquo;un objet posé sur une sphère est définie par les 2 angles de latitude et de longitude, plus un angle définissant l&amp;rsquo;orientation de l&amp;rsquo;objet&lt;/p&gt;
&lt;p&gt;Le problème consistant à faire tourner &amp;ldquo;en douceur&amp;rdquo; un objet dans l&amp;rsquo;espace pour l&amp;rsquo;amener dans une orientation déterminée est appelé &amp;ldquo;interpolation sphérique linéaire&amp;rdquo; parce qu&amp;rsquo;il est équivalent à celui consistant à se déplacer &amp;ldquo;en douceur&amp;rdquo; sur une sphère pour atteindre une position et une orientation donnée. Le problème n&amp;rsquo;est pas trivial pour 2 raisons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;comme les angles sont définis &amp;ldquo;modulo 360°&amp;rdquo;, il faut que l&amp;rsquo;interpolation en tienne compte : si on va par exemple de la longitude -179° à la longitude +179°, il faut faire 2° dans le sens négatif et pas 358° dans le sens positif.&lt;/li&gt;
&lt;li&gt;quelle que soit la manière dont on définit les 3 angles, il existe des &amp;ldquo;singularités&amp;rdquo; aux point analogues aux pôles : à la lattitude 90°, la longitude n&amp;rsquo;a plus d&amp;rsquo;importance mais si on passe par le pôle, il faut &amp;ldquo;se rappeler&amp;rdquo; de notre dernière longitude pour pouvoir continuer &amp;ldquo;tout droit&amp;rdquo; dans la longitude augmentée de 180° (modulo 360°), et simultanément éviter qu&amp;rsquo;une mauvaise description de l&amp;rsquo;angle d&amp;rsquo;orientation nous fasse faire brusquement un demi-tout sur nous mêmes en passant par le pôle pour conserver un angle par rapport au nord &amp;hellip;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;ldquo;
&amp;rdquo; décrit la fonction &amp;ldquo;slerp&amp;rdquo;
qui définit l&amp;rsquo;interpolation sphérique linéaire entre 2 vecteurs unitaires v0, v1 ainsi:&lt;/p&gt;
&lt;p&gt;                  &lt;code&gt;sin((1-t)*a)        sin(t*a) slerp(v0,v1,t) = ______________*v0 + __________*v1 sin(a)             sin(a)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;où a est l&amp;rsquo;angle entre v0 et v1 calculé comme indiqué plus haut. Mais il est clair que pour des angles tels que sin(a) est nul ou très petit, des problèmes numériques vont survenir. En travaillant un peu la fonction slerp peut s&amp;rsquo;écrire:&lt;/p&gt;
&lt;p&gt;                  &lt;code&gt;sin_over_x((1-t)*a)            sin_over_x(t*a) slerp(v0,v1,t) = ____________________*(1-t)*v0 + ________________*t*v1 sin_over_x(a)                 sin_over_x(a)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;où sin_over_x est la fonction sin(x)/x calculée de façon robuste, toujours comme indiqué plus haut&lt;/p&gt;
&lt;p&gt;Reste à traiter le cas ou a est proche de 180°, ce qui revient à retourner un objet, ou à aller aux antipodes du point où on se trouve sur le globe. Il y a alors une infinité de trajets possibles, et il faut bien en choisir un plutôt que de laisser l&amp;rsquo;ordinateur se planter&amp;hellip;&lt;/p&gt;
&lt;h3 id="références"&gt;Références:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span id="ref-1"&gt;&lt;/span&gt;Ken Shoemake, &lt;em&gt;Animating rotation with quaternion curves,&lt;/em&gt; SIGGraph &amp;lsquo;85 proceeding&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Lua, le nouveau Basic</title><link>https://drgoulu.com/2007/09/21/lua-le-nouveau-basic/</link><pubDate>Fri, 21 Sep 2007 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2007/09/21/lua-le-nouveau-basic/</guid><description>&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;Me suis mis à programmer un peu en
, un &amp;ldquo;langage de script&amp;rdquo;
, mais aussi par Hyperion.&lt;/p&gt;
&lt;p&gt;LUA présente plusieurs caractéristiques étonnantes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;il est très rapide, presque autant que JAVA mais environ 6x plus que Python ou 15x plus que PHP (voir
par exemple)&lt;/li&gt;
&lt;li&gt;l&amp;rsquo;interpréteur LUA est très petit : moins de 100k, contre 800k pour Python et beaucoup plus pour les autres langages.&lt;/li&gt;
&lt;li&gt;LUA est à la fois un langage très simple, genre &amp;ldquo;Basic des années 80&amp;rsquo;&amp;rdquo;, et offre des notions beaucoup plus avancées décrites plus bas&lt;/li&gt;
&lt;li&gt;LUA est le premier langage de programmation brazilio-catholique : il a été créé à la
et est donc mieux documenté en portugais qu&amp;rsquo;en français.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="outils"&gt;Outils&lt;/h3&gt;
&lt;p&gt;Télécharger LUA depuis le site
ne sert à rien, à moins que vous aimiez programmer dans une fenêtre DOS&amp;hellip;&lt;/p&gt;
&lt;p&gt;Le mieux est de vous initier à LUA avec
un petit IDE simple mais avec ce qu&amp;rsquo;il faut pour éditer, compiler et déboguer du code LUA. Comme l&amp;rsquo;interpréteur LUA est tout petit, il est fourni avec !&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai investigué d&amp;rsquo;autres environnements de développement LUA, y compris certains censés s&amp;rsquo;intégrer au Microsoft Visual Studio, mais aucun n&amp;rsquo;a fonctionné correctement :-(&lt;/p&gt;
&lt;h3 id="un-langage-très-simple"&gt;Un langage (très) simple&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;En LUA comme avec beaucoup de langages de script, les variables peuvent prendre n&amp;rsquo;importe quel type sans déclaration préalable : &lt;code&gt;a=1 -- un nombre entier a=3.14 -- un nombre réel a=&amp;quot;hello&amp;quot; -- une chaine&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;comme Pascal, LUA veut qu&amp;rsquo;on ferme les blocs avec end: &lt;code&gt;function chose(x) if x&amp;lt;10 then return x+10 else return x end end while not quelque do for i=debut,fin do quelque=chose(i) end end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;voilà, vous savez tout ce qu&amp;rsquo;il faut pour programmer en LUA ;-). En fait, toutes les fonctions de LUA permettant de faire des choses utiles proviennent de
comme math, os et string, ou d&amp;rsquo;extensions programmées en C comme celles développées dans le cadre du
.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="subtilités"&gt;Subtilités&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Les variables non initialisées valent &amp;ldquo;nil&amp;rdquo;. On peut tester si une variable vaut nil.&lt;/li&gt;
&lt;li&gt;On peut appeler une fonction avec moins de paramètres qu&amp;rsquo;elle n&amp;rsquo;en accepte. Les paramètres surnuméraires servent donc de paramètres optionnels et prennent la valeur nil, donc on peut leur affecter une valeur par défaut&amp;hellip;&lt;/li&gt;
&lt;li&gt;Les fonctions peuvent être référencées par des variables: &lt;code&gt;function sinus(x) return math.sin(x) end function tabule(f,de,a,pas) -- le paramètre f est une fonction ! for i=de,a,pas do print(i,f(i)) end end tabule(sinus,0,2*math.pi,0.1) -- la fonction est passée en paramètre&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Les &amp;ldquo;tables&amp;rdquo; de LUA sont bien plus sophistiquées que des tableaux ou vecteurs car on peut y combiner des types différents, y compris des fonctions, mettre des tables dans des tables, assigner les indices etc. ce qui permet de créer de puissantes structures de données : &lt;code&gt;a = { [f(1)] = g; &amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;; x = 1, f(x), [30] = 23; 45 }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Les
sont des tables contenant des références aux fonctions appelées lorsqu&amp;rsquo;on manipule une variable, que l&amp;rsquo;on peut &amp;ldquo;attacher&amp;rdquo; à celle ci. La variable devient donc un &amp;ldquo;objet&amp;rdquo; même si LUA n&amp;rsquo;est pas un langage &amp;ldquo;orienté objet&amp;rdquo; stricto-sensu (très belle &amp;ldquo;phrase à la con&amp;rdquo; lue dans Joystick : j&amp;rsquo;aime bien &amp;ldquo;stricto-sensu&amp;rdquo;: ça fait karatéka !).&lt;/li&gt;
&lt;li&gt;Avec ce mécanisme, on peut même redéfinir les opérateurs d&amp;rsquo;addition, de multiplication etc comme avec C++ ! En fait, LUA peut servir aux néophytes que vous êtes à comprendre comment marche la programmation objet. Pour cela, lire dans l&amp;rsquo;ordre les 3 tutoriels
puis
et enfin
&lt;/li&gt;
&lt;li&gt;LUA est en principe multithread grâce au support de coroutines, mais je n&amp;rsquo;ai pas encore expérimenté ces fonctionnalités&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="pièges"&gt;Pièges&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;LUA est rapide parce qu&amp;rsquo;il ne vérifie rien, même pas qu&amp;rsquo;une variable existe (il n&amp;rsquo;y a pas de &amp;ldquo;option explicit&amp;rdquo; comme dans Visual Basic&amp;hellip;). Il faut donc être très prudent et utiliser le debug de LuaEdit intensivement: &lt;code&gt;somme=2+2 print(somne) -- génère une erreur&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;les variables de type &amp;ldquo;table&amp;rdquo; sont toujours des références aux tables, et en raison de la complexité potentielle des tables, il n&amp;rsquo;y a pas de fonction prédéfinie pour copier une table. Donc: &lt;code&gt;a = { &amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;} b=a -- crée une 2ème référence à la table print(b[1]) -- affiche &amp;quot;x&amp;quot; b[1]=&amp;quot;modifié!&amp;quot; -- change aussi a[1] !!! print(a[1]) -- affiche &amp;quot;modifié!&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;rapide, léger et puissant, LUA est un langage idéal pour être embarqué dans d&amp;rsquo;autres applications, comme les jeux ou Hyperion.&lt;/li&gt;
&lt;li&gt;Il est moins adapté pour réaliser des applications qui en pilotent d&amp;rsquo;autres. Python, beaucoup plus riche en librairies sophistiquées et plus robuste au niveau du traitement des exceptions et erreurs semble mieux armé dans ce cas (voir
qui compare avantages/inconvénients de ces 2 langages)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;/p&gt;</description></item><item><title>Simulation de Galaxie Spirale</title><link>https://drgoulu.com/2007/08/23/simulation-de-galaxie-spirale/</link><pubDate>Thu, 23 Aug 2007 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2007/08/23/simulation-de-galaxie-spirale/</guid><description>&lt;p&gt;Poursuivant ma découverte (*) du génial Hyperion 3D, je me suis attaqué à simuler une Galaxie Spirale.&lt;/p&gt;
&lt;p&gt;Il faut dire que la formation des bras spiraux des galaxies n’a été comprise que récemment parce qu’il fallait « penser différemment ». Bien que je l’aie un peu expliqué 
, je voulais le voir pour le croire. Et voilà, c’est fait, admirez !&lt;/p&gt;
&lt;div class="my-6 mx-auto" style="max-width: 640px; width: 100%;"&gt;
&lt;div class="w-full relative rounded-lg overflow-hidden shadow-md bg-black" style="padding-bottom: 56.25%; height: 0;"&gt;
&lt;iframe
src="https://www.youtube-nocookie.com/embed/LTlSLVbYFso"
title="YouTube video player"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
loading="lazy"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Si vous voulez vous aussi explorer de belles galaxies virtuelles en temps réel, il vous faut:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
 et l’installer&lt;/li&gt;
&lt;li&gt;télécharger 
 , et le décompresser n’importe où&lt;/li&gt;
&lt;li&gt;lancer Hyperion et ouvrir SpiralGalaxy.xml .&lt;/li&gt;
&lt;li&gt;Jouer avec les touches F1-F2 et F3-F4 qui modifient les paramètres eratio et etwist (voir plus bas) pour obtenir différentes spirales.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Comme le montre l’image ci-contre (réalisée avec une petite macro SolidWorks, en passant…) les bras spiraux sont simplement un effet géométrique : ils correspondent à la zone dans laquelle les ellipses sont rapprochées, donc il y a une plus grande densité d’étoiles dans ces zones, mais les étoiles suivent tout de même des orbites elliptiques : elles ne restent pas dans les bras.&lt;/p&gt;
&lt;p&gt;La simulation fait décrire à quelques milliers d’étoile des trajectoires elliptiques autour du centre de la galaxie, le grand et le petit axe de chaque trajectoire étant tournés d’un angle qui dépend de la distance moyenne au centre. Il faut donc calculer la trajectoire de chacune des milliers d’étoiles en temps réel, chose possible avec Hyperion grâce à son intégration du langage LUA, que je ne connaissais pas du tout. C’était donc l’occasion de l’apprendre. Il a beaucoup de qualités dont je reparlerai ailleurs, et un gros défaut : faiblement typé, il n’effectue que peu de vérifications à la compilation et aucune à l’exécution : en cas d’erreur, c’est le crash.&lt;/p&gt;
&lt;p&gt;La programmation ne pose aucune difficulté particulière pour quelqu’un connaissant un peu la trigo et la 2D. Oui, 2D parce que tous les calculs se font dans le plan XY, la coordonnée Z de chaque étoile étant un petit nombre aléatoire constant, destiné à donner un peu d’épaisseur à la Galaxie.&lt;/p&gt;
&lt;p&gt;La visibilité des bras dépend:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;de deux paramètres définissant:
&lt;ol&gt;
&lt;li&gt;l’aplatissement des ellipses (eratio = grand axe / petit axe)&lt;/li&gt;
&lt;li&gt;l’angle de rotation des ellipses en fonction du rayon (etwist)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;de l’apparence des étoiles. Les premiers bras bien visibles ont été obtenus avec des étoiles texturées avec un gros point rouge. En utilisant une texture d’étoile réaliste trouvée 
 la couleur est plus crédible, mais les bras sont moins visibles :&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;l’idéal serait d’utiliser plusieurs vertex pool avec plusieurs textures différentes pour simuler différents types d’étoiles, avec leurs couleurs.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(article aussi publié 
 )&lt;/em&gt;&lt;/p&gt;</description></item><item><title>GPUs et Physique</title><link>https://drgoulu.com/2007/05/19/gpus-et-physique/</link><pubDate>Sat, 19 May 2007 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2007/05/19/gpus-et-physique/</guid><description>&lt;p&gt;Dans votre ordinateur, il y a un CPU (Central Processing Unit) de chez Intel ou AMD communément appelé &amp;ldquo;processeur&amp;rdquo;, et un GPU (Graphics Processing Unit) de chez nVidia ou ATI. Il n&amp;rsquo;y a pas si longtemps, le GPU était un circuit &amp;ldquo;fermé&amp;rdquo;, non programmable par le commun des mortels, entièrement dédié à la production de belles images sur votre écran. Depuis quelques années, ces circuits sont devenus programmables pour permettre de produire de très beaux effets graphiques, et leur puissance à augmenté, augmenté&amp;hellip; A tel point qu&amp;rsquo;aujourd&amp;rsquo;hui, votre GPU contient probablement plus de transistors que votre CPU, et est certainement capable de résoudre certains problèmes plus rapidement !&lt;/p&gt;
&lt;p&gt;Alors qu&amp;rsquo;un CPU a maintenant 2 coeurs capables d&amp;rsquo;exécuter chacun quelques dizaines de tâches complexes en (quasi-) parallèle, un GPU peut exécuter un petit programme appelé &amp;ldquo;shader&amp;rdquo; pour chaque point de l&amp;rsquo;écran (presque) en même temps, soit traiter des milliers de données (presque) simultanément. Pour autant qu&amp;rsquo;un problème puisse être ramené à celui de petits points &amp;ldquo;intelligents&amp;rdquo; qui ne parlent et écoutent que leurs voisins immédiats, le GPU va le résoudre bien plus vite que le CPU.&lt;/p&gt;
&lt;p&gt;Quelques exemples:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;figure &gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt=""
srcset="https://drgoulu.com/posts/2007/images/bd4a01a19cfda0292a5e64880f721c85_hu_4e5f3dbde673726e.webp 320w, https://drgoulu.com/posts/2007/images/bd4a01a19cfda0292a5e64880f721c85_hu_1e7b178691940099.webp 480w, https://drgoulu.com/posts/2007/images/bd4a01a19cfda0292a5e64880f721c85_hu_b59ce94d28635dd0.webp 580w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://drgoulu.com/posts/2007/images/bd4a01a19cfda0292a5e64880f721c85_hu_4e5f3dbde673726e.webp"
width="580"
height="491"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/figure&gt;
la
, déjà mentionné dans l&amp;rsquo;article sur
, mais on reste dans le monde de l&amp;rsquo;inutile beauté des mathématiques.&lt;/li&gt;
&lt;li&gt;
, déjà mentionné
qui combine la fonction principale d&amp;rsquo;une carte graphique, représenter une scène en 3D, avec des calculs relativistes nécessitant 4 dimensions grâce au fait que les GPU traitent 4 composantes de couleur RGBA (Rouge, Gert, Bleu, trAnspArent)&lt;/li&gt;
&lt;li&gt;Et là je viens de tomber sur plusieurs références expliquant comment simuler la gravitation entre N corps avec un GPU, ce qui permet de simuler une mini galaxie de 8192 étoiles beaucoup plus vite qu&amp;rsquo;avec un CPU:
&lt;ul&gt;
&lt;li&gt;Mark Harris &amp;ldquo;Mapping Computational Concepts to GPUs&amp;rdquo;, nVidia (
)&lt;/li&gt;
&lt;li&gt;Francisco Chinchilla, Todd Gamblin, Morten Sommervoll &amp;ldquo;Parallel N-Body Simulation using GPUs (
)&lt;/li&gt;
&lt;li&gt;L. Nyland, M. Harris, and J. Prins, “N-body simulations on a GPU,” in Proc of the ACM Workshop on General-Purpose Computation on Graphics Processors, 2004.&lt;/li&gt;
&lt;li&gt;Tsuyoshi Hamada, Toshiaki Iitaka, &amp;ldquo;The Chamomile Scheme: An Optimized Algorithm for N-body simulations on Programmable Graphics Processing Units&amp;rdquo; , 2007 (
)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pour rester au courant sur ce sujet, suivre le site de référence
(General-Purpose Computation Using Graphics Hardware)&lt;/p&gt;
&lt;p&gt;Tout ceci et la récente fusion d&amp;rsquo;AMD (CPU) et d&amp;rsquo;ATI (GPU) fait penser que les prochains processeurs combineront peut-être les avantages respectifs des CPU et des GPU. Peut-être en coupant la poire en deux en faisant beaucoup de coeurs simples, comme dans le &amp;ldquo;Cell&amp;rdquo; d&amp;rsquo;IBM qui trône dans les PlayStation 3 ? Il faudra encore apprendre à programmer ce genre de puces pour en tirer toute la puissance&amp;hellip;&lt;/p&gt;</description></item><item><title>Relativistic Computer Game</title><link>https://drgoulu.com/2007/05/02/relativistic-computer-game/</link><pubDate>Wed, 02 May 2007 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2007/05/02/relativistic-computer-game/</guid><description>&lt;p&gt;Relativity was discovered in 1905 by Albert Einstein and describes a world full of surpises and strange effects &lt;/p&gt;
\[1\]&lt;p&gt; which have not been exploited in movies or computer games so far.&lt;/p&gt;
&lt;p&gt;Graphically, simulating fast moving spaceships or simply a world where light moves much slower than 300'000 km/s generates interesting visual effects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;objects are deformed as in picture+movie below, which makes them harder to identify quickly
&lt;/li&gt;
&lt;li&gt;their color is altered, enabling to visualize their speed&lt;/li&gt;
&lt;li&gt;the field of vision becomes restricted to the direction of displacement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those effects can be viewed in &amp;ldquo;
&amp;rdquo; &lt;/p&gt;
\[1\]&lt;p&gt;, a PC software that lets you navigate in a scenery at relativistc speed.Even more interstingly, the &amp;ldquo;lag&amp;rdquo; induced by communication delays is a general problem that limits the geographic distance between players of a network game, but relativistic games might be designed to take advantage of the lag, and even make it artifically longer to make the game more interesting. Such games would rely on the player&amp;rsquo;s ability to anticipate possible actions from other players rather than reacting to them.&lt;/p&gt;
&lt;p&gt;Technically, relativistic visual effects can be computed in real time by modified &amp;ldquo;3D engines&amp;rdquo;, while lag handling requires only memory buffers.&lt;/p&gt;
&lt;p&gt;All you need now to create a very original video game based on relativity is a good gameplay&amp;hellip;&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Craig M. Savage, Antony C. Searle, Lachlan McCalman, &amp;ldquo;
&amp;rdquo;. Department of Physics, Faculty of Science, The Australian National University. Interactive Program for PC using
can be downloaded
&lt;/li&gt;
&lt;li&gt;
with
&lt;/li&gt;
&lt;li&gt;A.C. Searle, C.M. Savage, P.A. Altin, F.H. Bennet and M.R. Hush, Through Einstein’s Eyes, The Physicist, July/August 2005. ArXiv: physics/0508224.
,
,
&lt;/li&gt;
&lt;li&gt;C.M. Savage and A.C. Searle,
, The Physicist, July/August 1999&lt;/li&gt;
&lt;li&gt;D. Weiskopf, “
”, Ph.D. thesis, U. Tübingen (2001).&lt;/li&gt;
&lt;li&gt;M. Bochers, “
”, Ph.D. thesis, U. Tübingen (2005).&lt;/li&gt;
&lt;li&gt;U. Kraus, “
”: Featured on the cover of Physics Today 58, num. 1, Jan 2005.&lt;/li&gt;
&lt;li&gt;
, 2004, short novel (in french) describing a travel at relativistic speed to Barnard star&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>DicoLib</title><link>https://drgoulu.com/2005/09/14/dicolib/</link><pubDate>Wed, 14 Sep 2005 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2005/09/14/dicolib/</guid><description>&lt;p&gt;DicoLib est une librairie C++/STL pour les jeux de mots, que j&amp;rsquo;ai développé initialement pour résoudre le casse-tête &amp;ldquo;
&amp;rdquo;&lt;/p&gt;
&lt;h4 id="complexité"&gt;Complexité&lt;/h4&gt;
&lt;p&gt;L’algorithme &amp;ldquo;force brute&amp;rdquo; pour résoudre &amp;ldquo;
&amp;rdquo; consiste à chercher les n mots de 8 lettres du dictionnaire (O(N)), puis pour chacun d’eux, enlever successivement chaque lettre et vérifier s’il est présent dans le dictionnaire (O(N.log N) pour liste triée), et recommencer s’il y est. La complexité est environ O(N+n.100.N.log N). Le facteur 100 est une estimation du nombre de recherches dans le dictionnaire pour chaque mot avant d’arriver à une impasse. Avec typiquement N=30’000 et n=5’000, on se retrouve avec &lt;em&gt;&amp;lsquo;240 milliards de comparaisons&lt;/em&gt;&amp;rsquo; de chaînes de caractères à effectuer si l’on veut trouver toutes les solutions. Compter une petite heure&amp;hellip;&lt;/p&gt;
&lt;p&gt;On pourrait se satisfaire de ceci et se demander pourquoi passer des heures à programmer une solution plus futée. Et bien, si on est capable de retrouver rapidement les mots qui ne se distinguent d’un autre que par une seule lettre, ou deux ou trois, on obtient un correcteur d’orthographe rapide et efficace. Mais pour une telle application, la complexité mentionnée ci-dessus serait inacceptable.&lt;/p&gt;
&lt;h4 id="conception"&gt;Conception&lt;/h4&gt;
&lt;p&gt;Comment accélérer très sérieusement la recherche de mots &amp;ldquo;semblables&amp;rdquo; a un autre dans un dictionnaire ?&lt;/p&gt;
&lt;p&gt;Quelques idées :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;grouper les mots par tailles. Si on cherche un mot de 6 lettres, on ne le cherchera que parmi ceux-là.&lt;/li&gt;
&lt;li&gt;construire une &amp;ldquo;signature&amp;rdquo; du mot sous la forme d’un ensemble de 26 bits indiquant quelles lettres sont présentes dans le mot, et grouper les mots ayant la même signature (donc composés des mêmes lettres) dans une liste. 26 bits, c’est moins que 32, donc très pratique à manipuler par le processeur pour des opérations logiques. Mais c’est trop pour être utilisé comme clé dans une table de hachage, qui aurait dans les 64 millions d’entrées.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je me suis dont mis à réfléchir à une structure de donnée permettant de stocker un dictionnaire de mots sous une forme permettant la recherche rapide de mots similaires (avec une lettre en plus ou en moins), des anagrammes (mots obtenus par permutation des lettres) ou selon les lettres qui les composent (pour le scrabble).&lt;/p&gt;
&lt;p&gt;J’ai alors eu une idée simple, dont je ne sais pas encore si elle est originale, mais en tout cas elle est très efficace, et j’ai écrit un ensemble de classes C++ &amp;ldquo;Dico.lib&amp;rdquo;,une librairie permettant de réaliser en quelques lignes des programmes de résolution de divers jeux de lettres.&lt;/p&gt;
&lt;p&gt;L’idée principale de DicoLib est de stocker les mots dans une structure permettant d’y accéder rapidement sur la base de 2 informations simples :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la longueur du mot&lt;/li&gt;
&lt;li&gt;une clé de 26 bits (letterset) codant la présence de chaque lettre de l’alphabet dans le mot. par exemple le mot &amp;ldquo;alphabet&amp;rdquo; donne&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;11001001000100000001000000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;abcdefghijklmnopqrstuvwxyz
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="structure-de-données"&gt;Structure de données&lt;/h4&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;dico.lib définit la hiérarchie de classes suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;class Word // mots du dictionnaire&lt;/li&gt;
&lt;li&gt;class letterset : public std ::bitset&amp;lt;26&amp;gt; // clé d’accès&lt;/li&gt;
&lt;li&gt;class WordList : public std ::list // liste de mots&lt;/li&gt;
&lt;li&gt;class Anagrams : public WordList // liste d’anagrammes&lt;/li&gt;
&lt;li&gt;class AnagramsList : public list // liste de listes d’anagrammes&lt;/li&gt;
&lt;li&gt;class SameLetters : public vector // mots formés des même lettres, organiséss par longueurr&lt;/li&gt;
&lt;li&gt;class Dico : public std ::map // dictionnaire utilisant les letterset comme clé primaire&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="liens"&gt;Liens&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
, d&amp;rsquo;où vous pouvez télécharger le code et contribuer à le développer&lt;/li&gt;
&lt;li&gt;
, article sur
&lt;/li&gt;
&lt;li&gt;des dictionnaire en mode texte sont disponibles ici:
&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Pentominos</title><link>https://drgoulu.com/2005/09/04/pentominos/</link><pubDate>Sun, 04 Sep 2005 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2005/09/04/pentominos/</guid><description>&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;J’avais écrit un programme &amp;ldquo;PentoSolver&amp;rdquo; en Visual Basic qui trouve les solutions 6x10 mais
résout toutes les variantes de Pentominos et de Polynominos encore plus vite, directement sur votre explorateur&amp;hellip; TRES FORT !&lt;/p&gt;</description></item><item><title>SuperShape Exporer : a first experience with DevLib</title><link>https://drgoulu.com/2004/08/05/supershape-exporer-a-first-experience-with-devlib/</link><pubDate>Thu, 05 Aug 2004 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2004/08/05/supershape-exporer-a-first-experience-with-devlib/</guid><description>&lt;p&gt;SuperShape Explorer has 2 goals:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;explore 3D shapes generated by the
&lt;/li&gt;
&lt;li&gt;see what can be done with the
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;SuperShape runs on Windows XP with OpenGL. You’ll need Visual C++ 7.1 (2003) to recompile it. SuperShape is freeware, comes with open source code (you need DevLib) and without any warranty&amp;hellip;.&lt;/p&gt;
&lt;h4 id="usage"&gt;Usage&lt;/h4&gt;
&lt;p&gt;After installation, program will start automatically. You can then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rotate the shape by moving your mouse around while pressing any mouse button&lt;/li&gt;
&lt;li&gt;press (Space) to generate a random SuperShape&lt;/li&gt;
&lt;li&gt;press (C) for a cube, (Y) for a cone, (X) for a cylinder, (S) for a sphere, (D) for a diamond&lt;/li&gt;
&lt;li&gt;press (0,1,2..9) keys to set the M1 value accordingly&lt;/li&gt;
&lt;li&gt;press (W) for Wireframe, (V) for volume again&lt;/li&gt;
&lt;li&gt;(ESC) to escape&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="known-problems"&gt;Known Problems:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Uses 100% of processor since supershape is recomputed at every frame&lt;/li&gt;
&lt;li&gt;Face culling is sometimes wrong (you can sometimes see faces that should be hidden. Probably because normals aren’t computed yet&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="todo-list"&gt;Todo list:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Remove that ugly perspective effect&lt;/li&gt;
&lt;li&gt;Solve the face culling problem&lt;/li&gt;
&lt;li&gt;Avoid recomputing the shape if it doesn’t change&lt;/li&gt;
&lt;li&gt;Do smooth transitions (&amp;ldquo;morphing&amp;rdquo;) when changing shapes&lt;/li&gt;
&lt;li&gt;Automatically adjust the mesh density to keep fps constant (probably using the
)&lt;/li&gt;
&lt;li&gt;Add a way to move the camera and to zoom in/out with mouse&lt;/li&gt;
&lt;li&gt;Add lights&lt;/li&gt;
&lt;li&gt;Add GUI widgets to allow editing the supershape like the tool
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="history-200485"&gt;History: 2004/8/5&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;V 1.0 done from existing DevLib demo code&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>15000 décimales de Pi en 133 octets de C</title><link>https://drgoulu.com/2004/06/28/pi-en-c/</link><pubDate>Mon, 28 Jun 2004 00:00:00 +0000</pubDate><guid>https://drgoulu.com/2004/06/28/pi-en-c/</guid><description>&lt;p&gt;Voici un minuscule programme en langage C de 133 caractères, c’est vraiment pas gros&amp;hellip;.&lt;/p&gt;
\[c\]&lt;p&gt;int a&lt;/p&gt;
\[52514\]&lt;p&gt;,b,c=52514,d,e,f=1e4,g,h;main() {for(;b=c-=14;h=printf(&amp;quot;%04d&amp;quot;,e+d/f)) for(e=d%=f;g=&amp;ndash;b*2;d/=g) d=d*b+f*(h?a&lt;/p&gt;
\[b\]&lt;p&gt;:f/5),a&lt;/p&gt;
\[b\]&lt;p&gt;=d%&amp;ndash;g;}&lt;/p&gt;
\[/c\]&lt;p&gt;Si vous l’exécutez. vous allez obtenir ce résultat en quelques secondes:&lt;/p&gt;
&lt;p&gt;31415926535897932384626433832795028841971693993751 05820974944592307816406286208998628034825342117067 98214808651328230664709384460955058223172535940812 84811174502841027019385211055596446229489549303819 64428810975665933446128475648233786783165271201909 14564856692346034861045432664821339360726024914127 37245870066063155881748815209209628292540917153643 67892590360011330530548820466521384146951941511609 43305727036575959195309218611738193261179310511854 80744623799627495673518857527248912279381830119491 29833673362440656643086021394946395224737190702179 86094370277053921717629317675238467481846766940513 20005681271452635608277857713427577896091736371787 21468440901224953430146549585371050792279689258923 54201995611212902196086403441815981362977477130996 05187072113499999983729780499510597317328160963185 95024459455346908302642522308253344685035261931188 17101000313783875288658753320838142061717766914730 35982534904287554687311595628638823537875937519577 81857780532171226806613001927876611195909216420198 93809525720106548586327886593615338182796823030195 20353018529689957736225994138912497217752834791315 15574857242454150695950829533116861727855889075098 38175463746493931925506040092770167113900984882401 28583616035637076601047101819429555961989467678374 49448255379774726847104047534646208046684259069491 29331367702898915210475216205696602405803815019351 12533824300355876402474964732639141992726042699227 96782354781636009341721641219924586315030286182974 55570674983850549458858692699569092721079750930295 53211653449872027559602364806654991198818347977535 66369807426542527862551818417574672890977772793800 08164706001614524919217321721477235014144197356854 81613611573525521334757418494684385233239073941433 34547762416862518983569485562099219222184272550254 25688767179049460165346680498862723279178608578438 38279679766814541009538837863609506800642251252051 17392984896084128488626945604241965285022210661186 30674427862203919494504712371378696095636437191728 74677646575739624138908658326459958133904780275900 99465764078951269468398352595709825822620522489407 72671947826848260147699090264013639443745530506820 34962524517493996514314298091906592509372216964615 15709858387410597885959772975498930161753928468138 26868386894277415599185592524595395943104997252468 08459872736446958486538367362226260991246080512438 84390451244136549762780797715691435997700129616089 44169486855584840635342207222582848864815845602850 60168427394522674676788952521385225499546667278239 86456596116354886230577456498035593634568174324112 51507606947945109659609402522887971089314566913686 72287489405601015033086179286809208747609178249385 89009714909675985261365549781893129784821682998948 72265880485756401427047755513237964145152374623436 45428584447952658678210511413547357395231134271661 02135969536231442952484937187110145765403590279934 40374200731057853906219838744780847848968332144571 38687519435064302184531910484810053706146806749192 78191197939952061419663428754440643745123718192179 99839101591956181467514269123974894090718649423196 15679452080951465502252316038819301420937621378559 56638937787083039069792077346722182562599661501421 50306803844773454920260541466592520149744285073251 86660021324340881907104863317346496514539057962685 61005508106658796998163574736384052571459102897064 14011097120628043903975951567715770042033786993600 72305587631763594218731251471205329281918261861258 67321579198414848829164470609575270695722091756711 67229109816909152801735067127485832228718352093539 65725121083579151369882091444210067510334671103141 26711136990865851639831501970165151168517143765761 83515565088490998985998238734552833163550764791853 58932261854896321329330898570642046752590709154814 16549859461637180270981994309924488957571282890592 32332609729971208443357326548938239119325974636673 05836041428138830320382490375898524374417029132765 61809377344403070746921120191302033038019762110110 04492932151608424448596376698389522868478312355265 82131449576857262433441893039686426243410773226978 02807318915441101044682325271620105265227211166039 66655730925471105578537634668206531098965269186205 64769312570586356620185581007293606598764861179104 53348850346113657686753249441668039626579787718556 08455296541266540853061434443185867697514566140680 07002378776591344017127494704205622305389945613140 71127000407854733269939081454664645880797270826683 06343285878569830523580893306575740679545716377525 42021149557615814002501262285941302164715509792592 30990796547376125517656751357517829666454779174501 12996148903046399471329621073404375189573596145890 19389713111790429782856475032031986915140287080859 90480109412147221317947647772622414254854540332157 18530614228813758504306332175182979866223717215916 07716692547487389866549494501146540628433663937900 39769265672146385306736096571209180763832716641627 48888007869256029022847210403172118608204190004229 66171196377921337575114959501566049631862947265473 64252308177036751590673502350728354056704038674351 36222247715891504953098444893330963408780769325993 97805419341447377441842631298608099888687413260472 15695162396586457302163159819319516735381297416772 94786724229246543668009806769282382806899640048243 54037014163149658979409243237896907069779422362508 22168895738379862300159377647165122893578601588161 75578297352334460428151262720373431465319777741603 19906655418763979293344195215413418994854447345673 83162499341913181480927777103863877343177207545654 53220777092120190516609628049092636019759882816133 23166636528619326686336062735676303544776280350450 77723554710585954870279081435624014517180624643626 79456127531813407833033625423278394497538243720583 53114771199260638133467768796959703098339130771098 70408591337464144282277263465947047458784778720192 77152807317679077071572134447306057007334924369311 38350493163128404251219256517980694113528013147013 04781643788518529092854520116583934196562134914341 59562586586557055269049652098580338507224264829397 28584783163057777560688876446248246857926039535277 34803048029005876075825104747091643961362676044925 62742042083208566119062545433721315359584506877246 02901618766795240616342522577195429162991930645537 79914037340432875262888963995879475729174642635745 52540790914513571113694109119393251910760208252026 18798531887705842972591677813149699009019211697173 72784768472686084900337702424291651300500516832336 43503895170298939223345172201381280696501178440874 51960121228599371623130171144484640903890644954440 06198690754851602632750529834918740786680881833851 02283345085048608250393021332197155184306354550076 68282949304137765527939751754613953984683393638304 74611996653858153842056853386218672523340283087112 32827892125077126294632295639898989358211674562701 02183564622013496715188190973038119800497340723961 03685406643193950979019069963955245300545058068550 19567302292191393391856803449039820595510022635353 61920419947455385938102343955449597783779023742161 72711172364343543947822181852862408514006660443325 88856986705431547069657474585503323233421073015459 40516553790686627333799585115625784322988273723198 98757141595781119635833005940873068121602876496286 74460477464915995054973742562690104903778198683593 81465741268049256487985561453723478673303904688383 43634655379498641927056387293174872332083760112302 99113679386270894387993620162951541337142489283072 20126901475466847653576164773794675200490757155527 81965362132392640616013635815590742202020318727760 52772190055614842555187925303435139844253223415762 33610642506390497500865627109535919465897514131034 82276930624743536325691607815478181152843667957061 10861533150445212747392454494542368288606134084148 63776700961207151249140430272538607648236341433462 35189757664521641376796903149501910857598442391986 29164219399490723623464684411739403265918404437805 13338945257423995082965912285085558215725031071257 01266830240292952522011872676756220415420516184163 48475651699981161410100299607838690929160302884002 69104140792886215078424516709087000699282120660418 37180653556725253256753286129104248776182582976515 79598470356222629348600341587229805349896502262917 48788202734209222245339856264766914905562842503912 7577102840279980663658254889264 8802545661017296702 66407655904290994568150652653053718294127033693137 85178609040708667114965583434347693385781711386455 87367812301458768712660348913909562009939361031029 16161528813843790990423174733639480457593149314052 97634757481193567091101377517210080315590248530906 69203767192203322909433467685142214477379393751703 44366199104033751117354719185504644902636551281622 88244625759163330391072253837421821408835086573917 71509682887478265699599574490661758344137522397096 83408005355984917541738188399944697486762655165827 65848358845314277568790029095170283529716344562129 64043523117600665101241200659755851276178583829204 19748442360800719304576189323492292796501987518721 27267507981255470958904556357921221033346697499235 63025494780249011419521238281530911407907386025152 27429958180724716259166854513331239480494707911915 32673430282441860414263639548000448002670496248201 79289647669758318327131425170296923488962766844032 32609275249603579964692565049368183609003238092934 59588970695365349406034021665443755890045632882250 54525564056448246515187547119621844396582533754388 56909411303150952617937800297412076651479394259029 89695946995565761218656196733786236256125216320862 86922210327488921865436480229678070576561514463204 69279068212073883778142335628236089632080682224680 12248261177185896381409183903673672220888321513755 60037279839400415297002878307667094447456013455641 72543709069793961225714298946715435784687886144458 12314593571984922528471605049221242470141214780573 45510500801908699603302763478708108175450119307141 22339086639383395294257869050764310063835198343893 41596131854347546495569781038293097164651438407007 07360411237359984345225161050702705623526601276484 83084076118301305279320542746286540360367453286510 57065874882256981579367897669742205750596834408697 35020141020672358502007245225632651341055924019027 42162484391403599895353945909440704691209140938700 12645600162374288021092764579310657922955249887275 84610126483699989225695968815920560010165525637567 85667227966198857827948488558343975187445455129656 34434803966420557982936804352202770984294232533022 57634180703947699415979159453006975214829336655566 15678736400536665641654732170439035213295435291694 14599041608753201868379370234888689479151071637852 90234529244077365949563051007421087142613497459561 51384987137570471017879573104229690666702144986374 64595280824369445789772330048764765241339075920434 01963403911473202338071509522201068256342747164602 43354400515212669324934196739770415956837535551667 30273900749729736354964533288869844061196496162773 44951827369558822075735517665158985519098666539354 94810688732068599075407923424023009259007017319603 62254756478940647548346647760411463233905651343306 84495397907090302346046147096169688688501408347040 54607429586991382966824681857103188790652870366508 32431974404771855678934823089431068287027228097362 48093996270607472645539925399442808113736943388729 40630792615959954626246297070625948455690347119729 96409089418059534393251236235508134949004364278527 13831591256898929519642728757394691427253436694153 23610045373048819855170659412173524625895487301676 00298865925786628561249665523533829428785425340483 08330701653722856355915253478445981831341129001999 20598135220511733658564078264849427644113763938669 24803118364453698589175442647399882284621844900877 76977631279572267265556259628254276531830013407092 23343657791601280931794017185985999338492354956400 57099558561134980252499066984233017350358044081168 55265311709957089942732870925848789443646005041089 22669178352587078595129834417295351953788553457374 26085902908176515578039059464087350612322611200937 31080485485263572282576820341605048466277504500312 62008007998049254853469414697751649327095049346393 82432227188515974054702148289711177792376122578873 47718819682546298126868581705074027255026332904497 62778944236216741191862694396506715157795867564823 99391760426017633870454990176143641204692182370764 88783419689686118155815873606293860381017121585527 26683008238340465647588040513808016336388742163714 06435495561868964112282140753302655100424104896783 52858829024367090488711819090949453314421828766181 03100735477054981596807720094746961343609286148494 17850171807793068108546900094458995279424398139213 50558642219648349151263901280383200109773868066287 79239718014613432445726400973742570073592100315415 08936793008169980536520276007277496745840028362405 34603726341655425902760183484030681138185510597970 56640075094260878857357960373245141467867036880988 06097164258497595138069309449401515422221943291302 17391253835591503100333032511174915696917450271494 33151558854039221640972291011290355218157628232831 82342548326111912800928252561902052630163911477247 33148573910777587442538761174657867116941477642144 11112635835538713610110232679877564102468240322648 34641766369806637857681349204530224081972785647198 39630878154322116691224641591177673225326433568614 61865452226812688726844596844241610785401676814208 08850280054143613146230821025941737562389942075713 62751674573189189456283525704413354375857534269869 94725470316566139919996826282472706413362221789239 03176085428943733935618891651250424404008952719837 87386480584726895462438823437517885201439560057104 81194988423906061369573423155907967034614914344788 63604103182350736502778590897578272731305048893989 00992391350337325085598265586708924261242947367019 39077271307068691709264625484232407485503660801360 46689511840093668609546325002145852930950000907151 05823626729326453738210493872499669933942468551648 32611341461106802674466373343753407642940266829738 65220935701626384648528514903629320199199688285171 83953669134522244470804592396602817156551565666111 35982311225062890585491450971575539002439315351909 02107119457300243880176615035270862602537881797519 47806101371500448991721002220133501310601639154158 95780371177927752259787428919179155224171895853616 80594741234193398420218745649256443462392531953135 10331147639491199507285843065836193536932969928983 79149419394060857248639688369032655643642166442576 07914710869984315733749648835292769328220762947282 38153740996154559879825989109371712621828302584811 23890119682214294576675807186538065064870261338928 22994972574530332838963818439447707794022843598834 10035838542389735424395647555684095224844554139239 41000162076936368467764130178196593799715574685419 46334893748439129742391433659360410035234377706588 86778113949861647874714079326385873862473288964564 35987746676384794665040741118256583788784548581489 62961273998413442726086061872455452360643153710112 74680977870446409475828034876975894832824123929296 05829486191966709189580898332012103184303401284951 16203534280144127617285830243559830032042024512072 87253558119584014918096925339507577840006746552603 14461670508276827722235341911026341631571474061238 50425845988419907611287258059113935689601431668283 17632356732541707342081733223046298799280490851409 47903688786878949305469557030726190095020764334933 59106024545086453628935456862958531315337183868265 61786227363716975774183023986006591481616404944965 01173213138957470620884748023653710311508984279927&lt;/p&gt;
&lt;p&gt;Oui, ce sont bien les 15’000 premières décimales de Pi !&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(ajout du 3.14 (pi-day&amp;hellip;) 2012:)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;algorithme utilisé s&amp;rsquo;appelle &amp;ldquo;
&amp;rdquo; et il est du à Rabinowitz and Wagon. La référence suivante explique son fonctionnement&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
\[altmetric doi="10.1007/978-3-319-32377-0\_16" float="right"\]Jeremy Gibbons &amp;ldquo;
&amp;rdquo; (2006), The American Mathematical Monthly 4 (113) p. 318-328 DOI&amp;gt;
&lt;/li&gt;
&lt;/ol&gt;</description></item></channel></rss>