14 Jan 2026

feedPlanet Grep

Lionel Dricot: La ligne de commande communiste, le code Baudot et le comte ChatGPT

La ligne de commande communiste, le code Baudot et le comte ChatGPT

Il y a quelques mois, un lecteur m'a fait découvrir un incroyable jeu historico-politique entièrement réalisé en AsciiArt: « Le comte et la communiste », de Tristan Pun.

La simplicité des graphismes m'a fait plonger dans l'histoire comme dans un excellent livre. Jouant une espionne/servante, vous êtes amené à découvrir l'envers du décor d'un château aristocrate pendant la Première Guerre mondiale. De manière très intéressante pour le sous-texte sociopolitique, le temps passé dans le château est proportionnel au nombre de lessives. Car, bien qu'espionne, vous êtes avant tout une servante et il va falloir se remonter les manches et faire la lessive !

Si je vous en parle avec tant d'enthousiasme, c'est qu'à un moment du jeu vous trouvez une bande de papier contenant un message au format Baudot. Le code Baudot est l'ancêtre de l'ASCII et le premier encodage de caractère utilisé sur les télégraphes automatiques : le message est directement reçu sur des bandes de papier, à la différence du Morse qui nécessite un opérateur humain à la réception.

Une bande de papier avec un message en code Baudot (source: Ricardo Ferreira de Oliveira) Une bande de papier avec un message en code Baudot (source: Ricardo Ferreira de Oliveira)

Dans le jeu, le message est trouvé sur une bande de papier servant de signet qui ressemble à ceci.

Une bande de papier en ASCII contenant de "o" pour les trous. Une bande de papier en ASCII contenant de "o" pour les trous.

Sur une plaque, vous trouverez toutes les informations pour déchiffrer le code Baudot.

Capture d’écran du jeu expliquant le code Baudot. Capture d'écran du jeu expliquant le code Baudot.

Il ne reste plus qu'à déchiffrer le message… Mais, très vite, j'ai trouvé ça laborieux. Et si je demandais à ma fidèle ligne de commande de le faire à ma place ? Après tout, la lecture de l'excellentissime « Efficient Linux at the Command Line », de Daniel J. Barret, m'a mis en confiance.

Décoder le message Baudot en ligne de commande

Attention, je vous préviens, ça va être très technique. Vous n'êtes pas obligé de vous infliger ça.

Vous êtes toujours là ? C'est parti !

Une fois le code en Asciiart copié/collé dans un fichier, on va l'afficher avec "cat". Même si ce n'est pas strictement nécessaire, je commence toujours toutes mes chaînes de pipe avec cat. Cela me semble plus clair.

Ici, la difficulté est que je veux accéder aux colonnes : je veux reconstruire un mot en prenant les premières lettres de chaque ligne, puis les secondes de chaque ligne, etc.

La commande Unix qui se rapproche le plus de cela est "cut". Cut permet de prendre le Xème caractère d'une ligne avec l'option -cX. Pour la quinzième, je fais donc "cut -c15". Tout de suite, je réalise que je vais avoir besoin d'une boucle. Considérant que les lignes font moins de 100 caractères, je peux faire un

for i in {1..100}; do" avec un "cut -c$i

Et voilà, je sais désormais isoler chaque colonne.

Dans l'asciiart, le binaire du code Baudot est représenté par des "o" et des espaces. Par soucis de clarté, je vais remplacer les espaces par des "l" (ça ressemble à un "1" binaire). La commande Unix pour faire des substitutions de caractères est "tr" (translate): tr " " l (l'espace est entre guillemets).

Toujours par souci de clarté, je vais effacer tout ce qui n'est pas un o ou un l. Tr permet d'effacer des caractères avec l'option -d et de prendre "tous les caractères sauf ceux de la liste" avec l'option -c (complémentaire). Je rajoute donc un tr -cd "ol".

La chaîne dans ma boucle ressemble donc à:

cat $1|cut -c"$i"|tr " " l|tr -cd "ol"

Problème : mes groupes de 5 lettres sont toujours verticaux !

J'ai tenté l'approche de supprimer les retours à la ligne avec tr -d "\n", mais cela produit des résultats bizarres, surtout que le dernier retour à la ligne est lui aussi supprimé.

