Como escrever um código de reprodução auto (imprime a fonte em exec)?
-
01-07-2019 - |
Pergunta
Eu vi um monte de soluções baseadas em C / C ++ para este problema em que temos de escrever um programa que após a execução imprime sua própria fonte.
algumas soluções -
http://www.cprogramming.com/challenges/solutions/self_print.html
solução Quine página em muitas línguas
Há muitas mais soluções na rede, cada uma diferente da outra. Pergunto-me como é que vamos abordar a esse problema um, o que se passa dentro da mente de quem resolve. Empreste-me alguns insights sobre este problema ... Enquanto soluções em linguagens interpretadas como Perl, PHP, Ruby, etc pode ser fácil ... eu gostaria de saber como se faz para projetá-la em linguagens compiladas ...
Solução
Além de cheating¹ não há diferença entre linguagens compiladas e interpretadas.
A abordagem genérica para quines é bastante fácil. Em primeiro lugar, qualquer que seja o programa se parece, em algum momento ele tem que imprimir algo:
print ...
No entanto, o que deveria imprimir? Em si. Por isso, precisa imprimir o "imprimir" comando:
print "print ..."
O que deveria imprimir o próximo? Bem, nesse meio tempo, o programa cresceu, por isso precisa imprimir a string começando com "print", também:
print "print \"print ...\""
Agora, o programa cresceu outra vez, então não há outra vez mais para imprimir:
print "print \"print \\\"...\\\"\""
E assim por diante. Com cada código adicionado há mais código para imprimir. Esta abordagem está chegando a lugar nenhum, mas revela um padrão interessante: A "impressão \" string" é repetida uma e outra vez. Seria bom para colocar a parte repetindo em uma variável:
a = "print \"" print a
No entanto, o programa só mudou, por isso precisamos ajustar a:
a = "a = ...\nprint a" print a
Quando nós agora tentar preencher o "...", nos deparamos com os mesmos problemas que antes. Em última análise, queremos escrever algo como isto:
a = "a = " + (quoted contents of a) + "\nprint a" print a
Mas isso não é possível,
porque mesmo se tivéssemos tal função um quoted()
para citar,
ainda há o problema que nós definimos a
em termos de si mesma:
a = "a = " + quoted(a) + "\nprint a" print a
Assim, a única coisa que podemos fazer é colocar um espaço reservado para a
:
a = "a = @\nprint a" print a
E esse é o truque!
Qualquer outra coisa é agora claro.
Basta substituir o titular do lugar
com o conteúdo cotados de a
:
a = "a = @\nprint a" print a.replace("@", quoted(a))
Uma vez que mudaram o código, precisamos ajustar a cadeia:
a = "a = @\nprint a.replace(\"@\", quoted(a))" print a.replace("@", quoted(a))
E é isso! Todos os quines em todas as línguas assim que funciona (Exceto os batota).
Bem, você deve garantir que você só substituir a primeira ocorrência do titular do lugar. E se você usar um segundo titular lugar, você pode evitar a necessidade de citar a string.
Mas essas são questões menores
e fácil de resolver.
Se o fato, a realização de quoted()
e replace()
são os únicos detalhes em que os vários quines realmente diferem.
¹, fazendo o programa ler seu arquivo fonte
Outras dicas
Há um par de diferentes estratégias para escrever quines. A mais óbvia é a de código apenas gravação que abre o código e imprime-lo. Mas os mais interessantes envolvem recursos de linguagem que permitem a auto-incorporação, como o recurso printf% de estilo s em muitas línguas. Você tem que descobrir como incorporar alguma coisa para que ele acaba resolvendo a solicitação para ser incorporado. Eu suspeito que, como palíndromos, um monte de tentativa e erro está envolvido.
Além disso, você pode estudar como Core Wars jogo funciona. Seria um bom exemplo, eu acho.
A abordagem usual (quando você não pode enganar *) é escrever algo que codifica a sua fonte em uma constante corda, em seguida, imprime essa constante duas vezes: uma vez como um literal de cadeia, e uma vez como código. Que fica em torno do "cada vez que eu escrever uma linha de código, eu tenho que escrever uma outra para imprimi-lo para fora!" problema.
'Engano' inclui: - Usando uma linguagem interpretada e simplesmente carregar a fonte e imprimi-lo -. Arquivos longos 0 bytes, que são válidos em algumas linguagens, como C
Para se divertir, eu vim com um no esquema, que eu era muito orgulhoso por aproximadamente 5 minutos até que eu descobri foi descoberto antes. De qualquer forma, há uma ligeira modificação para as "regras" do jogo para melhor contagem para a dualidade de dados e código em Lisp: em vez de imprimir a fonte do programa, que é uma S-expressão que retorna-se:
((lambda (x) (list x `',x)) '(lambda (x) (list x `',x)))
O um em Wikipedia tem o mesmo conceito, mas com um (mais detalhado) mecanismo ligeiramente diferente para citar. Eu como o meu melhor ainda.
Uma idéia para pensar sobre a codificação e como dar algo um duplo significado para que ele possa ser usado para imprimir algo em um par de formas. Há também a cavaet que este tipo de problema vem com restrições para tornar mais difícil, pois sem quaisquer outros do que a própria saída do programa regras, o programa vazio é uma solução.
Você pode encontrar algumas soluções para este aqui: http: // forums.thedailywtf.com/forums/p/5232/147528.aspx
Como cerca de realmente ler e imprimir o seu código-fonte? A sua não é difícil em tudo !! Heres um em php:
<?php
{
header("Content-Type: text/plain");
$f=fopen("5.php","r");
while(!feof($f))
{
echo fgetc($f);
}
fclose($f);
}
?>
Em Python, você pode escrever:
s='c=chr(39);print"s="+c+s+c+";"+s';c=chr(39);print"s="+c+s+c+";"+s
inspirado a partir desta pseudo-código de auto impressão:
Print the following line twice, the second time with quotes.
"Print the following line twice, the second time with quotes."
Eu fiz um exemplo AS3 para os interessados ??nesta ??p>
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()
Em Ruby:
puts File.read (_ _ _ _ ARQUIVO)