Tips for writing quines

30

4

A is a program that produces output that's identical to the program's source code. On this website, we generally only care about proper quines (at the time of writing, the current definition is "some part of the output is encoded by a different part of the program").

What advice do you have for writing proper quines, or programs with quine-like properties? As usual, each tip should be in a different answer.

user62131

Posted 2017-04-06T13:17:26.167

Reputation:

Answers

14

Take advantage of string formatting

One of the easiest ways to create a quine is to define a string, then put the string inside itself with string formatting.

s='s=%r;print s%%s';print s%s


So in this example Python quine, we declare a string with the first part equal to whatever is before the string s=, then we allow for the string to be inserted with formatting with %r, and finally we put what comes after the string to print and format it. The trailing newline is because print prints a trailing newline.

So the template is really this, in Python:

<A>'<A>%r<B>'<B>

To expand the existing quine with more code:

<more A>s='<more A>s=%r;print s%%s<more B>';print s%s<more B>

mbomb007

Posted 2017-04-06T13:17:26.167

Reputation: 21 944

14

Use eval to reduce the need to copy code

The majority of quines require two copies of the code; one to be executed, one as data. This can end up doubling the length of the source code, making it harder to maintain, and worsening the score if you're writing the quine for a competition.

Merging the two copies means that one piece of information needs to be used for two purposes. Trying to treat your code as data is often not possible, and is typically considered cheating when it is. Treating data as code, however, can be done in many languages via use of a builtin, typically called eval. As such, your quine basically consists of storing the main body of your quine in a variable (so that you can refer to it more than once), then evaluating that variable.

Here's an example of how this works (the example is written in Python, but something similar works in many other languages):

d='print("d="+repr(d)+"\\neval(d)")'
eval(d)

user62131

Posted 2017-04-06T13:17:26.167

Reputation:

2@QPaysTaxes: I aim to make my code here as readable and maintainable as the victory condition allows. Unfortunately, that's still typically indistinguishable from ASCII line noise (or just regular line noise if I'm using Jelly) from people who aren't used to the language. – None – 2017-04-07T07:03:08.867

9

Use string delimiters that nest without escaping

Often, one of the hardest parts about writing a quine is the escaping step. This is needed in almost every quine; the issue is that you're storing data somehow, and you need to replicate the code that stores the data in the quine's output. That code will contain an escaped form of the data, so the program will see an unescaped form, and you'll need to re-escape it.

The easiest way to handle the unescaping step is if the escaped and unescaped forms of the data differ only in the presence or absence of string delimiters. Escaping is thus a simple matter of adding a new pair of string delimiters around the string. Unfortunately, this can clearly only work if the string delimiters themselves can be expressed in the data without escaping.

Perl is a good example of a language where this trick works. Although its usual string delimiters are "…" or '…', the less commonly used q(…) nests, allowing this sort of quine to be written:

$_=q($_=q(0);s/\d/$_/;print);s/\d/$_/;print

This is a code+data quine. s/// is a regex string-replace operation; we use 0 as the marker, and match it within the regex as \d ("any digit"), to avoid using the marker more than once (although as another optimization, we could actually just have used 0 again, because Perl's s/// only replaces the first occurrence by default). Note that there's no explicit escaping step needed here, as the q(…) delimiters can just be included literally in the data string.

user62131

Posted 2017-04-06T13:17:26.167

Reputation:

9

Stringified functions

In several languages, function objects (or equivalent constructs) implicitly store their source code, and will return it when converted into a string. This allows compact quines without using string eval. A notable example of such a language is JavaScript:

function f(){console.log(f+"f()")}f()

This code defines and calls a function f that, when called, prints its own source code followed by a call to itself. The only part of the program that needs to be duplicated is the function call f(). Of course, the function body can include an arbitrary "payload" of code that will also be executed when the function is called.


A more compact version of the same trick works in the golfing languages GolfScript:

{".~"}.~

and CJam:

{"_~"}_~

Each of these quines first defines an anonymous code block (enclosed in braces), which behaves much like a function object in JavaScript: it can be executed, and if stringified, it returns its source code. The rest of the code (.~ in GolfScript, or _~ in CJam) then executes the block, while leaving a copy of it on the stack. The code inside the block then pushes a string onto the stack that repeats the code outside the block. When the interpreter exits, it automatically stringifies and prints everything left on the stack. As with the JavaScript example, these code blocks could also be made to carry and execute an arbitrary payload of additional code without having to duplicate it.