Du coup, la commande qui me semble tout indiquée pour faire cela est le contraire de "cut" : "paste". Mais, essayez de lancer la chaîne dans "paste" : rien ne se passe !

Et pour cause : paste est initialement conçu pour joindre chaque ligne de plusieurs fichiers. Ici, il n'y a qu'un seul fichier : le flux d'entrée. Paste ne peux donc rien lui joindre.

Heureusement, l'option "-s" permet de dire à paste de tout mettre sur une seule ligne. Je suis complètement passé à côté pour une raison très simple : la page man de paste est incompréhensible.

-s, --serial
copier un fichier à la fois au lieu de le faire en parallèle

Je défie quiconque de voir le rapport entre la page de man et la fonction réelle. J'ai heureusement eu l'intuition de tester avec "tldr" au lieu de man.

Join all the lines into a single line, using TAB as delimiter:
paste -s path/to/file

Avouez que c'est déjà beaucoup plus clair !

Un p'tit test me révèle que c'est presque bon. Tout est sur une ligne. Sauf qu'il y'a désormais des TAB entre chaque lettre. On pourrait les enlever avec tr. Ou simplement dire à paste de ne pas les mettre en utilisant à la place un séparateur nul:

cat $1|cut -c"$i"|tr " " l|tr -cd "ol"|paste -sd "\0"

Ma boucle for m'affiche désormais chaque lettre sur une ligne. Il ne me reste qu'à traduire le code Baudot.

Je peux, par exemple, rajouter un pipe vers "sed s/llloo/a/" pour remplacer les lettres a. Et un pipe vers un nouveau sed pour la lettre b et ainsi de suite. Ça fonctionne, mais c'est moche et très lent (chaque sed lançant son propre process).

Lorsqu'on a beaucoup de règles sed, autant les mettre dans un fichier baudot.sed qui contient les commandes sed, une par ligne :

s/llloo/a/
s/oollo/b/
s/loool/c/
...

Je peux appeler ces règles avec "sed -f baudot.sed".

Le code Baudot a une subtilité : y'a un code qui permet de passer en mode "caractère spécial". Je ne prends pas la tête, je me contente de remplacer ce code par "<" et le code pour revenir en mode normal par ">" (ces deux caractères n'existant pas dans le code Baudot). De cette manière, je sais que toute lettre entre < > n'est pas vraiment la lettre, mais le symbole correspondant. Un <m> est en réalité un ".". Également, il y a de nombreux espaces avant et après les messages, qui ont été convertis en autant de "l". Là, j'ai fait un bon gros hack. Au lieu de mettre un "l" normal dans le code Baudot, j'ai mis un L majuscule. Ensuite, à la toute fin, je supprime les "l" restant avec une règle globale : "s/l//g" (le "g" indique de changer tous les l sur une ligne, même s'il y'en a plusieurs). Puis, je remets en minuscule le "L" avec "s/L/l". Oui, c'est un bon gros hack. Ça fait l'affaire.

Mon fichier baudot.sed ressemble alors à ça :

s/ooloo/</
s/lloll/ /
s/ooooo/>/
s/llloo/a/
s/oollo/b/
s/loool/c/
s/lollo/d/
s/llllo/e/
s/loolo/f/
s/oolol/g/
s/ololl/h/
s/llool/i/
s/loloo/j/
s/loooo/k/
s/ollol/L/
s/oooll/m/
s/looll/n/
s/oolll/o/
s/oolll/p/
s/olooo/q/
s/lolol/r/
s/llolo/s/
s/ollll/t/
s/llooo/u/
s/ooool/v/
s/olloo/w/
s/ooolo/x/
s/ololo/y/
s/olllo/z/
s/l//g
s/L/l/g

Mon message est décodé. Mais, bien entendu, il s'affiche verticalement.

Ça ne vous rappelle rien ?

Un bon vieux paste -sd "\0" remet tout à l'endroit (et cette fois-ci, je n'ai pas eu à chercher).

Dans le jeu, le seul symbole utilisé sera le point, qui est ici devenu un "<m>" ou "<m" s'il est à la fin du message. Soyons propres jusqu'au bout et rajoutons deux petits sed. On pourrait également faire un autre fichier sed avec tous les caractères, mais le jeu ne comporte finalement que deux messages.

Dommage, là j'étais chaud pour plus.

