Tupper's Self-Referential Formula (copied from Wikipedia)

Tupper's self-referential formula is a formula defined by Jeff Tupper that, when graphed in two dimensions at a very specific location in the plane, can be "programmed" to visually reproduce the formula itself. It is used in various math and computer science courses as an exercise in graphing formulae.

$$ \frac{1}{2} < \left\lfloor \text{mod}\left( \left\lfloor \frac{y}{17} \right\rfloor 2^{ -17 \lfloor x \rfloor -\text{mod}\left( \lfloor y \rfloor ,17 \right) } ,2 \right) \right\rfloor $$

where \$\lfloor\cdot\rfloor\$ is the floor function.

Let \$k\$ be the following 543-digit number: 960939379918958884971672962127852754715004339660129306651505519271702802395266424689642842174350718121267153782770623355993237280874144307891325963941337723487857735749823926629715517173716995165232890538221612403238855866184013235585136048828693337902491454229288667081096184496091705183454067827731551705405381627380967602565625016981482083418783163849115590225610003652351370343874461848378737238198224849863465033159410054974700593138339226497249461751545728366702369745461014655997933798537483143786841806593422227898388722980000748404719

If one graphs the set of points \$(x, y)\$ in \$0 \le x < 106\$ and \$k \le y < k + 17\$ satisfying the inequality given above, the resulting graph looks like this (note that the axes in this plot have been reversed, otherwise the picture comes out upside-down):

Result of Tupper's Self-Referential Formula

So what?

The interesting thing about this formula is that it can be used to graph any possible black and white 106x17 image. Now, actually searching through to search would be extremely tedious, so there's a way to figure out the k-value where your image appears. The process is fairly simple:

  1. Start from the bottom pixel of the first column of your image.
  2. If the pixel is white, a 0 will be appended to the k-value. If it is black, append a 1.
  3. Move up the column, repeating step 2.
  4. Once at the end of the column, move to the next column and start from the bottom, following the same process.
  5. After each pixel is analyzed, convert this binary string to decimal, and multiply by 17 to get the k-value.

What's my job?

