Quine (programa)

Summary

En programación, un quine (pronunciado "kwain") es un programa (un tipo de Metaprogramación) que produce su código fuente como su salida única. Para diversión, algunos hackers intentan desarrollar el quine más corto posible en cualquier lenguaje de programación. Simplemente abriendo el archivo fuente del programa e imprimiendo el contenido se considera hacer trampa.

El término quine fue acuñado por Douglas Hofstadter, en su obra Gödel, Escher, Bach: un Eterno y Grácil Bucle, en honor a Willard Van Orman Quine, que hizo un estudio extensivo de autoreferencia indirecta y sugirió un caso famoso de paradoja sin autoreferencia directa: "Da como resultado un enunciado falso si es precedido por su cita" da como resultado un enunciado falso si es precedido por su cita.

Ejemplos

editar

C

editar
#include<stdio.h>
char*i="\\#include<stdio.h>",n='\n',q='"',*p=
"%s%cchar*i=%c%c%s%c,n='%cn',q='%c',*p=%c%c%s%c,*m=%c%c%s%c%c;%s%c",*m=
"int main(){return!printf(p,i+1,n,q,*i,i,q,*i,q,n,q,p,q,n,q,m,q,n,m,n);}"
;int main(){return!printf(p,i+1,n,q,*i,i,q,*i,q,n,q,p,q,n,q,m,q,n,m,n);}

Otro (este debe ser una sola línea, y supone que el compilador ejecuta en una máquina que usa el código ASCII):

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

O aún más corto (aunque no es código C99 de ISO correcto):

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

C#

editar

Nota: Debe ser una sola línea. Los saltos de línea se agregaron para hacerlo más fácil de leer.

using System;
namespace quine
{
  class Program
  {
    [STAThread]
    static void Main(string[] args)
    {
      string s = "using System;{0}namespace quine{0}{2}{0}{1}class Program{0}
{1}{2}{0}{1}{1}[STAThread]{0}{1}{1}static void Main(string[] args){0}{1}{1}{2}{0}{1}{1}{1}
string s = {4}{6}{4};{0}{1}{1}{1}Console.Write(s, Environment.NewLine, {4}{5}t{4}, {4}{2}
{4}, {4}{3}{4}, {4}{5}{4}{4}, {4}{5}{5}{4}, s);{0}{1}{1}{3}{0}{1}{3}{0}{3}";
      Console.Write(s, Environment.NewLine, "\t", "{", "}", "\"", "\\", s);
    }
  }
}

Scheme

editar
    ((lambda (x)
            (list x (list (quote quote) x)))
        (quote
            (lambda (x)
                (list x (list (quote quote) x)))))

Common Lisp