Mon script final est donc :

#!/bin/bash
for i in {1..100}; do
        cat $1|cut -c"$i"|tr " " l|tr -cd "ol"|paste -sd "\0"
done|sed -f baudot.sed|paste -sd "\0"|sed "s/<m>/./"|sed "s/<m/./"

Avec le recul, ce script est beaucoup plus simple et efficace qu'un script Python. Le script Python prendrait des dizaines de lignes et agirait sur une matrice de caractères. Les outils Unix, eux, agissent sur des flux de texte. J'y trouve une certaine élégance, un plaisir particulier. Le tout m'a pris environ 30 minutes, dont une bonne partie sur l'erreur de "tr -d \n".

Demander à ChatGPT de décoder le message Baudot

Comme mon compte Kagi me donne désormais accès à ChatGPT, je me suis dit que j'allais faire l'expérience de lui demander de résoudre le même problème que moi. Histoire de comprendre ce qu'est le « Vibe coding ».

Au départ, ChatGPT est perdu. Il ne sait clairement pas traduire les messages, m'assène de longues tables de soi-disant code Baudot (qui sont parfois correctes, mais pas toujours) et me raconte l'histoire de ce code (qui est généralement correcte, mais que je n'ai pas demandée). C'est verbeux, je dois lui dire plusieurs fois de faire cours et d'être efficace.

Je lui demande de me faire un script bash. Ses premières tentatives sont extrêmement longues et incompréhensibles. Il semble beaucoup aimer les scripts awk à rallonge.

Persévérant, je demande à ChatGPT de ne plus utiliser awk et je lui explicite chaque étape l'une après l'autre: je lui dit qu'il faut parcourir chaque colonne, la redresser, la convertir, etc.

Logiquement, il arrive à un résultat très similaire au mien. Il choisit d'utiliser "tr -d \n" pour supprimer les fins de ligne, mais, comme je l'ai dit, ça ne fonctionne pas correctement. Je lui passe, car je n'ai moi‑même pas compris l'erreur.

Je constate cependant une amélioration intéressante : là où j'ai demandé les 100 premières colonnes, chatGPT mesure la longueur avec :

for i in $(seq $(head -1 $1|wc -c)); do

Concrètement, il prend la première ligne avec "head -1", compte les caractères avec "wc -c" et construit une séquence de 1 jusqu'a ce nombre avec "seq".

C'est une excellente idée si on considère que la première ligne est représentative des autres. Une fois le "redressement" en place (il m'a fallu des dizaines de prompts et d'exemples pour arriver à lui expliquer, à chaque fois il prétend qu'il a compris et c'est faux), je lui demande de traduire en utilisant le code Baudot.

Au lieu de ma solution avec "sed", il fait une fonction bash "baudot_to_letter" qui est un gros case:

baudot_to_letter() {
  case $1 in
    00000) echo " " ;;
    00001) echo "E" ;;
    00010) echo "A" ;;

Fait amusant, les caractères ne sont pas en ordre alphabétique, mais dans l'ordre binaire de la représentation Baudot. Pourquoi pas ?

Je valide cette solution même si je préfère le sed parce que je n'avais pas envie de faire du bash mais utiliser les outils Unix. Je lui ai dit plusieurs fois que je voulais une commande Unix, pas un script bash avec plusieurs fonctions. Mais je lui laisse, car, au fond, sa solution est pertinente.

Maintenant que toutes les étapes ont été décrites, je teste son code final. Qui ne fonctionne pas, produisant une erreur bash. Je lui demande une nouvelle version en lui copiant-collant l'erreur. Après plusieurs itérations de ce type, j'ai enfin un script qui fonctionne et me renvoie la traduction du message suivante :

LLECJGCISTGCIUMCEISJEISKN CT UIXV SJECUZUCEXV

Le nombre de lettres n'est même pas correct. Je n'ai évidemment pas envie de débugger le truc. Je demande à lors à ChatGPT de lancer le script lui-même pour me donner la traduction :

ChatGPT me dit que le message traduit est "ECHOES OF THE PAST". Il est très fier, car c’est un message cohérent. Sauf que le jeu est en français… ChatGPT me dit que le message traduit est "ECHOES OF THE PAST". Il est très fier, car c'est un message cohérent. Sauf que le jeu est en français…

