Jouni's face

I am interested in mathematics, programming and data science, currently employed by Reaktor as Senior AI Developer. Favourite technologies include Python, Matplotlib, Clojure, Go. I sometimes coach math-olympiad contestants and am trying to learn tai chi.

For contact information, see About.

Some recent posts below.

tramp.el with a small target

A Tramp connection issue in a limited Unix environment

Recently I needed to edit some files on an old-school shared web host. That host had a severely limited Unix environment, so I could access it via ssh and use basic shell commands, but most of the usual utilities were missing. No perl, no python, but sed and awk were present. Based on the presence of jk_lsh I suppose it was a jailkit-based chroot jail.

Anyway, Emacs and tramp.el to the rescue! Or not:

Tramp: 'getconf PATH' not successful, using default value "/bin:/usr/bin".
Tramp: Opening connection nil for remote using ssh...failed

Read more…

ChatGPT ylioppilaskokeessa

Pääsisikö ChatGPT ylioppilaaksi?

Sitähän on puitu viime kuukaudet kaikissa kahvi- ja baaripöydissä (ainakin nörttipiireissä), miten hurjasti ChatGPT:n kaltaiset suuret kielimallit ovat kehittyneet, ja vievätkö ne meiltä kohta kaikki siistit sisätyöt. Yksi yleinen argumentti näissä keskusteluissa on, että vaikka kielimalli voi tuottaa häkellyttävän uskottavaa tekstiä, se on pohjimmiltaan vain seuraavan sanan ennustin, vähän kuin puhelimen ennustava tekstinsyöttö jolla on taustallaan muutama kertaluokka enemmän dataa ja laskentatehoa kuin puhelimessa. Siksi se on vain stokastinen papukaija, joka papattaa sanoja ymmärtämättä mitään todellisuudesta. Toki papukaijalla voidaan korvata joku keskinkertainen keskitason johtaja, jonka tuottama sisältömarkkinointistrategia tai monitilatoimistosuunnitelma on yhtä lailla irrallaan todellisuudesta ja siksi mahdoton erottaa papukaijan tuotoksista, mutta eihän se osaa tehdä oikeaa ajatustyötä. Varsinkin laskennossa ChatGPT on tunnetusti huono, joten ehkäpä laskento onkin se ihmisyyden kova ydin, jota mikään papukaija-armeija ei voi koskaan saavuttaa.

Vai voiko? Kokeillaan.

Read more…

Switching keyboard layouts on macOS

Those §°±¤ keyboard layouts

I imagine this frustration is shared by programmers who don't speak English as their native language: to fluently type text in your language, you need easy access to some funny characters (åäö in my case) which are best found on your native keyboard layout. But that layout was designed by people who value characters like §°±¤ over the characters you need for programming, such as []{}\|.

So you switch between layouts. This used to work fine on MacOS X, but in some recent versions of macOS it has become unreliable. It feels like the layout switch sometimes fails (perhaps a third of the time), or happens after a delay, and sometimes it even switches the layout indicator but not the actual layout. I thought it was just me, but a colleague asked about this recently, so I guess it could be more widespread.

It could be this bug but that was supposed to be solved in 11.2? Also I never liked using the fn key for this, it gives some extra slow graphical feedback. (I used to map ctrl-shift-space to the layout switch instead of the default ctrl-space, because the latter is needed in Emacs.)

Read more…

Sorting floats

A floating-point mystery

Here's a bug I ran into several years ago. Assume we have a bunch of points defined by their coordinates and we want their pairwise distances in increasing order:

distances = [dist(x, y) for x, y in itertools.combinations(points, 2)]
distances.sort()

Here dist is a function that computes some kind of distance measure. The details don't matter much but let's say that it's Manhattan distance,

def dist(x, y):
    return sum(abs(a - b) for a, b in zip(x, y))

Now we have the distances in order so that distances[0] is the smallest and distances[-1] is the largest... right? But it turned out that distances[0] was not the same as min(distances).

If you want to ponder the mystery yourself, the question is how to complete the assignment points = ... so that the assertion at the end fails:

import itertools

def dist(x, y):
    return sum(abs(a - b) for a, b in zip(x, y))

points = ...

distances = [dist(x, y) for x, y in itertools.combinations(points, 2)]
distances.sort()

assert distances[0] == min(distances)

Read more…