Quine Entropic!

12

Sua tarefa é escrever um programa ou função que:

  • Quando executado pela primeira vez, gera seu código fonte.
  • Nas execuções subseqüentes, deve gerar o que produziu anteriormente, mas com uma alteração aleatória de caracteres (definida abaixo). Não precisa ser uma alteração uniformemente aleatória, mas todas as alterações possíveis devem ter uma chance diferente de zero.

    Após a primeira execução, seu programa não será mais necessariamente um quine; a saída será alterada (e o programa também poderá se modificar).

Por exemplo, se o seu quine foi ABCD, a execução repetida pode ser impressa:

ABCD
A!CD
j!CD
j!CjD

Especificações

  • Uma mudança de caractere é:

    • A inserção de um caractere aleatório,
    • A exclusão de um caractere aleatório ou
    • Uma substituição de um personagem por um novo personagem aleatório. Observe que o novo personagem pode ser o mesmo que ele substitui; nesse caso, nenhuma alteração será feita.

    Obviamente, excluir ou substituir um caractere de uma sequência vazia não é uma alteração válida.

  • Apesar de ter sido marcado como , as regras contra a leitura do seu código-fonte não se aplicam.

Você pode usar qualquer conjunto de caracteres, desde que inclua os caracteres usados ​​no seu código-fonte.

Esolanging Fruit
fonte
1
Quais caracteres cada personagem se refere?
Dennis
2
Quantas vezes isso tem que funcionar? Claramente, não pode ser arbitrariamente frequente ou, de outra forma, todo programa possível, mais longo ou mais longo do que o original, deve ser uma solução para o desafio.
Martin Ender
1
O personagem pode ser adicionado em qualquer lugar, ou apenas no final?
Conor O'Brien
1
@ ConorO'Brien em qualquer lugar.
Esolanging Fruit
1
Quantas iterações ele tem para funcionar?
Dylnan 17/0518

Respostas:

7

Python 3 , 288 270 224 212 195 196 194 180 178 168 bytes

f=__file__
m=open(f).read()
x=m	
print(end=x)
h=hash
k=h(f)
n=k%2
a=h(m)%-~len(x)
x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:]
open(f,'w').write(m.replace("\t",";x=%r\t"%x))

Experimente online!

Depois de imprimir o código-fonte do arquivo na primeira iteração, anexamos uma linha extra para definir x para o novo código-fonte, em vez de m.

Explicação:

f=__file__    #Open and read the source code
m=open(f).read()

x=m       #Set x to the source code for the first iteration
x="..."
...
x="..."   #Set x to the latest iteration
          #On the last iteration there's a tab character to mark progress
print(end=x)    #Print the previous iteration's text

#Modify the text
h=hash
k=h(f)            #Generate a random number to use
n=k%2             #Whether the character will be inserted or changed/deleted
a=h(m)%-~len(x) #The index of the change
                         #Add 1 to the range to append new characters, and to avoid mod by 0 in the case of an empty string
x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:]    #Make the change

open(f,'w').write(m.replace("\t",";x=%r\t"%x))   #Modify the source code, adding the new iteration of the source code

Supondo que hashretorna um número uniformemente aleatório, há cerca de 1/6 de chance de inserir um novo caractere, 1/6 de chance de alterar um caractere existente e 2/6 de chance de excluir um caractere. Qual é a chance restante de 2/6 que você pergunta? Ora, isso não faz nada em 2/6 do tempo!

(Aqui está um programa de validação adaptado das respostas de mbomb007 . Experimente online! )

Brincadeira
fonte
Eu acho f=__file__que ajudaria no primeiro passo também.
Ørjan Johansen
4

Python 3 , 205 195 bytes

s='print(end=x);h=hash;k=h(x);n=k%2;a=h(s)%-~len(x);x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:];open(__file__,"w").write("s=%r;x=%r;exec(s)"%(s,x))';x='s=%r;x=%r;x=x%%(s,x);exec(s)';x=x%(s,x);exec(s)

Experimente online!

Queria experimentar uma versão que não lê o código fonte. Acabou não é um mau como eu pensava, e é apenas 30 ou mais bytes por trás da versão que faz . A explicação de como funciona é basicamente a mesma que a outra resposta, mas inicializa x de maneira diferente, pois não pode apenas ler o código-fonte.

Brincadeira
fonte
4

Python 2 , 779 801 bytes

Embora o desafio tenha sido editado para mostrar que a leitura de sua fonte é permitida, eu já estava criando minha solução sem isso. Então, para mostrar que é possível, eu terminei. Nenhuma leitura do arquivo de origem:

s='s=%r;print s%%s\nfrom random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint\nf.write("\\n".join((s%%s).split("\\n")[1:5:2]).replace("4",`map(ord,s%%s)`))\nif L>5:exec\'b=[];h=%%d\\nwhile~-h:b+=[h%%%%1000];h/=1000\\nwhile b:r,p,n=b[-3:];b=b[:-3];L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]\\nprint"".join(map(chr,L))\'%%1\n\nn=R(0,2);p=R(0,len(L if L>5else s%%s));r=R(0,255);f.write("%%03d"*3%%(n,p,r))';print s%s
from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint
f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))
if L>5:exec'b=[];h=%d\nwhile~-h:b+=[h%%1000];h/=1000\nwhile b:r,p,n=b[-3:];b=b[:-3];L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]\nprint"".join(map(chr,L))'%1

n=R(0,2);p=R(0,len(L if L>5else s%s));r=R(0,255);f.write("%03d"*3%(n,p,r))

Experimente online! (Observe que isso não modificará a fonte. É necessário executá-lo localmente para que isso funcione)

Para mostrar que as transformações trabalhar, aqui está um programa de teste (atualmente configurado para sempre escolher 100para r, e imprime o resultado para cada combinação de ne ppara a lista inicial.)



