Quine endurecido por radiação


39

Como você deve (espero) saber, um quine endurecido por radiação é um quine do qual você pode remover qualquer caractere e ainda imprimir sua fonte original pré-modificada. O problema é que, com a maioria deles, você pode remover apenas um caractere; caso contrário, tudo quebra. É aqui que entra; seu objetivo é criar uma solução resistente à radiação que possa levar o maior número possível de remoções de caracteres. Qualquer idioma que esteja em conformidade com as regras é bom.

Regras

  • O programa deve ter pelo menos um caractere
  • O idioma usado deve estar completo (para idiomas como HQ9 + não se qualificarem)
  • Todas as outras regras que se aplicam a quines normais também se aplicam aqui.
  • A solução com o mínimo program_length^(2/n)em que qualquer conjunto de ncaracteres exatamente pode ser removido enquanto ainda imprime o código-fonte original vence.

1
Estou tentando encontrar uma solução Subleq. Eu acho que seria ideal para esse tipo de desafio!


Talvez mude o nome, já que isso não é o mesmo que uma solução endurecida por radiação? Talvez " quine à prova de radiação "?
Cyoce

@Cyoce A única diferença que posso dizer é que esse desafio é para qualquer número de remoções, enquanto a maioria (senão todas) de outras peças resistentes à radiação permite apenas uma.
takra

Solução Ruby da famosa "mame". github.com/mame/radiation-hardened-quine
mbomb007

Respostas:


57

Perl, 1116 1124 bytes, n = 3, pontuação = 1124 ^ (2/3) ou aproximadamente 108,1

Atualização : verifiquei agora que isso funciona com n = 3 via força bruta (que levou alguns dias); com um programa desse complexo, é difícil verificar a resistência à radiação manualmente (e cometi um erro em uma versão anterior, e é por isso que a contagem de bytes aumentou). Finalizar atualização

Eu recomendo redirecionar o stderr para algum lugar que você não verá; esse programa produz vários avisos sobre sintaxe dúbia, mesmo quando você não está excluindo caracteres.

É possível que o programa possa ser reduzido. Trabalhar nisso é bastante doloroso, facilitando a perda de possíveis micro-otimizações. Meu objetivo era obter o maior número possível de caracteres deletáveis ​​(porque essa é a parte realmente desafiadora do programa), e tratava o tie break de como algo que era bom de se procurar, mas como algo que eu não colocaria esforço ridículo para otimizar (com base em que é muito fácil quebrar a resistência à radiação por acidente).

O programa

Nota: existe um _caractere de controle literal (ASCII 31) imediatamente antes de cada uma das quatro ocorrências de -+. Eu não acho que ele copiou e colou corretamente no StackOverflow, portanto, você precisará adicioná-lo novamente antes de executar o programa.

eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;

A explicação

Esse programa, claramente, é composto de quatro programas menores idênticos concatenados juntos. A idéia básica é que cada cópia do programa verifique se foi danificado demais para ser executado ou não; se foi, não fará nada (além de possivelmente emitir avisos) e permitirá que a próxima cópia seja executada; se não tiver sido (ou seja, nenhuma exclusão ou o caractere que foi excluído não faz diferença na operação do programa), ele fará o que é minucioso (imprimir o código-fonte completo do programa; esse é um quine apropriado, com cada parte contendo uma codificação de todo o código-fonte) e, em seguida, saia (impedindo que outras cópias não danificadas imprimam o código-fonte novamente e, assim, arruinem a solução imprimindo muito texto).

Cada parte, por sua vez, é composta de duas partes que são efetivamente independentes funcionalmente; um invólucro externo e algum código interno. Como tal, podemos considerá-los separadamente.

Invólucro externo

O wrapper externo é, basicamente, eval<+eval<+eval< ... >####>####...>###(mais um ponto e vírgula e novas linhas cujo objetivo deve ser bastante óbvio; é para garantir que as partes do programa permaneçam separadas, independentemente de alguns pontos e vírgulas ou as novas linhas antes deles serem excluídas ) Isso pode parecer bastante simples, mas é sutil de várias maneiras, e a razão pela qual escolhi Perl para esse desafio.