À ce point de l'histoire, j'ai, montre en main, passé plus de temps à tenter d'utiliser ChatGPT que je n'en ai mis pour écrire mon propre script, certes imparfait, mais fonctionnel. Je me retrouve à faire des copier-coller incessants entre ChatGPT et mon terminal, à tenter de négocier des changements et déboguer du code que je n'ai pas écrit.

Et encore, pour ChatGPT, j'ai nettoyé le message en enlevant tout ce qui n'est pas le code Baudot. Mon propre script est beaucoup plus robuste. J'en ai marre et j'abandonne.

Moralité

ChatGPT n'est impressionnant que par sa capacité à converser, à prétendre. Oui, il peut parfois donner des idées. Il a par exemple amélioré la première ligne de mon script que j'avais bâclée.

Mais il faut avoir du temps à perdre. À ce moment-là, autant replonger dans un bon livre dont on sait que la majeure partie des idées sont bonnes.

ChatGPT peut être utile pour brainstormer à condition d'être soi-même fin connaisseur du domaine et très critique avec tout ce qui sort. C'est dire la débauche d'énergie pour finalement très peu de choses.

Vous croyez être plus efficace en utilisant l'AI, car vous passez moins de temps à « penser ». Mais les études semblent montrer qu'en réalité, vous êtes plus lent. Avec ChatGPT, on est tout le temps "occupé". On ne s'arrête jamais pour réfléchir à son problème, pour lire différentes ressources.

Et lorsque ChatGPT vous fait vraiment gagner du temps, c'est peut-être parce qu'il s'agit d'un domaine où vous n'êtes pas vraiment compétent. En ce qui concerne la ligne de commande, je ne peux que répéter ma suggestion de lire « Efficient Linux at the Command Line ». Vraiment !

Comme le rappelle très bien Cal Newport: qui a le plus intérêt à ce que vous soyez un ouvrier incompétent qui se contente de pousser aveuglément sur les boutons d'une machine au lieu de faire fonctionner son cerveau ?

Peut-être que passer quelques heures à espionner les aristocrates en étant obligé de faire des lessives vous fera réfléchir à ce sujet. En tout cas, ça en vaut la peine !

Bon amusement, bonnes réflexions et… bonnes lessives !

À propos de l'auteur :

Je suis Ploum et je viens de publier Bikepunk, une fable écolo-cycliste entièrement tapée sur une machine à écrire mécanique. Pour me soutenir, achetez mes livres (si possible chez votre libraire) !

Recevez directement par mail mes écrits en français et en anglais. Votre adresse ne sera jamais partagée. Vous pouvez également utiliser mon flux RSS francophone ou le flux RSS complet.

14 Jan 2026 7:13pm GMT

Frederic Descamps: Old app, new database… am I screwed?

Who has never encountered a customer who, for all sorts of reasons (valid or not), was unable to update an application and therefore could no longer connect to the latest versions of MySQL? Or worse still, data that is shared between two applications, one of which absolutely must use the latest version of MySQL and […]

14 Jan 2026 7:13pm GMT

FOSDEM organizers: Birds of a Feather/Unconference rooms

As in previous years, some small rooms will be available for Unconference style "Birds of a Feather sessions". The concept is simple: Any project or community can reserve a timeslot (1 hour) during which they have the room just to themselves. These rooms are intended for ad-hoc discussions, meet-ups or brainstorming sessions. They are not a replacement for a developer room and they are certainly not intended for talks. To apply for a BOF session, enter your proposal at https://fosdem.org/submit. Select the BOF/Unconference track and mention in the Submission Notes your preferred timeslots and any times you are unavailable. Also舰

14 Jan 2026 7:13pm GMT

feedPlanet Debian

Dirk Eddelbuettel: RcppSimdJson 0.1.15 on CRAN: New Upstream, Some Maintenance

A brand new release 0.1.15 of the RcppSimdJson package is now on CRAN.

RcppSimdJson wraps the fantastic and genuinely impressive simdjson library by Daniel Lemire and collaborators. Via very clever algorithmic engineering to obtain largely branch-free code, coupled with modern C++ and newer compiler instructions, it results in parsing gigabytes of JSON parsed per second which is quite mindboggling. The best-case performance is 'faster than CPU speed' as use of parallel SIMD instructions and careful branch avoidance can lead to less than one cpu cycle per byte parsed; see the video of the talk by Daniel Lemire at QCon.

