programming-languages quine

programming languages - ¿Cómo escribir un código de autoreproducción(imprime la fuente en el ejecutivo)?



programming-languages quine (13)

He visto muchas soluciones basadas en C / C ++ para este problema donde tenemos que escribir un programa que luego de la ejecución imprime su propia fuente.

algunas soluciones -

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

Solución de Quine Page en muchos idiomas

Hay muchas más soluciones en la red, cada una diferente de la otra. Me pregunto cómo nos acercamos a ese problema, qué pasa dentro de la mente de quien lo resuelve. Préstame algunas ideas sobre este problema ... Si bien las soluciones en lenguajes interpretados como perl, php, ruby, etc. pueden ser fáciles ... me gustaría saber cómo se diseña en lenguajes compilados ...


El enfoque habitual (cuando no se puede hacer trampa *) es escribir algo que codifica su origen en una constante de cadena, y luego imprime esa constante dos veces: una vez como una cadena literal, y una vez como código. Eso pasa por alto que "cada vez que escribo una línea de código, tengo que escribir otra para imprimirla". problema.

''Hacer trampa'' incluye: - Usar un lenguaje interpretado y simplemente cargar la fuente e imprimirlo - Archivos largos de 0 bytes, que son válidos en algunos idiomas, como C.


En ruby:

pone File.read (_ _ FILE _ _)


Hay un par de estrategias diferentes para escribir quines. El más obvio es escribir código que abre el código y lo imprime. Pero los más interesantes implican características de lenguaje que permiten la autoincrección, como la característica printf% s en muchos idiomas. Debes averiguar cómo insertar algo para que termine resolviendo la solicitud de incrustación. Sospecho que, al igual que los palíndromos, se trata de una gran cantidad de prueba y error.



También podrías estudiar cómo funciona Core Wars. Sería un buen ejemplo, creo.



Una idea para pensar sobre la codificación y cómo darle a algo un doble significado para que pueda ser usado para dar salida a algo en un par de formas. También está el hecho de que este tipo de problema viene con restricciones para hacerlo más difícil ya que sin otras reglas que no sean la salida del programa en sí, el programa vacío es una solución.



Para divertirme, se me ocurrió uno en Scheme, del cual me sentí muy orgulloso durante unos 5 minutos hasta que descubrí que se había descubierto antes. De todos modos, hay una ligera modificación en las "reglas" del juego para contar mejor la dualidad de datos y códigos en Lisp: en lugar de imprimir la fuente del programa, es una expresión S que se devuelve a sí misma:

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

El de Wikipedia tiene el mismo concepto, pero con un mecanismo ligeramente diferente (más detallado) para las citas. Pero me gusta el mío mejor.


¿Qué hay de realmente leer e imprimir su código fuente? ¡No es difícil en absoluto! Aquí está uno en php:

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


En python, puedes escribir:

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

inspirado en este pseudo-código de impresión automática:

Print the following line twice, the second time with quotes. "Print the following line twice, the second time with quotes."


He hecho un ejemplo de AS3 para aquellos interesados ​​en esto

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()


Además de hacer trampa¹, no hay diferencia entre los lenguajes compilados e interpretados.

El enfoque genérico para quines es bastante fácil. Primero, cualquiera que sea el programa, en algún momento tiene que imprimir algo:

print ...

Sin embargo, ¿qué debería imprimir? Sí mismo. Por lo tanto, necesita imprimir el comando "imprimir":

print "print ..."

¿Qué debería imprimir después? Bueno, mientras tanto, el programa creció, por lo que también necesita imprimir la cadena comenzando con "imprimir":

print "print /"print .../""

Ahora el programa creció de nuevo, por lo que una vez más hay que imprimir:

print "print /"print ///"...///"/""

Y así. Con cada código agregado, hay más código para imprimir. Este enfoque no conduce a ninguna parte, pero revela un patrón interesante: la cadena "print /" "se repite una y otra vez. Sería bueno poner la parte que se repite en una variable:

a = "print /"" print a

Sin embargo, el programa acaba de cambiar, por lo que debemos ajustar un:

a = "a = .../nprint a" print a

Cuando intentamos completar el "...", nos encontramos con los mismos problemas que antes. En definitiva, queremos escribir algo como esto:

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

Pero eso no es posible, porque incluso si tuviéramos tal función quoted() para cotizar, todavía existe el problema que definimos a en términos de sí mismo:

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

Entonces, lo único que podemos hacer es colocar un marcador de posición en a :

a = "a = @/nprint a" print a

¡Y ese es todo el truco! Cualquier otra cosa ahora está clara. Simplemente reemplace el marcador de lugar con el contenido citado de:

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

Como hemos cambiado el código, debemos ajustar la cadena:

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

¡Y eso es! Todas las quines en todos los idiomas funcionan de esa manera (excepto las trampas).

Bueno, debe asegurarse de reemplazar solo la primera ocurrencia del marcador de posición. Y si usa un segundo titular, puede evitar tener que citar la cadena.

Pero esos son problemas menores y fáciles de resolver. De hecho, la realización de quoted() y replace() son los únicos detalles en los que las diversas quines realmente difieren.

¹ haciendo que el programa lea su archivo fuente