A really geeky way to start a Monday morning is to be nerd-sniped by the cool Fermat’s Library twitter account…
… reading up on the cool Tupper’s Self-Referential Formula thinking “Can This be Done in SQL?™”
As we all know from a previous article, SQL is turing complete, so the answer must be yes. And in fact, as it turns out, this is actually super easy, compared to some other problems I’ve been solving with SQL on this blog in the past.
The Formula
The formula is really simple:
Or, in a more programmer-y way:
1/2 < floor(mod(floor(y/17)*2^(-17*floor(x)-mod(floor(y), 17)),2))
Luckily, this syntax also happens to be SQL syntax, so we’re almost done. So, let’s try plotting this formula for the area of x BETWEEN 0 AND 105
and y BETWEEN k AND k + 16
, where k is just some random large number, let’s say
96093937991895888497167296212785275471500433966012930665 15055192717028023952664246896428421743507181212671537827 70623355993237280874144307891325963941337723487857735749 82392662971551717371699516523289053822161240323885586618 40132355851360488286933379024914542292886670810961844960 91705183454067827731551705405381627380967602565625016981 48208341878316384911559022561000365235137034387446184837 87372381982248498634650331594100549747005931383392264972 49461751545728366702369745461014655997933798537483143786 841806593422227898388722980000748404719
Unfortunately, most SQL databases cannot handle such large numbers without any additional libraries, except for the awesome PostgreSQL, whose decimal / numeric types can handle up to 131072 digits before the decimal point and up to 16383 digits after the decimal point.
Yet again, unfortunately, even PostgreSQL by default can’t handle such precisions / scales, so we’re using a trick to expand the precision beyond what’s available by default (for a better workaround, see Torsten Grust’s comment in the comments section). Here’s the SQL query:
WITH t1(k, z) AS ( SELECT ('96093937991895888497167296212785275471500433966012930665' || '15055192717028023952664246896428421743507181212671537827' || '70623355993237280874144307891325963941337723487857735749' || '82392662971551717371699516523289053822161240323885586618' || '40132355851360488286933379024914542292886670810961844960' || '91705183454067827731551705405381627380967602565625016981' || '48208341878316384911559022561000365235137034387446184837' || '87372381982248498634650331594100549747005931383392264972' || '49461751545728366702369745461014655997933798537483143786' || '841806593422227898388722980000748404719')::numeric, (repeat('0', 2000) || '.' || repeat('0', 1000) || '1')::numeric ), tupper(x, y, b) AS ( SELECT x, y, 0.5 < floor(mod(floor(y / 17) * 2 ^ (-17 * x - mod(y, 17)), 2)) FROM t1, LATERAL ( SELECT z + x AS x FROM generate_series(0, 105) t2(x)) t2, LATERAL ( SELECT z + k + y AS y FROM generate_series(0, 16) t3(y)) t3 ) SELECT string_agg( CASE WHEN b THEN '@@' ELSE ' ' END, '' ORDER BY x DESC) FROM tupper GROUP BY y ORDER BY y ASC;
What’s the result of the above?
string_agg | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ @@ @@ @@@@ @@ @@ @@ @@ @@ @@ @@ @@@@ @@ @@ | @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ | @@@@ @@ @@ @@ @@ @@@@ @@ @@ @@ @@ @@ @@ @@@@ @@@@@@@@ @@@@@@ @@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ | @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ | @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@@@ @@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ | @@ @@ @@ @@ @@ @@ @@ @@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@ @@ @@ | @@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ | @@ @@ @@@@ @@ @@@@ @@@@@@ @@ @@ @@ @@ @@@@@@ @@@@@@ @@ @@@@@@ @@@@@@ @@ @@ @@ @@ @@ | @@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@@@@@@@ @@ @@ @@ @@ @@ | @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ | @@@@ @@ @@ @@ @@ @@ @@@@ @@@@@@ @@ @@ @@ @@@@ @@ @@@@@@@@ @@@@@@@@ @@ @@ | @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ | @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ | @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ | @@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ | @@ @@ @@ @@ @@ @@ | @@@@@@ @@ @@@@@@ @@@@@@ @@ @@@@@@ |
It is a formula that can plot itself on a 17-bit wide bitmap. Cool, eh?
Play around with this formula yourself:
https://www.tuppers-formula.tk