Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Thinking about various quine puzzles here, I got an idea for another one:

Compose a program that outputs its own compiled code to a file (or multiple files, if the compiled code is). (This means that only compiled languages are eligible.)

Rules

Standard quine rules - no cheating allowed. In particular:

  1. The program cannot read the compiled code from disk, cannot store it somewhere etc. It must compute it somehow without external help.
  2. If the program is compiled to several files (i.e. several Java .class files), it must output them all.
  3. You can use any existing libraries available for your language. However:
    • The libraries you use cannot be something created just for this task. (For example in order to keep some information away from what's considered to be the program.)
    • Any libraries you use must be older than your program. You cannot just create a program that loads a piece of data from an external library, compile the program, and copy the compiled code into the library - that'd be cheating.
    • You cannot embed a compiler of your language in any form. In particular, you cannot just take a standard quine and hook it up with a compiler to produce the compiled output.
  4. As mentioned, only compiled languages are eligible. You can use a scripting language as long as it can be compiled to a bytecode that's reasonably different from the source form (if you're not sure, better ask).

Notes

Most likely, this puzzle can be solved reasonably only in languages that compile to some sort of bytecode that can be manipulated. For example, Java and compiled bytecode seems good for the task. (But if you find a genuine solution in some other compiled language, that's fine too, as long as it isn't some sort of cheating.)

Submission

Don't submit the compiled program (as this could be potentially dangerous). Instead post your sources and a description what to do to create the final program.

Evaluation

Let voters decide the best solution. Personally I'd appreciate solution that are elegant, short (in their source form) and didactic - that explain what's going on.

Bonuses

Bonus points for

  • Let the program output a compressed file containing its compiled code. This has the additional benefit that if the program is compiled into more files, the output will be a single packed file. For example, in Java try to create an executable JAR file that outputs the JAR itself.
  • Outputting the MD5 sum of the compiled file(s) - so the program would write its compiled code and its MD5 sum.
share|improve this question
3  
Is assembly language considered eligible for this challenge? –  Ilmari Karonen Nov 10 '12 at 12:50
    
@IlmariKaronen Good question. I'd say yes, because compiled output is very different from what you type in source code. –  Petr Pudlák Nov 10 '12 at 13:52
    
Can you read the compiled code from memory? Something like main(){write(1, main, SIZE);}? –  ugoren Nov 10 '12 at 19:13
    
@ugoren No, that'd be similar to reading the code from a file. –  Petr Pudlák Nov 10 '12 at 20:02

2 Answers 2

up vote 2 down vote accepted

Assembly (DOS .com file)

start:

%rep 2
    call $+3

    mov ah, 9
    mov dx, 100h + (end - start) / 2
    int 21h

    mov ah, 2
    mov dl, "$" - 1
    inc dx
    int 21h

    ret
    db "$"

%endrep

end:

Assemble with nasm quine.asm -o quine.com. Try with dosbox quine.com.

Proof of correctness (you can also verify by the smilies here):

dosbox quine screenshot

share|improve this answer
2  
If I understand correctly, it reads compiled code from memory. –  ugoren Nov 11 '12 at 5:12
    
I have to agree with @ugoren. The point of a quine is to construct its own code, not to read it from somewhere (whether it is a file or memory). For example, it could happen that the OS forbids reading the program's code (not under DOS probably, but in general). –  Petr Pudlák Nov 11 '12 at 7:03
    
@PetrPudlák The program actually consists of a code and a data section, which cannot really be separated in a .com executable. In my understanding this is a valid quine, because no byte is both interpreted as an instruction and written to output. –  copy Nov 11 '12 at 12:34
    
OK I think I understand now how it works. But I cannot compile it, nasm tells me: quine.asm:16: error: division operator may only be applied to scalar value. Any ideas? –  Petr Pudlák Nov 11 '12 at 14:51
    
@PetrPudlák fixed. –  copy Nov 11 '12 at 15:32

Python 2.7.3

#!/usr/bin/env python
import sys
import time
import struct
import compiledquine