Ilmari Karonen

Posted 2017-04-06T13:17:26.167

Reputation: 19 513

8

Code + data quines

The most general structure for a quine looks something like this pseudocode:

data = "an escaped version of the entire program,
        with this string replaced with a marker"
program = data.replace(
  an expression that evaluates to the marker but doesn't mention it,
  escaped(data))
print program;

This structure can be used to write a (fairly naive) quine in most languages. However, it tends to score fairly badly on most scoring systems, because you have to write the entirety of the program twice. However, most quine structures can be considered optimizations of this one.

There are some subtleties to this. In some languages, the hardest part of performing this operation is to write the escaping code; in many languages, producing the marker without mentioning its name is difficult; and in some esoteric languages, you'll have to invent your own sort of string literal. All three operations tend not to cause too much trouble, though.

For example, we can write a Python quine escaping a string using repr, and using the 2-character-sequence x" string (which is representable as "x\"", i.e. not using the sequence x" in the string representation of the string itself) as the marker:

d='d=x"\nprint(str.replace(d,"x\\"",repr(d)))'
print(str.replace(d,"x\"",repr(d)))

user62131

Posted 2017-04-06T13:17:26.167

Reputation:

2It may be worth noting (possibly in another answer) that inserting the string into the position of a marker is often expensive in esolangs, and it might worth structuring the code such that the string itself is the first or the last thing (maybe separated from the end by one or two characters which you can hardcode) so that you know where it has to go. – Martin Ender – 2017-04-06T13:45:06.040

@MartinEnder: I agree that that's worth mentioning, but it's probably another answer (rather than a comment or an edit in this answer). Most quine tips are modifications to this general structure, so I wanted to get it out there as a tip on its own first, as many people don't have any idea where to start for writing a quine. – None – 2017-04-06T13:46:07.313

An alternative to a marker is to use two strings, I did that for Glass.

– Ørjan Johansen – 2017-04-06T18:06:26.617

4

Exploit wrapping source code

In quite a few languages (mostly 2D languages), the source code can wrap around; under certain circumstances (e.g. in Befunge-98, if your program is a one-liner) going past the end of the program will take you back to the start of the program. This kind of nonlinear behaviour means that you can write code that's inside and outside a string literal at the same time; an unmatched " (or whatever the string delimiter is) will effectively give you a string containing the whole of the rest of the program (except for the " itself).

One problem with using this trick is that you'll get the string as seen from the point of view of the ", rather than from the start of the program (like you'd want). As such, it's likely easiest to rearrange the program so that the " appears at the start or end. This often means chopping your program up into multiple pieces and making use of whatever interesting/unusual flow control commands your language has (most languages which let string literals wrap around the program have a good selection of these).

A good example is @Justin's Befunge-98 quine:

<@,+1!',k9"

The unmatched " at the end of the program wraps the whole program in a string literal, so (running right to left due to the < at the start) all we have to do is output the program (9k), then output the double quote ('!1+,) and exit (@). This saves needing two copies of the program (one as code, one as data); the two copies are the same piece of code, just interpreted in different ways.

user62131

Posted 2017-04-06T13:17:26.167

Reputation:

4

Remember the Structure of a Quine

I like to think of quines as three parts, rather than 2:

  • Part 1: Generate a data representation of parts 2 and 3.
  • Part 2: Use the data to algorithmically print back part 1.
  • Part 3: Decode the representation to print parts 2 and 3.

This can make it easier to think about quines. Here is a Python quine, with each line corresponding to a part:

s = "print(\"s = \" + repr(s))\nprint(s)"
print("s = " + repr(s))
print(s)

Sometimes, you use an eval or similar to remove duplication, but generally I have found that this helps in writing simple quines.

Let's take a look at two different Underload quines. This is the first:

(:aSS):aSS

The first part is (:aSS), which generates the data representation. The second is :aS, which prints (:aSS). The third part is S, which prints :aSS.

Here is the second quine:

(:aS(:^)S):^

At first, this doesn't seem to fit. But if you expand the quine, you get:

(:aS(:^)S):aS(:^)S

Now (:aS(:^)S) is part 1, :aS is part 2, and (:^)S is part 3.

Esolanging Fruit

Posted 2017-04-06T13:17:26.167

Reputation: 13 542