33

I have seen a lot of C/C++ based solutions to this problem where we have to write a program that upon execution prints its own source.

some solutions --

http://www.cprogramming.com/challenges/solutions/self_print.html

Quine Page solution in many languages

There are many more solutions on the net, each different from the other. I wonder how do we approach to such a problem, what goes inside the mind of the one who solves it. Lend me some insights into this problem... While solutions in interpreted languages like perl, php, ruby, etc might be easy... i would like to know how does one go about designing it in compiled languages...

Thomas Owens
  • 114,398
  • 98
  • 311
  • 431
Abhishek Mishra
  • 5,002
  • 8
  • 36
  • 38

10 Answers10

55

Aside from cheating¹ there is no difference between compiled and interpreted languages.

The generic approach to quines is quite easy. First, whatever the program looks like, at some point it has to print something:

print ...

However, what should it print? Itself. So it needs to print the "print" command:

print "print ..."

What should it print next? Well, in the mean time the program grew, so it needs to print the string starting with "print", too:

print "print \"print ...\""

Now the program grew again, so there's again more to print:

print "print \"print \\\"...\\\"\""

And so on. With every added code there's more code to print. This approach is getting nowhere, but it reveals an interesting pattern: The string "print \"" is repeated over and over again. It would be nice to put the repeating part into a variable:

a = "print \""
print a

However, the program just changed, so we need to adjust a:

a = "a = ...\nprint a"
print a

When we now try to fill in the "...", we run into the same problems as before. Ultimately, we want to write something like this:

a = "a = " + (quoted contents of a) + "\nprint a"
print a

But that is not possible, because even if we had such a function quoted() for quoting, there's still the problem that we define a in terms of itself:

a = "a = " + quoted(a) + "\nprint a"
print a

So the only thing we can do is putting a place holder into a:

a = "a = @\nprint a"
print a

And that's the whole trick! Anything else is now clear. Simply replace the place holder with the quoted contents of a:

a = "a = @\nprint a"
print a.replace("@", quoted(a))

Since we have changed the code, we need to adjust the string:

a = "a = @\nprint a.replace(\"@\", quoted(a))"
print a.replace("@", quoted(a))

And that's it! All quines in all languages work that way (except the cheating ones).

Well, you should ensure that you replace only the first occurence of the place holder. And if you use a second place holder, you can avoid needing to quote the string.

But those are minor issues and easy to solve. If fact, the realization of quoted() and replace() are the only details in which the various quines really differ.


¹ by making the program read its source file

vog
  • 23,517
  • 11
  • 59
  • 75
  • But how do you avoid replacing @ by a in replace(\"@\", quoted(a)) part? As far as I understand the replace should take place only for the first occurrence of @, namely @\nprint. Am I right? That is replace should replace only the first occurrence of the symbol? – Yrogirg Oct 30 '12 at 12:12
9

There are a couple of different strategies to writing quines. The obvious one is to just write code that opens the code and prints it out. But the more interesting ones involve language features that allow for self-embedding, like the %s-style printf feature in many languages. You have to figure out how to embed something so that it ends up resolving to the request to be embedded. I suspect, like palindromes, a lot of trial and error is involved.

aaronsw
  • 4,455
  • 5
  • 31
  • 27
1

The usual approach (when you can't cheat*) is to write something that encodes its source in a string constant, then prints out that constant twice: Once as a string literal, and once as code. That gets around the "every time I write a line of code, I have to write another to print it out!" problem.

'Cheating' includes: - Using an interpreted language and simply loading the source and printing it - 0-byte long files, which are valid in some languages, such as C.

Nick Johnson
  • 100,655
  • 16
  • 128
  • 198
  • Actually, the smallest C file you can have is: main; dsm$ echo main\; > test.c dsm$ gcc -o test test.c test.c:1: warning: data definition has no type or storage class dsm$ ./test Segmentation fault dsm$ dsm$ – dsm Sep 19 '08 at 22:42
  • 1
    Many C compilers will compile a 0 byte file into an executable that outputs nothing and terminates. – Nick Johnson Sep 20 '08 at 19:16
1

For fun, I came up with one in Scheme, which I was pretty proud of for about 5 minutes until I discovered has been discovered before. Anyways, there's a slight modification to the "rules" of the game to better count for the duality of data and code in Lisp: instead of printing out the source of the program, it's an S-expression that returns itself:

((lambda (x) (list x `',x)) '(lambda (x) (list x `',x)))

The one on Wikipedia has the same concept, but with a slightly different (more verbose) mechanism for quoting. I like mine better though.

Kyle Cronin
  • 77,653
  • 43
  • 148
  • 164
  • 1
    I always figured these counted since, entered into the REPL, you actually **do** see the program come out again. – SamB Apr 16 '10 at 03:33
  • Doesn't count because in REPL you can write just a string, e.g. `"a"` in ruby and it will return itself. – akostadinov Jan 26 '17 at 10:46
0

One idea to think about encoding and how to give something a double meaning so that it can be used to output something in a couple of forms. There is also the cavaet that this type of problem comes with restrictions to make it harder as without any rules other than the program output itself, the empty program is a solution.

JB King
  • 11,860
  • 4
  • 38
  • 49
0

How about actually reading and printing your source code? Its not difficult at all!! Heres one in php:

<?php
{
header("Content-Type: text/plain");
    $f=fopen("5.php","r");
    while(!feof($f))
    {
        echo fgetc($f);
    } 
    fclose($f);
}
?>
0

In python, you can write:

s='c=chr(39);print"s="+c+s+c+";"+s';c=chr(39);print"s="+c+s+c+";"+s

inspired from this self printing pseudo-code:

Print the following line twice, the second time with quotes.
"Print the following line twice, the second time with quotes."
Rabih Kodeih
  • 9,361
  • 11
  • 47
  • 55
0

I've done a AS3 example for those interested in this

var program = "var program = @; function main(){trace(program.replace('@', 

String.fromCharCode(34) + program + String.fromCharCode(34)))} main()"; 
function main(){
   trace(program.replace('@', String.fromCharCode(34) + program + String.fromCharCode(34)))
}
main()
Taires
  • 66
  • 1
  • 6
-1

In bash it is really easy

touch test; chmod oug+x test; ./test

Empty file, Empty output

  • Please share more details. The OP asked for solutions in compiled languages, and I would not say that a bash script is compiled in any way – Nico Haase Oct 30 '20 at 22:14
-2

In ruby:

puts File.read(_ _ FILE _ _)

Roland
  • 1,166
  • 11
  • 18
  • 2
    Actually, almost all languages have compiler (options) that can introduce the source into the binary. But reading information your compiler/interpreter gives you for free isn't really the point of this question at all. – Aleksandar Dimitrov Sep 19 '08 at 22:40
  • A quine is not valid when it takes input or it read from a file – Tristan Jul 30 '16 at 09:06