Inspiration

Doom on X is a popular hobby for a certain demographic. Recently, I'd seen Doom on a pregnancy test. Bad Apple is a popular internet video which has been run on at least 149 things according to this playlist, including Desmos, HTML Checkboxes, and a TI-84. Following in this illustrious tradition, I present Bad Apple in a quine.

What it does

A quine is a program that takes no input and produces itself as output. A "simple" (it's not!) C quine is the following (from StackOverflow):

char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";

main() {
    printf(f,34,f,34,10);
}

I present a quine written in C which when compiled and executed, produces output which contains a Bad Apple frame in comments along with its own source code. This output can be saved into a C file, compiled and executed to print the next Bad Apple frame in comments along with its source code. This can be repeated in an infinite loop to play the first 100 frames* from Bad Apple in a loop.

*: We actually sample one out of every two frames to have more variety, so it's really every other frame from the first 200 frames.

How we built it

A good starting point was this repository of quines which contains good examples of writing C quines. I tried to copy as little as possible, and while the method of making a quine is directly taken from this repository, many of the surrounding scripts used for generating data and formatting the quine were written independently.

Challenges we ran into

Two major challenges:

  1. Minifying the C code into a rectangular shape proved surprisingly hard; there are many levels of string escaping to deal with in a quine environment, and splitting strings while preserving escapes (eg. '\"') was hard. I ended up with a Haskell script that failed at properly splitting strings. (Attempting to vibe-code this on a lark failed and left me worse off.)

  2. Coming up with a good compression algorithm that was compact in the C code without relying on external libraries was difficult. Run-length encoding achieved a mean 8.8% compression ratio (good!) but I noticed recurring patterns in the RLE data, indicating that I could've pushed compression farther.

A few minor challenges:

  • C segfaults. I will never be free and I accept it.
  • VSCode slowing down when I'm copying kilobytes of text around.

Accomplishments that we're proud of

Bad Apple on a quine!!

What we learned

Vibe coding is bad; I should keep my Haskell skills sharp -- it's a good language.

Other ideas that were considered

My original idea for this project was to somehow derive Bad Apple from visualizing a compiler's optimization passes on a seemingly-innocuous program. I thought of a scheme on coloring cells based on whether an IR node was optimized in a pass or not, but realized that the code that would trigger this would look rather boring or be very hard to construct. I then considered coming up with more interesting looking expressions that could still lead to Bad Apple in optimization passes. I considered deriving implicit surface formulas for each frame (which I knew from Matt Keeter's research) but that proved to be more complicated than doable in the few hours I had. I then switched to thinking about quines and landed on the current idea.

What's next for Quine Apple: Bad Apple in a C Quine

I might attempt to figure out better compression, grayscale rendering, and a smaller ("golfed") quine.

More Information

I ran out of time to edit this, so look at the Github repo for more.

Built With

Share this project:

Updates