_ = '\x63\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x40\x00\x00\x00\x73\x6e\x00\x00\x00\x64\x00\x00\x64\x01\x00\x6c\x00\x00\x5a\x00\x00\x64\x00\x00\x64\x01\x00\x6c\x01\x00\x5a\x01\x00\x64\x00\x00\x64\x01\x00\x6c\x02\x00\x5a\x02\x00\x64\x00\x00\x64\x01\x00\x6c\x03\x00\x5a\x03\x00\x64\x02\x00\x5a\x04\x00\x65\x00\x00\x6a\x05\x00\x6a\x06\x00\x64\x03\x00\x65\x02\x00\x6a\x07\x00\x64\x04\x00\x65\x08\x00\x65\x01\x00\x6a\x01\x00\x83\x00\x00\x83\x01\x00\x83\x02\x00\x17\x65\x04\x00\x65\x04\x00\x16\x17\x83\x01\x00\x01\x64\x01\x00\x53\x28\x05\x00\x00\x00\x69\xff\xff\xff\xff\x4e\x73\x08\x00\x00\x00%s\x73\x04\x00\x00\x00\x03\xf3\x0d\x0a\x74\x01\x00\x00\x00\x49\x28\x09\x00\x00\x00\x74\x03\x00\x00\x00\x73\x79\x73\x74\x04\x00\x00\x00\x74\x69\x6d\x65\x74\x06\x00\x00\x00\x73\x74\x72\x75\x63\x74\x74\x0d\x00\x00\x00\x63\x6f\x6d\x70\x69\x6c\x65\x64\x71\x75\x69\x6e\x65\x74\x01\x00\x00\x00\x5f\x74\x06\x00\x00\x00\x73\x74\x64\x6f\x75\x74\x74\x05\x00\x00\x00\x77\x72\x69\x74\x65\x74\x04\x00\x00\x00\x70\x61\x63\x6b\x74\x03\x00\x00\x00\x69\x6e\x74\x28\x00\x00\x00\x00\x28\x00\x00\x00\x00\x28\x00\x00\x00\x00\x73\x1c\x00\x00\x00\x2f\x68\x6f\x6d\x65\x2f\x67\x72\x61\x6e\x74\x2f\x63\x6f\x6d\x70\x69\x6c\x65\x64\x71\x75\x69\x6e\x65\x2e\x70\x79\x74\x08\x00\x00\x00\x3c\x6d\x6f\x64\x75\x6c\x65\x3e\x02\x00\x00\x00\x73\x0a\x00\x00\x00\x0c\x01\x0c\x01\x0c\x01\x0c\x02\x06\x01'
sys.stdout.write('\x03\xf3\x0d\x0a' + struct.pack('I', int(time.time())) + _ % _)

Note that this must be saved as compiledquine.py. These are the results I get:

$ ./compiledquine.py > compiledquine.py.out
$ md5sum compiledquine.pyc compiledquine.py.out
4b82e7d94d0d59e3d647d775fffc1948  compiledquine.pyc
4b82e7d94d0d59e3d647d775fffc1948  compiledquine.py.out

I won't guarantee that it'll work for you, but it does consistently work for me. Here's what happens:

  • At the bottom of the import statements, the script itself is imported. This compiles it to a .pyc file.
  • The variable _ is filled with the program's bytecode starting at byte 0x08, except %s is put in place of the variable itself.
  • The script fills in the first 4 'magic' bytes, which are specific to Python 2.7.3, followed by the timestamp in the next 4 bytes, which is generated by struct.pack and time.time, and then adds _ % _ to complete the output. (That last bit is borrowed from some other Python quines.)
  • Because of the timestamp at the beginning, this script technically isn't always accurate. If the self-import and the last line execute in different seconds, the output will be a byte off.
share|improve this answer
    
It seems to me there is a typo - shouldn't it be md5sum compiledquine.pyc compiledquine.py.out? However I tried and .pyc (679 bytes) is very different from .out (1372 bytes). –  Petr Pudlák Nov 12 '12 at 5:22
    
That was indeed a typo, my bad. And I'm not sure what to tell you regarding the outputs of .pyc and .out. For what it's worth, I'm using CPython 2.7.3 on 32-bit Linux. –  Fraxtil Nov 12 '12 at 19:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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