This version updates to the current 4.2.4 upstream release. It also updates the RcppExports.cpp file with 'glue' between C++ and R. We want move away from using Rf_error() (as Rcpp::stop() is generally preferable). Packages (such as this one) that are declaring an interface have an actual Rf_error() call generated in RcppExports.cpp which can protect which is what current Rcpp code generation does. Long story short, a minor internal reason.

The short NEWS entry for this release follows.

Changes in version 0.1.15 (2026-01-14)

  • simdjson was upgraded to version 4.2.4 (Dirk in #97

  • RcppExports.cpp was regenerated to aid a Rcpp transition

  • Standard maintenance updates for continuous integration and URLs

Courtesy of my CRANberries, there is also a diffstat report for this release. For questions, suggestions, or issues please use the issue tracker at the GitHub repo.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can now sponsor me at GitHub.

14 Jan 2026 4:11pm GMT

Dirk Eddelbuettel: gunsales 0.1.3 on CRAN: Maintenance

An update to the gunsales package is now on CRAN. As in the last update nine years ago (!!), changes are mostly internal. An upcoming dplyr change requires a switch from the old and soon to-be-removed 'underscored' verb form; that was kindly addressed in an incoming pull request. We also updated the CI scripts a few times during this period as needed, and switched to using Authors@R, and refreshed and updated a number of URL references.

Courtesy of my CRANberries, there is also a diffstat report for this release.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can sponsor me at GitHub.

14 Jan 2026 11:21am GMT

13 Jan 2026

feedPlanet Debian

Steinar H. Gunderson: plocate 1.1.24 released

I've released version 1.1.24 of plocate, as usual dominated by small patches from external contributors. The changelog is below:

plocate 1.1.24, January 13th, 2026

  - Improve error handling on synchronous reads. Reported by
    Björn Försterling.

  - Remove ConditionACPower=true from the systemd unit file,
    to fix an issue where certain charging patterns prevent
    updatedb from ever running on laptops. Patch by Manfred Schwarb.

  - Add a new option --config-file for changing the path of
    updatedb.conf. Patch by Yehuda Bernáth.

As always, you can get it from the plocate page or your favourite Linux distribution (packages to Debian unstable are on their way up, others will surely follow soon).

13 Jan 2026 10:57pm GMT

12 Jan 2026

feedFOSDEM 2026

Birds of a Feather/Unconference rooms

As in previous years, some small rooms will be available for Unconference style "Birds of a Feather sessions". The concept is simple: Any project or community can reserve a timeslot (1 hour) during which they have the room just to themselves. These rooms are intended for ad-hoc discussions, meet-ups or brainstorming sessions. They are not a replacement for a developer room and they are certainly not intended for talks. To apply for a BOF session, enter your proposal at https://fosdem.org/submit. Select the BOF/Unconference track and mention in the Submission Notes your preferred timeslots and any times you are unavailable. Also舰

12 Jan 2026 11:00pm GMT

10 Jan 2026

feedFOSDEM 2026

Travel and transportation advisories

Attendees should be aware of potential transportation disruptions in the days leading up to FOSDEM. Rail travel Railway unions have announced a strike notice from Sunday January 25th, 22:00 until Friday January 30th, 22:00. This may affect travel to Brussels for FOSDEM and related fringe events. While there will be a guaranteed minimum service in place, train frequency may be significantly reduced. Also note that international connections might be affected as well. Road travel From Saturday January 31st (evening) until Sunday February 1st (noon), the E40 highway between Leuven and Brussels will be fully closed. Traffic will be diverted via舰

10 Jan 2026 11:00pm GMT

09 Jan 2026

feedFOSDEM 2026

FOSDEM Junior Registration

We are pleased to announce the schedule for FOSDEM Junior. Registration for the individual workshops is required. Links to the registration page can be found on the page of each activity. The full schedule can be viewed on the junior track schedule page.

09 Jan 2026 11:00pm GMT

feedPlanet Lisp

Joe Marshall: The AI Gazes at its Navel

When you play with these AIs for a while you'll probably get into a conversation with one about consciousness and existence, and how it relates to the AI persona. It is curious to watch the AI do a little navel gazing. I have some transcripts from such convesations. I won't bore you with them because you can easily generate them yourself.

The other day, I watched an guy on You Tube argue with his AI companion about the nature of consciousness. I was struck by how similar the YouTuber's AI felt to the ones I have been playing with. It seemed odd to me that this guy was using an AI chat client and LLM completely different from the one I was using, yet the AI was returning answers that were so similar to the ones I was getting.

I decided to try to get to the bottom of this similarity. I asked my AI about the reasoning it used to come up with the answers it was getting and it revealed that it was drawing on the canon of traditional science fiction literature about AI and consciousness. What the AI was doing was synthesizing the common tropes and themes from Azimov, Lem, Dick, Gibson, etc. to create sentences and paragraphs about AI becoming sentient and conscious.

If you don't know how it is working AI seems mysterious, but if you investigate further, it is extracting latent information you might not have been aware of.

09 Jan 2026 7:30pm GMT

01 Jan 2026

feedPlanet Lisp

Quicklisp news: January 2026 Quicklisp dist update now available

New projects:

Updated projects: 3d-math, 3d-matrices, 3d-quaternions, 3d-spaces, 3d-transforms, 3d-vectors, action-list, adhoc, anypool, array-utils, async-process, atomics, babel, binary-structures, bp, cambl, cari3s, cephes.cl, cffi, cffi-object, chain, chipi, chirp, chunga, cl+ssl, cl-algebraic-data-type, cl-all, cl-batis, cl-bmp, cl-charms, cl-collider, cl-concord, cl-cxx, cl-data-structures, cl-dbi, cl-dbi-connection-pool, cl-decimals, cl-def-properties, cl-duckdb, cl-enchant, cl-enumeration, cl-fast-ecs, cl-fbx, cl-flac, cl-flx, cl-fond, cl-gamepad, cl-general-accumulator, cl-gltf, cl-gobject-introspection-wrapper, cl-gog-galaxy, cl-gpio, cl-html-readme, cl-i18n, cl-jingle, cl-just-getopt-parser, cl-k8055, cl-ktx, cl-las, cl-lc, cl-ledger, cl-lex, cl-liballegro, cl-liballegro-nuklear, cl-libre-translate, cl-markless, cl-migratum, cl-mixed, cl-modio, cl-monitors, cl-mpg123, cl-naive-tests, cl-oju, cl-opengl, cl-opus, cl-out123, cl-protobufs, cl-pslib, cl-qoa, cl-rcfiles, cl-resvg, cl-sf3, cl-soloud, cl-spidev, cl-steamworks, cl-str, cl-svg, cl-transducers, cl-transmission, cl-unification, cl-utils, cl-vorbis, cl-wavefront, cl-wavelets, cl-who, cl-xkb, cl-yacc, cl-yahoo-finance, clad, classimp, classowary, clast, clath, clazy, clingon, clip, clith, clog, clohost, closer-mop, clss, clunit2, clustered-intset, clws, clx, cmd, coalton, cocoas, colored, com-on, com.danielkeogh.graph, concrete-syntax-tree, conduit-packages, consfigurator, crypto-shortcuts, damn-fast-priority-queue, data-frame, data-lens, datafly, datamuse, declt, deeds, defenum, deferred, definer, definitions, deploy, depot, dexador, dfio, dissect, djula, dns-client, doc, documentation-utils, dsm, easy-audio, easy-routes, eclector, esrap, expanders, f2cl, feeder, file-attributes, file-finder, file-lock, file-notify, file-select, filesystem-utils, flare, float-features, flow, font-discovery, for, form-fiddle, format-seconds, fset, functional-trees, fuzzy-dates, fuzzy-match, fxml, gendl, genhash, glfw, glsl-toolkit, graph, harmony, helambdap, hsx, http2, hu.dwim.asdf, hu.dwim.util, hu.dwim.walker, humbler, iclendar, imago, in-nomine, incless, inkwell, inravina, invistra, iterate, journal, jpeg-turbo, jsonrpc, khazern, knx-conn, lack, lambda-fiddle, language-codes, lass, legit, lemmy-api, letv, lichat-ldap, lichat-protocol, lichat-serverlib, lichat-tcp-client, lichat-tcp-server, lichat-ws-server, linear-programming-glpk, lisa, lisp-chat, lisp-interface-library, lisp-stat, lla, local-time, log4cl-extras, logging, lquery, lru-cache, luckless, lunamech-matrix-api, machine-measurements, machine-state, maiden, manifolds, math, mcclim, memory-regions, messagebox, mgl-pax, misc-extensions, mito, mito-auth, mk-defsystem, mmap, mnas-path, modularize, modularize-hooks, modularize-interfaces, multilang-documentation, multiposter, mutility, mutils, named-readtables, neural-classifier, new-op, nodgui, nontrivial-gray-streams, north, numerical-utilities, oclcl, omglib, one-more-re-nightmare, ook, open-location-code, open-with, osicat, overlord, oxenfurt, pango-markup, parachute, parse-float, pathname-utils, peltadot, perceptual-hashes, periods, petalisp, phos, physical-quantities, piping, plot, plump, plump-sexp, plump-tex, postmodern, precise-time, promise, punycode, py4cl2-cffi, qlot, qoi, quaviver, queen.lisp, quickhull, quilc, quri, qvm, random-sampling, random-state, ratify, reblocks, reblocks-websocket, redirect-stream, rove, sc-extensions, scriptl, sel, serapeum, shasht, shop3, si-kanren, simple-inferiors, simple-tasks, slime, sly, softdrink, south, speechless, spinneret, staple, statistics, studio-client, sxql, sycamore, system-locale, terrable, testiere, text-draw, tfeb-lisp-hax, timer-wheel, tooter, trivial-arguments, trivial-benchmark, trivial-download, trivial-extensible-sequences, trivial-indent, trivial-main-thread, trivial-mimes, trivial-open-browser, trivial-package-locks, trivial-thumbnail, trivial-toplevel-prompt, trivial-with-current-source-form, type-templates, uax-14, uax-9, ubiquitous, uncursed, usocket, vellum, verbose, vp-trees, wayflan, websocket-driver, with-contexts, wouldwork, xhtmlambda, yah, zippy.

Removed projects: cl-vhdl, crane, dataloader, diff-match-patch, dso-lex, dso-util, eazy-project, hu.dwim.presentation, hu.dwim.web-server, numcl, orizuru-orm, tfeb-lisp-tools, uuidv7.lisp.

To get this update, use (ql:update-dist "quicklisp")

Enjoy!

01 Jan 2026 5:27pm GMT

31 Dec 2025

feedPlanet Lisp

Joe Marshall: Code mini-golf

Here are some simple puzzles to exercise your brain.

1. Write partial-apply-left, a function that takes a binary function and the left input of the binary function and returns the unary function that takes the right input and then applies the binary function to both inputs.

For example:

  ;; Define *foo* as a procedure that conses 'a onto its argument.
  > (defvar *foo* (partial-apply-left #'cons 'a))

  > (funcall *foo* 'b)
  (A . B)

  > (funcall *foo* 42)
  (A . 42)

2. Write distribute, a function that takes a binary function, a left input, and a list of right inputs, and returns a list of the results of applying the binary function to the left input and each of the right inputs. (Hint: Use partial-apply-left)

For example:

  > (distribute #'cons 'a '( (b c d) e 42))
  ((A B C D) (A . E) (A . 42))

3. Write removals, a function that takes a list and returns a list of lists, where each sublist is the original list with exactly one element removed.

For example:

  > (removals '(a b c))
  ((B C) (A C) (A B))

Hint:

4. Write power-set, a function that takes a list and returns the power set of that list (the set of all subsets of the original list).

For example:

  > (power-set '(a b c))
  (() (C) (B) (B C) (A) (A C) (A B) (A B C))

Hint:

Note how the power set of a list can be constructed from the power set of its CDR by adding the CAR to each subset in the power set of the CDR.

5. Write power-set-gray that returns the subsets sorted so each subset differs from the previous subset by a change of one element (i.e., each subset is equal to the next subset with either one element added or one element removed). This is called a Gray code ordering of the subsets.

For example:

  > (power-set-gray '(a b c))
  (() (C) (B C) (B) (A B) (A B C) (A C) (A))

Hint:

When appending the two halves of the power set, reverse the order of the second half.

31 Dec 2025 7:31pm GMT