editar
   (funcall (lambda (x) 
              (append x (list (list 'quote x)))))
            '(funcall (lambda (x) 
                         (append x (list (list 'quote x))))))

Ocaml

editar
(fun s -> Printf.printf "%s %S" s s) "(fun s -> Printf.printf \"%s %S\" s s)"

Python

editar
 a='a=%s;print a%%`a`';print a%`a`

Otro:

 b='\\';g='"';p='%';s="b='%s%s';g='%s';p='%s';s=%s%s%s;print s%s(b,b,g,p,g,s,g,p)";print s%(b,b,g,p,g,s,g,p)

Y otro que comparte los caracteres últimos con la anterior (solamente para mostrar que asignaciones múltiples no salva mecanografía):

 b,g,p,s='\\','"','%',"b,g,p,s='%s%s','%s','%s',%s%s%s;print s%s(b,b,g,p,g,s,g,p)";print s%(b,b,g,p,g,s,g,p)

JavaScript

editar
unescape(q="unescape(q=%22*%22).replace('*',q)").replace('*',q)

Perl

editar
$_=q{$_=q{Q};s/Q/$_/;print};s/Q/$_/;print

El más corto conocido:

open+0;print<0>

Y una combinación de Perl y script de shell:

perl -le '$n=q{perl -le a$n=q{$x};($_=$n)=~s/\141/\47/g;s/\$x/$n/;printa};($_=$n)=~s/\141/\47/g;s/\$x/$n/;print'

BASIC

editar
10 LIST

Pascal

editar
const a='const a=';b='begin write(a,#39,a,#39#59#98#61#39,b,#39#59#10,b) end.';
begin write(a,#39,a,#39#59#98#61#39,b,#39#59#10,b) end.

Comentario 1: En el caso de una implementación DOS de Pascal, la salida de la pantalla puede parecer bastante desorientadora. En ese caso, sería apropiado sustituir ambas instancias de "#10" con "#13#10" e insertar un CR antes del LF al fin de la primera línea.

Comentario 2: El programa se puede hace todavía más corto porque ambas instancias de ") end." se pueden sustituir con ")end." (aunque le hace difícil de leer). Se puede acortar más por borrar ambas instancias de "#10" y escribiendo el programa en una sola línea en vez de dos líneas. Después de los cambios, el programa parecerá como sigue:

const a='const a=';b='begin write(a,#39,a,#39#59#98#61#39,b,#39#59,b)end.';begin write(a,#39,a,#39#59#98#61#39,b,#39#59,b)end.

Otro (Borland Pascal and Free Pascal):

const a='const a=;begin write(copy(a,1,8),#39,a,#39,copy(a,9,99)) end.';begin write(copy(a,1,8),#39,a,#39,copy(a,9,99)) end.

Otro (Borland Pascal and Free Pascal):

const a:string='const a:string=;begin insert(#39+a+#39,a,16);write(a) end.';begin insert(#39+a+#39,a,16);write(a) end.

Brainfuck

editar

Nota: Debe ser una sola línea. Los cortes de línea se agregaron para hacerlo más fácil de leer.

 ->+>+++>>+>++>+>+++>>+>++>>>+>+>+>++>+>>>>+++>+>>++>+>+++>>++>++>>+>>+>++>++>
 +>>>>+++>+>>>>++>++>>>>+>>++>+>+++>>>++>>++++++>>+>>++>+>>>>+++>>+++++>>+>+++
 >>>++>>++>>+>>++>+>+++>>>++>>+++++++++++++>>+>>++>+>+++>+>+++>>>++>>++++>>+>>
 ++>+>>>>+++>>+++++>>>>++>>>>+>+>++>>+++>+>>>>+++>+>>>>+++>+>>>>+++>>++>++>+>+
 ++>+>++>++>>>>>>++>+>+++>>>>>+++>>>++>+>+++>+>+>++>>>>>>++>>>+>>>++>+>>>>+++>
 +>>>+>>++>+>++++++++++++++++++>>>>+>+>>>+>>++>+>+++>>>++>>++++++++>>+>>++>+>>
 >>+++>>++++++>>>+>++>>+++>+>+>++>+>+++>>>>>+++>>>+>+>>++>+>+++>>>++>>++++++++
 >>+>>++>+>>>>+++>>++++>>+>+++>>>>>>++>+>+++>>+>++>>>>+>+>++>+>>>>+++>>+++>>>+
 [[->>+<<]]<+]+++++[->+++++++++<]>.[+]>>[<<+++++++[->+++++++++<]>-
 .------------------->-[-<.<+>>]<[+]<+>>>]<<<[-[-[-[>>+<++++++[->+++++<]]>++++
 ++++++++++<]>+++<]++++++[->+++++++<]>+<<<-[->>>++<<<]>[->>.<<]<<]

HQ9+

editar
Q

DOS Batch

editar
 @echo off
 %1 %2
 call %0 goto e %%
 call %0 goto e %%3 echo.%%4
 echo :f
 goto f
 :e
 echo.%4@echo off
 echo.%4%31 %32
 echo.%4call %30 goto e %3%3
 echo.%4call %30 goto e %3%33 echo.%3%34
 echo.%4echo :f
 echo.%4goto f
 echo.%4:e
 :f

PHP

editar
<?
$a='chr(60).chr(63).chr(10).chr(36).chr(97).chr(61).chr(39).$a.chr(39).chr(59).chr(10)."echo $a;".chr(10).chr(63).chr(62)';
echo chr(60).chr(63).chr(10).chr(36).chr(97).chr(61).chr(39).$a.chr(39).chr(59).chr(10)."echo $a;".chr(10).chr(63).chr(62);
?>
  
<?
$a='<?
$a=2;
echo str_replace(1+1,chr(39).$a.chr(39),$a);
?>';
echo str_replace(1+1,chr(39).$a.chr(39),$a);
?>

PL/I

editar

Nota: Este es el quine de PL/I más pequeño posible que compila usando el compilador OS PL/I V2.3.0, pero requiere un margen izquierdo de 1 y la opción COMPILE para parar una cantidad significativo de errores):

  %dcl z%z='put edit';proc options(main;q=''''put list(m;do i=1,2;z(q)skip;do j=
  1to 78c=substr(m(i),j;if c=q z(c;z(c;end;z(q',';dcl(c,q)char,m(2)char(99)init(
  '%dcl z%z=''put edit'';proc options(main;q=''''''''put list(m;do i=1,2;z(q)skip;do j=',
  '1to 78c=substr(m(i),j;if c=q z(c;z(c;end;z(q'','';dcl(c,q)char,m(2)char(99)init(',

PostScript

editar
 (dup == {dup cvx exec} pop 8 12 getinterval =)
 dup cvx exec
 CLEAR
 SET TALK OFF
 SET TEXTMERGE ON
 \CLEAR
 \SET TALK OFF
 \SET TEXTMERGE ON

Enlaces externos

editar
  • La página de los quines (por Gary P. Thompson)
  • Los programas quine al wiki del Portland Pattern Repository
  • Una página sobre los quines Archivado el 13 de enero de 2005 en Wayback Machine.
  • Unos participantes en un concurso de hacer quines en JavaScript Archivado el 24 de octubre de 2007 en Wayback Machine.
  • Un quine HTML con uso de CSS apegado a la norma, incluyendo resaltado de la sintaxis
  • "Palíndromo quine": una página web que es lo mismo que su código fuente, lo mismo de izquierda a derecha que de derecha a izquierda, los mismo de arriba para abajo que de abajo para arriba.
  •   Datos: Q1047886
  •   Multimedia: Quine (computer program) / Q1047886