Explicação:

s='s=%r;print s%%s...';print s%s...

A primeira linha é o seu estilo clássico, mas muito mais para explicar o que vem depois.

from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint

Importar para números inteiros aleatórios. Lpassará a fazer parte da lista de ordinais do código fonte, mas inicialmente é um número inteiro não usado em nenhum outro lugar na fonte para permitir a substituição de uma string. Abra o arquivo para escrever a nova fonte. Em execuções posteriores, ele será aberto para anexar.

f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))

Remova a primeira e a terceira linhas de código. Substitua o 4acima pela lista de ordinais.

if L>5:exec'b=[];h=%d\nwhile~-h:b+=[h%%1000];h/=1000\nwhile b:r,p,n=b[-3:];b=b[:-3];L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]\nprint"".join(map(chr,L))'%1

n=R(0,2);p=R(0,len(L if L>5else s%s));r=R(0,255);f.write("%03d"*3%(n,p,r))

Em pedaços:

  • if L>5:- Ignora esta linha na primeira execução. Mais tarde, Lhaverá uma lista, e isso será executado. Vou explicar o execúltimo, porque não é executado pela primeira vez.

  • n- Um número aleatório 0-2. Isso determina qual modificação ocorre (0 = inserir, 1 = substituir, 2 = excluir).

  • p - Uma posição aleatória na lista em que a modificação ocorrerá.

  • r - Um número aleatório para inserir ou substituir na lista

  • f.write("%03d"*3%(n,p,r))- Anexe os 3 randoms ao final do arquivo de origem. A cada execução, isso adicionará um número inteiro que codifica todas as alterações na fonte inicial que ocorreram.

  • exec'b=[];h=%d...'%1...- Obtenha os números aleatórios (encontrados depois %1em execuções posteriores), aplique as alterações na lista e imprima.

  • while~-h:b+=[h%%1000];h/=1000- Crie uma lista dos randoms gerados até o momento, respondendo pelo líder 1, o que evita problemas com zeros à esquerda.

  • while b:r,p,n=b[-3:];b=b[:-3] - Atribua os randoms para esta iteração.

  • L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1] - (0 = inserir, 1 = substituir, 2 = excluir)

  • print"".join(map(chr,L)) - Imprima a fonte modificada.

mbomb007
fonte
Às vezes, isso exclui um caractere inexistente do final da string? Uma vez que ppode ser o comprimento da string. Além disso, qual é o comportamento de uma string vazia?
Jo Rei
@JoKing Adicionei um programa de teste. Toda mudança de personagem possível pode acontecer. Apenas mostra que todas as posições podem ser selecionadas para uma inserção, substituição ou exclusão e que lida com uma lista vazia. tio.run/##LYoxDsMgDEVnOAUjCAZgRO0NuIHloUOaRIocy6JDT08dpdt/…
mbomb007
Não acho que nenhuma alteração seja válida, embora eu tenha solicitado ao OP. A questão dizOf course, deleting or replacing a character from an empty string is not a valid change
Jo King
Eu perguntei à Esolanging Fruit e eles dizem que nenhuma alteração é válida, mas não para uma string vazia.
Jo Rei
1
@JoKing Deve ser corrigido.
Mbomb007
1

Java 10, 370 bytes

String s;v->{if(s==null){s="String s;v->{if(s==null){s=%c%s%1$c;s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%%3<2?c:%1$c%1$c)+s.substring(r+(c%%3>0?1:0));}}";s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%3<2?c:"")+s.substring(r+(c%3>0?1:0));}}

Experimente online.

Explicação:

String s;               // Class-level String variable to store the modifying source code
v->{                    // Method without parameter nor return-type
  if(s==null){          //  If this is the first execution of this function:
    s="String s;v->{if(s==null){s=%c%s%1$c;s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%%3<2?c:%1$c%1$c)+s.substring(r+(c%%3>0?1:0));}}";
                        //   Set `s` to the unformatted source-code
    s=s.format(s,34,s);}//   And then to the formatted source-code
else{                   //  For any following executions of this function:
  int r=s.length();r*=Math.random();
                        //   Random index in range [0, length_of_modified_source_code)
  char c=127;c*=Math.random();
                        //   Random ASCII character in unicode range [0, 127)
  s=                    //   Replace the current String `s` with:
    s.substring(0,r)    //    The first [0, `r`) characters of the modified source code `s`
    +(c%3<2?            //    If the random option is 0 or 1:
           c:"")        //     Append the random character
        +s.substring(r  //    Append the rest of the modified source code `s`, but:
          +(c%3>0?      //     If the random option is 1 or 2:
             1:0));}}   //      Skip the first character of this second part

Explicação geral:

-part:

  • A String scontém o código fonte não formatado.
  • %sé usado para inserir essa String em si mesma com o s.format(...).
  • %c, %1$cE 34são usados para formatar as aspas.
  • ( %%é usado para formatar o módulo %).
  • s.format(s,34,s) coloca tudo junto.

Aqui está um programa básico de Java Quine.

Parte do desafio:

  • String s; é o código-fonte que modificaremos no nível da classe.
  • int r=s.length();r*=Math.random();é usado para selecionar um índice aleatório do código fonte no intervalo [0, length_of_modified_source_code).
  • char c=127;c*=Math.random();é usado para selecionar um caractere ASCII aleatório (incluindo não imprimíveis) no intervalo unicode [0, 126].
  • c%3é usado para selecionar uma opção aleatória de 0, 1 ou 2. A opção 0 adicionará o caractere aleatório antes do índice r; a opção 1 substituirá o caractere no índice rpelo caractere aleatório; e a opção 2 removerá o caractere no índice r.
Kevin Cruijssen
fonte