Primeiro, vamos ver como o wrapper funciona em uma cópia não danificada do programa. evalanalisa como uma função interna, que requer um argumento. Como se espera um argumento, +aqui está um unário +(que já será muito familiar para os golfistas de Perl; eles são úteis surpreendentemente com frequência). Ainda estamos esperando um argumento (acabamos de ver um operador unário); portanto, o <que vem a seguir é interpretado como o início do <>operador (que não aceita argumentos de prefixo ou postfix e, portanto, pode ser usado na posição de operando).

<>é um operador bastante estranho. Seu objetivo usual é ler identificadores de arquivo e você coloca o nome do identificador dentro dos colchetes angulares. Como alternativa, se a expressão não é válida como um nome de arquivo, ela ocorre (basicamente, o mesmo processo que os shells do UNIX usam para converter o texto inserido pelo usuário em uma sequência de argumentos da linha de comando; versões muito mais antigas do Perl realmente usavam a casca para isso, mas hoje em dia o Perl lida internamente com o globbing). O uso pretendido, portanto, é <*.c>semelhante ao de , que normalmente retornaria uma lista como ("foo.c", "bar.c"). Em um contexto escalar (como o argumento paraeval), apenas retorna a primeira entrada encontrada na primeira vez que é executada (o equivalente ao primeiro argumento) e retorna outras entradas em execuções hipotéticas futuras que nunca acontecem.

Agora, os shells geralmente lidam com argumentos de linha de comando; se você der algo como -rsem argumentos, ele será transmitido literalmente ao programa, independentemente de haver ou não um arquivo com esse nome. O Perl age da mesma maneira, desde que asseguremos que não haja caracteres especiais para o shell ou para Perl entre o <e o correspondente >, podemos usá-lo efetivamente como uma forma realmente estranha de literal de cadeia de caracteres. Melhor ainda, o analisador de Perl para operadores do tipo cotação tem uma tendência compulsiva a combinar colchetes, mesmo em contextos como este, onde não faz sentido, para que possamos aninhar <>com segurança (que é a descoberta necessária para que este programa seja possível). A principal desvantagem de todos esses aninhados <>é que escapar do conteúdo do<>é quase impossível; parece haver duas camadas de <>fuga sem escape para cada uma delas ; portanto, para escapar de algo dentro das três, ele precisa ser precedido com 63 barras invertidas. Decidi que, embora o tamanho do código seja apenas uma consideração secundária nesse problema, quase certamente não valia a pena pagar esse tipo de penalidade na minha pontuação, por isso decidi escrever o restante do programa sem usar os caracteres incorretos.

