Question

J'ai vu beaucoup de solutions basées sur C / C ++ à ce problème dans lesquelles nous devons écrire un programme qui, une fois exécuté, imprime son propre source.

des solutions -

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

La solution Quine Page dans de nombreuses langues

Il existe beaucoup plus de solutions sur le net, différentes les unes des autres. Je me demande comment nous abordons un tel problème, qu'est-ce qui se passe dans l'esprit de celui qui le résout? Donnez-moi un aperçu de ce problème ... Alors que des solutions dans des langages interprétés comme perl, php, ruby, etc. pourraient être faciles ... j'aimerais savoir comment on s'y prend pour le concevoir dans des langages compilés ...

Était-ce utile?

La solution

Hormis la triche¹, il n'y a pas de différence entre les langages compilés et interprétés.

L’approche générique de quines est assez simple. Tout d’abord, quel que soit le programme, il doit à un moment donné imprimer quelque chose:

print ...

Cependant, que devrait-il imprimer? Lui-même. Il faut donc imprimer le " print " commande:

print "print ..."

Que faut-il imprimer ensuite? Dans l’intervalle, le programme a pris de l’ampleur et doit donc imprimer la chaîne en commençant par «print», également:

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

Maintenant, le programme a connu une nouvelle croissance, il reste donc encore beaucoup à imprimer:

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

Et ainsi de suite. Avec chaque code ajouté, il y a plus de code à imprimer. Cette approche ne va nulle part, mais il révèle un motif intéressant: La chaîne " print \ " " est répété encore et encore. Ce serait bien de mettre la partie répétée dans une variable:

a = "print \""
print a

Cependant, le programme vient de changer, nous avons donc besoin d'ajuster un:

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

Quand nous essayons maintenant de remplir le "" ...", nous rencontrons les mêmes problèmes qu'auparavant. En fin de compte, nous voulons écrire quelque chose comme ceci:

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

Mais ce n'est pas possible, parce que même si nous avions une telle fonction quoted () pour citer, il y a toujours le problème que nous définissons a en termes de lui-même:

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

La seule chose que nous puissions faire est donc de placer un espace réservé dans a :

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

Et c'est tout le tour! Tout le reste est maintenant clair. Il suffit de remplacer le remplaçant avec le contenu cité de a :

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

Depuis que nous avons changé le code, nous devons ajuster la chaîne:

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

Et c'est tout! Toutes les quines dans toutes les langues fonctionnent de la sorte (sauf ceux qui trichent).

Eh bien, vous devez vous assurer de ne remplacer que la première occurrence du titulaire. Et si vous utilisez un deuxième titulaire, vous pouvez éviter de citer la chaîne.

Mais ce sont des problèmes mineurs et facile à résoudre. Si fait, la réalisation de quoted () et replace () sont les seuls détails dans lesquels les différentes quines diffèrent vraiment.

¹ en faisant en sorte que le programme lise son fichier source

Autres conseils

Il existe différentes stratégies pour écrire des quines. La solution évidente consiste simplement à écrire du code qui ouvre le code et l’imprime. Les plus intéressantes concernent toutefois des fonctionnalités linguistiques permettant une auto-intégration, comme la fonctionnalité printf de style% s dans de nombreuses langues. Vous devez trouver comment incorporer quelque chose afin que cela finisse par se résoudre à la demande à incorporer. Je soupçonne que, comme les palindromes, de nombreux essais et erreurs sont impliqués.

Vous pouvez également étudier le fonctionnement du jeu Core Wars. Ce serait un bon exemple, je pense.

L'approche habituelle (lorsque vous ne pouvez pas tricher *) consiste à écrire quelque chose qui code sa source dans une constante chaîne, puis à imprimer cette constante deux fois: une fois en tant que chaîne de chaîne et une fois en tant que code. Cela évite "à chaque fois que j'écris une ligne de code, je dois en écrire une autre pour l'imprimer!" problème.

La "triche" comprend: - Utiliser un langage interprété et simplement charger la source et l’imprimer - Fichiers de 0 octet de long, valables dans certaines langues, tels que C.

Pour le fun, j’en ai créé un dans Scheme, dont je suis assez fier pendant environ 5 minutes, jusqu’à ce que j’ai découvert que c’était auparavant. Quoi qu'il en soit, il y a une légère modification des "règles". du jeu pour mieux compter pour la dualité données et code dans Lisp: au lieu d’imprimer la source du programme, c’est une expression S qui se retourne elle-même:

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

Le un sur Wikipedia a le même concept, mais avec un mécanisme de citation légèrement différent (plus détaillé). J'aime mieux le mien cependant.

Une idée de penser à l’encodage et à la façon de donner à deux choses une double signification afin qu’elles puissent être utilisées pour produire quelque chose sous deux formes. Il y a aussi le problème qui vient avec ce type de problème avec des restrictions pour le rendre plus difficile car sans règles autres que la sortie du programme lui-même, le programme vide est une solution.

Vous pouvez trouver plusieurs solutions à ce problème ici: http: // forums.thedailywtf.com/forums/p/5232/147528.aspx

Que diriez-vous de lire et d’imprimer votre code source? Ce n'est pas difficile du tout! Heres one in php:

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

En python, vous pouvez écrire:

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

inspiré de ce pseudo-code auto-imprimable:

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

J'ai créé un exemple AS3 pour les personnes intéressées par cette

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

En rubis:

met File.read (_ _ FILE _ _)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top