Your job is to create a program which can take in any 106x17 image, and output its corresponding k-value. You can make the following assumptions:

  1. All images will be exactly 106x17
  2. All images will only contain black (#000000) or white (#FFFFFF) pixels, nothing in between.

There's a few rules, too:

  1. Output is simply the k-value. It must be in the proper base, but can be in any format.
  2. Images must be read from either a PNG or PPM.
  3. No standard loopholes.

Test Images

[ Nintendo ] should produce ~1.4946x10542

[ A big number ] should produce ~7.2355x10159

[ 2^1801 * 17 ] should produce 21801 * 17

[ 2^1802 - 1 * 17 ] should produce (21802-1) * 17

Check out this Gist for the exact solutions.

This is , so least number of bytes wins.

Helpful Links


Wolfram Mathworld

  • \$\begingroup\$ Can I take in a PPM? \$\endgroup\$
    – Maltysen
    Jun 16, 2015 at 20:36
  • \$\begingroup\$ EDIT: Yes, PPM format is allowed. When I came up with the program I intended for PNGs to be used, but allowing PPM should allow for more golfing languages to participate. \$\endgroup\$
    – Kade
    Jun 16, 2015 at 20:46
  • 3
    \$\begingroup\$ As I was reading this question, before getting to "What's my job" part, I was positive I'm going to see the word quine somewhere. \$\endgroup\$
    – Jacob
    Jun 17, 2015 at 12:21
  • \$\begingroup\$ I won't pretend to be a programmer who can do this kind of stuff, instead I will simply present an innocent, earnest question: Yes, but can it be done in reverse? I.e. feeding in the solution and seeing the *.png generated as the result? \$\endgroup\$
    – user41644
    Jun 17, 2015 at 21:06
  • \$\begingroup\$ @NotAsSharpAsYouGuys: if you have arbitrary precision arithmetic it's trivial, you just have to check the result of that formula for each pixel and output the resulting image. \$\endgroup\$ Jun 18, 2015 at 11:31

5 Answers 5


Pyth - 21 bytes

Simple to do with pyth's i base conversion. Takes input as PBM file name and reads using ' command. I had to use !M to negate blacks and whites. Everything else is self-explanatory.

*J17i!MsC_cJrstt.z7 2

Try it here online. (Web interpreter can't read files, so is modified and takes file as input).

  • 64
    \$\begingroup\$ I don't think anything in Pyth is self-explanatory. :/ \$\endgroup\$
    – Alex A.
    Jun 16, 2015 at 23:59
  • 3
    \$\begingroup\$ No language I know can beat this one. But then again none of the languages I know are "made-for-golfing". \$\endgroup\$
    – Mahesh
    Jun 17, 2015 at 9:10
  • \$\begingroup\$ Can't open link, path is too long, dang (Safari 8.1) \$\endgroup\$
    – Kametrixom
    Jun 17, 2015 at 9:32
  • \$\begingroup\$ Your example image seems wrong. Did you mean to use P2 rather than P3? \$\endgroup\$ Jun 17, 2015 at 16:07
  • \$\begingroup\$ Oh wait, it's not even P2, it looks like P1 but inverted \$\endgroup\$ Jun 17, 2015 at 16:20

CJam, 16


With big thanks to Dennis. Try it online

In case you're having problems with the url, this is the input I tested:

106 17

I used the format that GIMP generated when exporting as ASCII pbm, with the comment removed.


l,    read the first line ("P1" magic number) and get its length (2)
l~    read and evaluate the second line (106 17)
q     read the rest of the input (actual pixels)
:~    evaluate each character ('0' -> 0, '1' -> 1, newline -> nothing)
f*    multiply each number by 17
/     split into rows of length 106
W%    reverse the order of the rows
z     transpose
e_    flatten (effectively, concatenate the lines)
      now we have all the pixels in the desired order, as 0 and 17
b     convert from base 2 "digits" to a number
  • \$\begingroup\$ I got it in the URL for you. \$\endgroup\$
    – mbomb007
    Jun 17, 2015 at 17:17
  • \$\begingroup\$ @mbomb007 thanks, not sure what went wrong. \$\endgroup\$ Jun 17, 2015 at 17:52
  • \$\begingroup\$ If you don't have to deal with comments, l;l~\qN-/W%zs:~2b* should work just as well. \$\endgroup\$
    – Dennis
    Jun 17, 2015 at 19:03
  • \$\begingroup\$ @Dennis OMG, there are several levels of brilliance there :) wanna post it by yourself? \$\endgroup\$ Jun 17, 2015 at 19:27
  • \$\begingroup\$ I don't think a separate answer would be sufficiently different from yours. \$\endgroup\$
    – Dennis
    Jun 17, 2015 at 19:32

Python 2: 133 110 bytes

A first attempt in python using PIL:

from PIL.Image import*
while a<1802:k=(j[a/17,16-a%17][0]<1)+k*2;a+=1
print k*17

Thanks to helpful commenters below

  • 2
    \$\begingroup\$ as you only use once Image.open(input()).load and it doesn't looke like you're modifying it, wouldn't it be better to use it as it is, instead of using a var j? it would be something like this from PIL import Image k=0 for a in range(1802):y=a%17;x=a/17;k=(0 if Image.open(input()).load()[x,16-y][0]else 1)+k*2 print k*17 \$\endgroup\$
    – Katenkyo
    Jun 17, 2015 at 11:50
  • 3
    \$\begingroup\$ Continuing on @Katenkyo's point, you can also just plug in a/17 and a%17 in the appropriate locations, and you can abuse the fact that 1 is truthy and 0 is falsy. Here's the result of these changes, you'll be down to 111 bytes :) \$\endgroup\$
    – Kade
    Jun 17, 2015 at 13:08
  • \$\begingroup\$ @Kateyenko, sadly input() gets called on every iteration of the loop with that modification. Editing with other tips though, thank you. \$\endgroup\$
    – joc
    Jun 17, 2015 at 17:01
  • 1
    \$\begingroup\$ (...<1) --> 0**... maybe? \$\endgroup\$
    – Sp3000
    Jun 17, 2015 at 17:28

C#, 199

This was fun! There's nothing wrong with reloading a bitmap 106 * 17 times, right? I did it as a function to save some bytes, not sure if that's legal.

BigInteger s(string i){return (Enumerable.Range(0,106).SelectMany(x=>Enumerable.Range(0,17).Select(y=>new BigInteger(new Bitmap(i).GetPixel(x,y).B==0?1:0)).Reverse()).Aggregate((x,y)=>(x<<1)+y)*17);}

i is the input file name.

Also, as a single expression, just because it is one expression, with i provided or subbed (167 bytes)

(Enumerable.Range(0,106).SelectMany(x=>Enumerable.Range(0,17).Select(y=>new BigInteger(new Bitmap(i).GetPixel(x,y).B==0?1:0)).Reverse()).Aggregate((x,y)=>(x<<1)+y)*17)
  • 1
    \$\begingroup\$ The question says "your job is to create a program..." \$\endgroup\$ Jun 18, 2015 at 12:39

Wolfram Language (Mathematica) 69 50 Bytes

Update: After revisiting this code a few years later due to @Matt's comment, I've found a few bytes of savings. Note that the test pictures must be Binarized first, because they are 24 bit color PNGs as downloaded from the posted question, instead of being monochrome format as posted in the assumptions.


old code


This function will reproduce the image:

  • \$\begingroup\$ The image is in monochrome format so you can save those 9 bytes. \$\endgroup\$
    – matt
    Sep 25, 2020 at 14:45
  • \$\begingroup\$ Actually the test images as provided are in three eight bit color channels. The PNG format supports monochrome, and when binarized before saving would then eliminate the need to use Binarize@. I just left it in just in case people wanted to try the code out with the provided pictures and actually have it work. \$\endgroup\$ Sep 25, 2020 at 17:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.