Então, o que acontece se partes do wrapper são excluídas?

  • Exclusões na palavra evalfazem com que ela se transforme em uma palavra de barra , uma string sem significado. Perl não gosta disso, mas trata-os como se estivessem cercados de aspas; assim eal<+eval<+...é interpretado como"eal" < +eval<+.... Isso não tem efeito na operação do programa, porque é basicamente pegar o resultado dos resultados fortemente aninhados (que não usamos de qualquer maneira), convertê-lo em um número inteiro e fazer algumas comparações inúteis. (Esse tipo de coisa causa muitos avisos de spam, pois claramente não é algo útil em circunstâncias normais; estamos apenas usando-o para absorver exclusões.) Isso altera o número de colchetes de ângulo de que precisamos (porque o colchete de abertura agora está sendo interpretado como um operador de comparação), mas a cadeia de comentários no final garante que a sequência termine com segurança, não importa quantas vezes seja aninhada. (Há mais #sinais do que o estritamente necessário aqui; escrevi como fiz para tornar o programa mais compressível, permitindo que eu use menos dados para armazenar o quine.)
  • Se um <for excluído, o código agora será analisado como eval(eval<...>). O secundário, outside evalnão tem efeito, porque os programas que estamos avaliando não retornam nada que tenha efeitos reais como um programa (se eles retornam normalmente, normalmente é uma string nula ou uma palavra de barra; mais comumente eles retornam via exceção, que faz evalcom que retorne uma cadeia nula ou use exitpara evitar retornar).
  • Se um +for excluído, isso não terá efeito imediato se o código adjacente estiver intacto; unário +não tem efeito no programa. (A razão pela qual os originais +existem existe para ajudar a reparar danos; eles aumentam o número de situações nas quais <é interpretado como um operador unário <>e não como relacional, o que significa que você precisa de mais exclusões para produzir um programa inválido.)

O wrapper pode ser danificado com exclusões suficientes, mas é necessário fazer uma série de exclusões para produzir algo que não é analisado. Com quatro exclusões, você pode fazer o seguinte:

eal<evl<eval+<...

e no Perl, o operador relacional <não é associativo e, portanto, você recebe um erro de sintaxe (o mesmo que ocorreria 1<2<3). Como tal, o limite para o programa como está escrito é n = 3. Adicionar mais unários +parece ser uma maneira promissora de aumentá-lo, mas isso tornaria cada vez mais provável que o interior do wrapper também pudesse quebrar, verificando se a nova versão do programa funciona poderia ser muito difícil.

O motivo pelo qual o wrapper é tão valioso é que evalno Perl captura exceções, como (por exemplo) a exceção que você recebe ao tentar compilar um erro de sintaxe. Como se evaltrata de uma string literal, a compilação da string acontece no tempo de execução e, se o literal falhar na compilação, a exceção resultante é capturada. Isso faz evalcom que retorne uma cadeia nula e defina o indicador de erro $@, mas nunca a verificamos (exceto executando ocasionalmente a cadeia nula retornada em algumas versões modificadas do programa). Fundamentalmente, isso significa que, se algo acontecer com o código dentroo invólucro, causando um erro de sintaxe, o invólucro fará apenas com que o código não faça nada (e o programa continuará sendo executado na tentativa de encontrar uma cópia não danificada de si mesmo). Portanto, o código interno não precisa ser tão à prova de radiação quanto o invólucro; tudo o que nos preocupa é que, se danificado, ele agirá de forma idêntica à versão não danificada do programa ou falhará (permitindo evalcapturar a exceção e continuar) ou sairá normalmente sem imprimir nada.

Dentro do invólucro

O código dentro do wrapper, basicamente, tem a seguinte aparência (novamente, há um controle _que o Stack Exchange não mostrará imediatamente antes do -+):

eval+(q(...)=~y=A-Z=-+;-AZz-~=r)

Este código é escrito inteiramente com caracteres seguros para globos, e seu objetivo é adicionar um novo alfabeto de sinais de pontuação que possibilite escrever um programa real, através da transliteração e avaliação de uma string literal (não podemos usar 'ou "como nossa citação marcas, mas q()também é uma maneira válida de formar uma string em Perl). (A razão para o caractere não imprimível é que precisamos transliterar algo no caractere de espaço sem um caractere de espaço literal no programa; assim, formamos um intervalo que começa no ASCII 31 e capturamos o espaço como o segundo elemento do intervalo.) Obviamente, se estamos produzindo alguns caracteres via transliteração, temos que sacrificar caracteres para transliterá-los de, mas letras maiúsculas não são muito úteis e é muito mais fácil escrever sem acesso a elas do que sem acesso a sinais de pontuação.

Aqui está o alfabeto de sinais de pontuação que se tornam disponíveis como resultado da glob (a linha superior mostra a codificação, a linha inferior o caractere que codifica):

BCDEFGHIJKLMNOPQRSTUVWXYZ
 ! "# $% & '() * +; <=>? @ AZz {|} ~ 

Mais notavelmente, temos um monte de sinais de pontuação que não são seguros para o globo, mas são úteis para escrever programas Perl, juntamente com o caractere de espaço. Também salvei duas letras maiúsculas, a literal Ae Z(que codifica não para si, mas para Te U, porque Aera necessária como ponto final superior e inferior do intervalo); isso nos permite escrever a própria instrução de transliteração usando o novo conjunto de caracteres codificados (embora as letras maiúsculas não sejam tão úteis, elas são úteis na especificação de alterações nas letras maiúsculas). Os caracteres mais notáveis ​​que não temos disponíveis são [,, \e ], mas nenhum é necessário (quando eu precisava de uma nova linha na saída, eu a produzi usando a nova linha implícita desayao invés de precisar escrever \n; chr 10também teria funcionado, mas é mais detalhado).

Como sempre, precisamos nos preocupar com o que acontece se o interior do wrapper for danificado fora da literal da string. Um corrompido evalimpedirá que algo funcione; estamos bem com isso. Se as aspas ficarem danificadas, o interior da string não é Perl válido e, portanto, o wrapper a capturará (e as inúmeras subtrações nas strings significam que, mesmo que você pudesse torná-lo válido, Perl não faria nada, o que é um resultado aceitável). O dano à transliteração, se não for um erro de sintaxe, irá mutilar a cadeia de caracteres que está sendo avaliada, normalmente fazendo com que ela se torne um erro de sintaxe; Não tenho 100% de certeza de que não haja casos em que isso ocorra, mas estou forçando-o no momento a garantir, e deve ser fácil o suficiente para corrigir, se houver.

O programa codificado

Olhando dentro da string literal, revertendo a codificação que usei e adicionando espaço em branco para torná-la mais legível, obtemos isso (novamente, imagine um sublinhado de controle antes de -+, que é codificado como A):

$o=q<
  length$o  ==181 || zzzz((()));
  do {
    chop ($t = "eval+<"x4);
    $r = '=-+;-AZz-~=';
    $s = '$o=q<' . $o . '>;eval$o';
    eval '$s=~y' . $r . 'A-Z=';
    say "$t(q($s)=~y=A-Z${r}r)" . "####>"x6;
    say ";" for 1..4
  } for 1..4;
  exit>;
eval $o

As pessoas que estão acostumadas com o método Quines reconhecerão essa estrutura geral. A parte mais crucial está no início, onde verificamos que $ o não está danificado; se os personagens foram excluídos, seu comprimento não irá corresponder 181, então corremos zzzz((()))o que, se não é um erro de sintaxe, devido aos suportes inigualáveis, será um erro de execução mesmo se você excluir todos os três personagens, porque nenhum de zzzz, zzz, zz, e zé uma função, e não há como impedir a análise como uma função além de excluir (((e causar um erro de sintaxe óbvio. O cheque em si também é imune a danos; o ||pode ser danificado, |mas isso fará com que a zzzz((()))chamada seja executada incondicionalmente; variáveis ​​ou constantes danosas causarão uma incompatibilidade porque você está comparando uma delas 0,180, 179, 178De igualdade para um subconjunto dos dígitos de 181; e remover um =causará uma falha na análise e dois =inevitavelmente farão com que o LHS avalie o número inteiro 0 ou uma seqüência nula, sendo ambos falsey.

Atualização : essa verificação estava um pouco errada na versão anterior do programa, então tive que editá-la para corrigir o problema. A versão anterior ficou assim após a decodificação:

length$o==179||zzzz((()))

e foi possível excluir os três primeiros sinais de pontuação para obter isso:

lengtho179||zzz((()))

lengtho179, sendo uma palavra de barra, é verdadeira e, portanto, quebra o cheque. Corrigi isso adicionando dois Bcaracteres extras (que codificam caracteres de espaço), o que significa que a versão mais recente do quine faz isso:

length$o  ==181||zzzz((()))

Agora é impossível ocultar os =sinais e o $sinal sem gerar um erro de sintaxe. (Eu tinha para adicionar dois espaços em vez de um, porque um comprimento de 180se colocar um literal 0de caracteres na fonte, o que poderia ser abusado neste contexto a zero com um bareword, que sucede. Comparar-inteiro) atualização End

Depois que a verificação de comprimento passa, sabemos que a cópia não está danificada, pelo menos em termos de exclusão de caracteres, por isso é tudo simples e simples a partir daí (substituições de sinais de pontuação devido a uma tabela de decodificação corrompida não seriam capturadas com essa verificação , mas eu já verifiquei por meio de força bruta que não há três exclusões somente da tabela de decodificação que quebram o quine; presumivelmente a maioria delas causa erros de sintaxe). Temos $oem uma variável já, portanto, tudo o que precisamos fazer é codificar os invólucros exteriores (com alguma pequena grau de compressão, eu não saltar para fora do parte da questão inteiramente ). Um truque é que armazenamos a maior parte da tabela de codificação em$r; podemos imprimi-lo literalmente para gerar a seção da tabela de codificação do invólucro interno ou concatenar algum código ao seu redor e evalexecutar o processo de decodificação ao contrário (nos permitindo descobrir qual é a versão codificada de $ o , tendo apenas a versão decodificada disponível neste momento).

Finalmente, se fôssemos uma cópia intacta e, portanto, pudéssemos imprimir o programa original inteiro, chamamos exitpara impedir que as outras cópias também tentem imprimir o programa.

Script de verificação

Não é muito bonito, mas publicá-lo porque alguém perguntou. Eu executei isso várias vezes com uma variedade de configurações (normalmente alterando $mine $maxpara verificar várias áreas de interesse); não foi um processo totalmente automatizado. Ele tende a parar de funcionar devido à carga pesada da CPU em outro local; quando isso aconteceu, mudei $minpara o primeiro valor do $xque não estava totalmente verificado e continuei executando o script (garantindo assim que todos os programas no intervalo fossem verificados eventualmente). Eu só verifiquei exclusões da primeira cópia do programa, porque é bastante óbvio que exclusões das outras cópias não podem fazer mais.

use 5.010;
use IPC::Run qw/run/;
undef $/;
my $program = <>;
my $min = 1;
my $max = (length $program) / 4 - 3;
for my $x ($min .. $max) {
    for my $y ($x .. $max) {
        for my $z ($y .. $max) {
            print "$x, $y, $z\n";
            my $p = $program;
            substr $p, $x, 1, "";
            substr $p, $y, 1, "";
            substr $p, $z, 1, "";
            alarm 4;
            run [$^X, '-M5.010'], '<', \$p, '>', \my $out, '2>', \my $err;
            if ($out ne $program) {
                print "Failed deleting at $x, $y, $z\n";
                print "Output: {{{\n$out}}}\n";
                exit;
            }
        }
    }
}

say "All OK!";

3
O OP é um pouco ambíguo; mas achei que a pontuação seria (1116 * 1116) / 3.
Greg Martin

@GregMartin: (1116 * 1116) / 3 é 415152, portanto essa entrada ainda estaria ganhando nessas circunstâncias. No entanto, não acho que o OP possa significar isso, porque daria muito pouco incentivo para lidar com a remoção de vários caracteres. Esse quine pode ter menos da metade do comprimento se você precisar apenas para lidar com a remoção de um caractere; isso me daria um ÷ 4 efetivo na pontuação se a interpretássemos dessa maneira, o que superaria o ÷ 3 que recebo de n = 3 e, portanto, significa que as entradas n = 1 menos interessantes são na verdade uma pontuação melhor.

2
Eu deixei a pontuação mais clara. De qualquer forma, isso é absolutamente incrível; não acho que ninguém iria ficar n> 1.
takra

1
Diz algo sobre o Perl que é mais fácil escrever um programa sem letras do que sem pontuação
Robert Fraser

35

Befunge-98 , 884, n = 14, pontuação ≈ 2.636

f00f00f00f00f00f00f00f00f00f00f00f00f00f00f0xxxxxxxxxxxxxxx"""""""""""""""fffffffffffffff'''''''''''''''000000000000000\\\\\\\\\\\\\\\'''''''''''''''000000000000000\\\\\\\\\\\\\\\'''''''''''''''fffffffffffffff\\\\\\\\\\\\\\\111111111111111---------------:::::::::::::::!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!000000000000000aaaaaaaaaaaaaaa---------------bbbbbbbbbbbbbbb---------------***************jjjjjjjjjjjjjjj$$$$$$$$$$$$$$$'''''''''''''''+++++++++++++++kkkkkkkkkkkkkkk,,,,,,,,,,,,,,,333333333333333kkkkkkkkkkkkkkk$$$$$$$$$$$$$$$000000000000000{{{{{{{{{{{{{{{'''''''''''''''888888888888888uuuuuuuuuuuuuuu'''''''''''''''!!!!!!!!!!!!!!!111111111111111+++++++++++++++'''''''''''''''xxxxxxxxxxxxxxx###############;;;;;;;;;;;;;;;:::::::::::::::!!!!!!!!!!!!!!!kkkkkkkkkkkkkkk@@@@@@@@@@@@@@@dddddddddddddddkkkkkkkkkkkkkkk:::::::::::::::eeeeeeeeeeeeeeekkkkkkkkkkkkkkk,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;

Experimente online!

Isso não funciona apenas quando você remove exatamente 14 caracteres, mas mesmo quando você remove qualquer quantidade de até 14 caracteres.

n = 14pode parecer uma escolha muito arbitrária, mas a técnica que usei só pode ser usada para ordens de proteção contra radiação de 1 a 14, mas não facilmente além disso (pode ser possível, mas não tenho idéia de como). O quine de ordem 1 tem apenas 73 bytes (embora empregue alguns truques de golfe que não se aplicam aos maiores n):

200 20 xx""''ÈÈ..aa22**..33kk$$00{{''!!uu''!!11++''xx##;;::!!kk@@::,,,,;;

Explicação

Quando eu estava trabalhando nessa resposta , descobri que é possível definir o delta do ponteiro de instruções para (2,0)sob condições de proteção de radiação com o seguinte trecho:

20020xx

Veja a resposta para saber por que isso funciona. Achei isso apenas com um pouco de brincadeira à mão, mas isso levantou a questão de saber se existem padrões semelhantes que são robustos sob a remoção de vários caracteres. Então, escrevi um pequeno script do Mathematica para procurá-los por força bruta:

n = 14;
m = 4;
Print @ FromDigits @ {
      m + 1, 0, 
      ## & @@ ((m + 1) IntegerDigits[#, 2, n - 4]),
      m + 1, 0
} & /@ Select[
   Range[0, 2^(n - 4) - 1], 
   AllTrue[
     Subsets[{
         m + 1, 0, 
         ## & @@ ((m + 1) IntegerDigits[#, 2, n - 4]),
         m + 1, 0
       }, 
       {n - m, n - 1}
     ] //. {a___, _, m + 1} | {a___, 0, _} :> {a}, 
     MatchQ@{___, m + 1, 0}
  ] &
];

Isso revelou muito rapidamente um padrão. Para obter um snippet correspondente que funcione para a remoção de até ncaracteres, você pode usar (m0x){n}m0onde mestá n+1ex é mou 0. Portanto, tudo o que se segue funcionaria para remover até dois caracteres:

30030030
30030330
30330030
30330330

Tenho certeza de que é possível provar isso, mas verifiquei naté 7. Claro, isso só funciona desde que possamos representarn+1 como um único dígito, e o maior dígito desse tipo no Befunge 98 é o fque representa 15. É por isso que minha abordagem é limitada n = 14. Se alguém encontrar uma maneira de definir o delta de maneira confiável para maior n+1, provavelmente seria possível aumentar a ordem dessa solução endurecida por radiação indefinidamente.

Vamos dar uma olhada no código real. Existem basicamente duas partes. Primeiro, definimos o delta como(15,0) como acabei de mencionar:

f00f00f00f00f00f00f00f00f00f00f00f00f00f00f0xxxxxxxxxxxxxxx

E o restante do código repetiu cada comando 15 vezes e imprime a fonte. Se removermos a repetição, fica assim:

"f'0\'0\'f\1-:!!0a-b-*j$'+k,3k$0{'8u'!1+'x#;:!k@dk:ek,;

A "técnica é uma técnica 2D de quining padrão: inicia o modo de sequência, empurra todos os caracteres (exceto ele próprio) para a pilha e termina o modo de sequência novamente depois de contornar. Isso nos ajuda a obter todos os pontos de código da segunda metade, mas não conseguirá fornecer nada útil a partir da primeira metade, porque durante todo of00f00...f0 bit, ele registrará apenas dois caracteres (que podem ser fou 0dependendo de quais caracteres foram excluídos) ) Mas como essa parte não é composta de caracteres sendo repetidos 15 vezes, precisamos imprimi-la separadamente de qualquer maneira.

Mais convenientemente, no quine não modificado, o comprimento da corda antes do "é -1 (mod 15). Isso garante que não importa quantos caracteres (até 14) removemos, que o número de caracteres gravados seja sempre 3 (umx e dois de fe 0). Isso é realmente verdade para qualquer pedido de radiação de até 14.

Começamos agora imprimindo a f00f00...f0peça:

f'0\'0\'f\1-:!!0a-b-*j$'+k,

f          Push 15, a loop counter.
'0\'0\'f\  Put "00f" underneath the loop counter.
1-         Decrement the loop counter.
:!!        Copy it, and turn it into a 1 if it's positive.
0a-b-      Push -21.
*          Multiply by 0 if the loop counter is zero, or by 1 otherwise.
j          Jump that many steps. If the value was 0, this is a no-op and
           the loop ends. Otherwise, this brings us back after the f.
$          Pop the loop counter (which is now 0).
'+k,       Print the top of the stack 43 times, which gives us all of
           the "f00f00...f0" and leaves one "0" on top of the stack.

O próximo 3k$simplesmente descarta isso 0, assim como os três caracteres que foram enviados "desde o início do programa. Agora, a pilha contém apenas os caracteres após o "e alguns itens indesejados abaixo do original, f00f00...f0dependendo de quais caracteres foram excluídos.

Agora, basta inverter o topo da pilha (contendo os caracteres restantes) e imprimir cada um deles 15 vezes.

0{     Start a new, empty stack. This pushes two zeros onto the original stack.
'8u    Move the top 56 values from the original stack to the new one, which
       is the 54 characters after the " as well as those two zeros. This is
       implemented as pop-push loop, so it reverses the order of those elements.
'!1+   Push a " by incrementing a !.
'x     Push an x. Now we've got all the characters that are repeated 15 times.
#;     Enter a loop. This is a standard technique for Befunge-98: the ; is
       a bit like a comment character, that ignores everything until the next
       ;, but we jump over the first one with #, so that from now on only
       the code inside will be executed (over and over).
  :!     Copy the top of the stack, and compute logical NOT (1 if 0, 0 otherwise).
  k@     Terminate the program that many times (i.e. when the top of the
         stack is zero).
  dk:    Make 14 copies of the top of the stack.
  ek,    Print 15 characters from the top of the stack.
;

E é isso. :)


16

JavaScript (ES6), 927 bytes, n = 1, pontuação = 859329

nota: não use um REPL (como um console do navegador) para executar isso.

Isso foi escrito antes que o tamanho do código fosse um fator, por isso ainda não é um jogo de golfe.

Isso foi muito difícil e merece uma explicação completa. Que escreverei mais tarde, depois de explorar um pouco mais esse desafio!

etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;
setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

nota: existe uma nova linha à direita

Basicamente, a primeira linha é cuidadosamente construída para renomear todos os 'erros ortográficos' de setTimeoutfunções válidas, de modo que, se um caractere for removido de um dos, setTimeouto código não cometerá erros e a versão ilesa poderá ser executada. Também está escrito para que, se qualquer caractere for removido da primeira linha, não haverá erro e o restante do código não seja afetado.

O segundo e o terceiro bloco são exatamente equivalentes. Se um for executado até a conclusão, ele define a _variável para que o outro saiba que não deve duplicar o quine. Se um desses blocos errar, ele não afetará o outro bloco porque foi chamado de forma assíncrona setTimeout. O erro causará_ não seja definido, portanto o outro bloco será restaurado com êxito. O código principal está em uma string, que é verificada quanto ao comprimento em cada bloco para garantir que não houve remoções.

As strings de modelo na próxima linha com alguns comentários no final das strings de modelo protegem o código de erros se um dos backticks que formam a string de modelo for removido. Se o backtick final for removido, a sequência do modelo será finalizada pelo backtick no comentário. Se o backtick inicial for removido, o setTimeout será avaliado como uma função não atribuída (no-op) e o código será executado normalmente, sem um setTimeout. O backtick final é anulado por outro comentário.


O que você disse? Você quer experimentar? Não digas mais nada!

Recomenda-se o modo de página inteira.

Ignore a caixa de entrada, este trecho não aceita entrada.

Tente remover qualquer caractere do código!

Não acredita nisso? O código normal ainda funcionará (mas não funcionará ...) Tente algo como console.log(5)!

nota: o trecho teve que ser modificado ligeiramente para desativar o recurso REPL, por isso removi vários recursos de saída apenas para esta resposta.

etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;
setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`
<!--                               Try the test suite below!                              --><strong id="bytecount" style="display:inline; font-size:32px; font-family:Helvetica"></strong><strong id="bytediff" style="display:inline; margin-left:10px; font-size:32px; font-family:Helvetica; color:lightgray"></strong><br><br><pre style="margin:0">Code:</pre><textarea id="textbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><pre style="margin:0">Input:</pre><textarea id="inputbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><button id="testbtn">Test!</button><button id="resetbtn">Reset</button><br><p><strong id="origheader" style="font-family:Helvetica; display:none">Original Code Output:</strong><p><div id="origoutput" style="margin-left:15px"></div><p><strong id="newheader" style="font-family:Helvetica; display:none">New Code Output:</strong><p><div id="newoutput" style="margin-left:15px"></div><script type="text/javascript" id="golfsnippet">var bytecount=document.getElementById("bytecount");var bytediff=document.getElementById("bytediff");var textbox=document.getElementById("textbox");var inputbox=document.getElementById("inputbox");var testbtn=document.getElementById("testbtn");var resetbtn=document.getElementById("resetbtn");var origheader=document.getElementById("origheader");var newheader=document.getElementById("newheader");var origoutput=document.getElementById("origoutput");var newoutput=document.getElementById("newoutput");textbox.style.width=inputbox.style.width=window.innerWidth-50+"px";var _originalCode=null;function getOriginalCode(){if(_originalCode!=null)return _originalCode;var allScripts=document.getElementsByTagName("script");for(var i=0;i<allScripts.length;i++){var script=allScripts[i];if(script.id!="golfsnippet"){originalCode=script.textContent.trim();return originalCode}}}function getNewCode(){return textbox.value.trim()}function getInput(){try{var inputText=inputbox.value.trim();var input=eval("["+inputText+"]");return input}catch(e){return null}}function setTextbox(s){textbox.value=s;onTextboxChange()}function setOutput(output,s){output.innerHTML=s}function addOutput(output,data){output.innerHTML='<pre style="background-color:'+(data.type=="err"?"lightcoral":"lightgray")+'">'+escape(data.content)+"</pre>"}function getByteCount(s){return(new Blob([s],{encoding:"UTF-8",type:"text/plain;charset=UTF-8"})).size}function onTextboxChange(){var newLength=getByteCount(getNewCode());var oldLength=getByteCount(getOriginalCode());bytecount.innerHTML=newLength+" bytes";var diff=newLength-oldLength;if(diff>0){bytediff.innerHTML="(+"+diff+")";bytediff.style.color="lightcoral"}else if(diff<0){bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgreen"}else{bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgray"}}function onTestBtn(evt){origheader.style.display="inline";newheader.style.display="inline";setOutput(newoutput,"");setOutput(origoutput,"");var input=getInput();if(input===null){addOutput(origoutput,{type:"err",content:"Input is malformed. Using no input."});addOutput(newoutput,{type:"err",content:"Input is malformed. Using no input."});input=[]}doInterpret(getNewCode(),input,function(data){addOutput(newoutput,data)});doInterpret(getOriginalCode(),input,function(data){addOutput(origoutput,data)});evt.stopPropagation();return false}function onResetBtn(evt){setTextbox(getOriginalCode());origheader.style.display="none";newheader.style.display="none";setOutput(origoutput,"");setOutput(newoutput,"")}function escape(s){return s.toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}window.alert=function(){};window.prompt=function(){};function doInterpret(code,input,cb){var workerCode=interpret.toString()+";function stdout(s){ self.postMessage( {'type': 'out', 'content': s} ); }"+" function stderr(s){ self.postMessage( {'type': 'err', 'content': s} ); }"+" function kill(){ self.close(); }"+" self.addEventListener('message', function(msg){ interpret(msg.data.code, msg.data.input); });";var interpreter=new Worker(URL.createObjectURL(new Blob([workerCode])));interpreter.addEventListener("message",function(msg){cb(msg.data)});interpreter.postMessage({"code":code,"input":input});setTimeout(function(){interpreter.terminate()},1E4)}setTimeout(function(){getOriginalCode();textbox.addEventListener("input",onTextboxChange);testbtn.addEventListener("click",onTestBtn);resetbtn.addEventListener("click",onResetBtn);setTextbox(getOriginalCode())},100);function interpret(code,input){_=undefined;window={};alert=function(s){stdout(s)};window.alert=alert;console.log=alert;prompt=function(s){if(input.length<1)stderr("not enough input");else{var nextInput=input[0];input=input.slice(1);return nextInput.toString()}};window.prompt=prompt;(function(){try{_=undefined;eval(code);if(typeof evalResult=="disabled_function_evaluation"){var callResult=evalResult.apply(this,input);if(typeof callResult!="undefined")stdout(callResult)}}catch(e){stderr(e.message)}})()};</script>

Uma explicação melhor está por vir. Enquanto isso, sinta-se à vontade para me enviar uma mensagem no chat @jrich com quaisquer comentários / perguntas / críticas!


ah tudo bem, gritos: |
Downgoat

4
Use em thisvez de window.
Mama Fun Roll

3
+1 por incluir o significado da vida no seu código fonte
Cyoce 27/11
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.