Quines Negativos Mútuos

22

Isso foi inspirado em Imprimir um Negativo do seu Código e Golf uma solução comum .


Considere um retângulo de caracteres que atenda às seguintes restrições:

  1. Consiste apenas em caracteres ASCII imprimíveis
  2. Dimensões maiores que 1
  3. Cada linha e cada coluna contém pelo menos um espaço.
  4. Cada linha e cada coluna contém pelo menos um caractere não espacial.

Por exemplo, a seguir é um retângulo 6x4 válido:

%n 2e 
1  g 3
 &* __
 3  

Um negativo para esse retângulo é definido como um retângulo de dimensões iguais, com todos os espaços substituídos por caracteres não espaciais e todos os caracteres não espaciais substituídos por espaços. Um negativo do retângulo acima pode ser:

  f  ^
 33 > 
9  $  
^ }|Q'

Qualquer caractere ASCII imprimível sem espaço pode ser usado para substituir um espaço.

Tarefa

Sua tarefa é escrever um programa com código-fonte retangular, que produza um negativo válido para si mesmo. O resultado negativo também deve ser um programa válido, no mesmo idioma que o original, e deve gerar a origem do original.

Nenhum espaço em branco à direita pode ser adicionado ou removido, exceto por uma única nova linha à direita no final de qualquer saída, que é opcional.

Nenhum dos programas tem permissão para ler o código fonte de ambos; nem os ambientes REPL podem ser assumidos.

Pontuação

Sua pontuação é o produto das dimensões do seu código (ou seja, se seu código-fonte está em um retângulo de 12 por 25, sua pontuação é de 12 * 15 = 180). Além disso, para cada caractere usado em um comentário, sua pontuação aumenta em 2 (se você usar /* .. */uma vez no seu código e seu código estiver em um retângulo de 10 por 10, sua pontuação será 10 * 10 + 8 * 2 = 116).

A pontuação mais baixa vence.

Se houver um empate, a submissão com o menor número de espaços no programa (o original ou o negativo, o que tiver menos espaços) vence.

Se ainda houver um empate, a resposta anterior vencerá.

Existe um bônus de -52% , se a combinação do original e do negativo produzir uma solução normal. Por exemplo:

Original   Negative   Combined
 A A       B B        BABA
A A         B B       ABAB
es1024
fonte
@ Optimizer Essa é a razão pela qual não tornei o bônus obrigatório.
Es1024
1
Eu estou falando apenas da parte negativa do quine mútuo;)
Optimizer
@ MartinBüttner Ah, meu mal. Eu estava pensando em termos estranhos.
Optimizer
1
Alguém pode fazer isso em c? +1 para quem quiser primeiro!
MegaTom

Respostas:

15

CJam, ( 51 49 47 46 45 42 x 2) * 48% = 40,32

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 
                                         R

A execução do código acima fornece esta saída:

                                         R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 

executando o qual, imprime de volta a fonte original.

A fonte e a saída são simplesmente linhas trocadas.

Agora vem a mágica.

A sobreposição da origem e da saída resulta no seguinte código:

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R

que é um quine perfeito!

Experimente-os online aqui


Como funciona

Toda a lógica de impressão está na primeira linha, que lida com os três casos explicados posteriormente.

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~
{                                     }_~   "Copy this code block and execute the copy";
 ]                                          "Wrap everything before it in array";
  )                                         "Pop the last element out of it";
   "_~"+                                    "Append string '_~' to the copied code block";
        S41*                                "Create a string of 41 spaces";
            'R+                             "Append character R to it";
               @,                           "Rotate the array to top and get its length";
                 [{   }{   }{     }]=~      "Get the corresponding element from this"
                                            "array and execute it";

A matriz na última linha acima é a matriz que possui blocos de código correspondentes aos três casos.

Caso 1

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 
                                         R

Nesse caso, o comprimento da pilha restante era 0, como quando o bloco foi executado, ele tinha apenas a cópia do próprio bloco, que foi inicialmente inicializada na terceira etapa acima. Então, retiramos o índice 0da última matriz e o executamos:

 {N@S}          "Note that at this point, the stack is something like:"
                "[[<code block that was copied> '_ '~ ] <41 spaces and R string>]";
  N             "Add newline to stack";
   @            "Rotate the code block to top of stack";
    S           "Put a trailing space which negates the original R";

Nesse caso, a segunda linha é no-op no que diz respeito à impressão da saída.

Caso 2

                                         R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 

Nesse caso, a pilha já continha uma sequência vazia, portanto, quando o bloco de código copiado foi executado, ele tinha 2 elementos - uma sequência vazia e o próprio bloco de código. Então, retiramos o índice 1da última matriz e o executamos:

{SN@}            "Note at this point, the stack is same as in case 1";
 SN              "Push space and newline to stack";
   @             "Rotate last three elements to bring the 41 spaces and R string to top";

Caso 3

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R

Nesse caso, a pilha possui 6 elementos. Então, depois de exibir o último bloco de código, o comprimento restante da matriz é 5. Retiramos o índice 5da matriz e o executamos. (Observe que em uma matriz de 3elementos, índice 5é índice 5%3 = 2)

{W=N]_}          "Note at this point, the stack is same as in case 1";
 W=              "Take the last character out of the 41 spaces and R string, i.e. R";
   N]            "Add a new line to stack and wrap the stack in an array";
     _           "Copy the array to get back the source of Case 3 itself";
Optimizer
fonte
27

Python, 97x2 + 2 = 196

Não é uma ótima solução para começar, mas pelo menos funciona (eu acho).

c='o=1-%d;print("%%97s\\n%%97s"%%("#","c=%%r;exec(c%%%%%%d)\\40"%%(c,o),"#")[o:][:2])';exec(c%1) 
                                                                                                #

Saída:

                                                                                                #
c='o=1-%d;print("%%97s\\n%%97s"%%("#","c=%%r;exec(c%%%%%%d)\\40"%%(c,o),"#")[o:][:2])';exec(c%0) 
grc
fonte
8
+1 para a única submissão tão longe para usar uma linguagem real
WinnieNicklaus
Também não parece estar muito longe do bônus.
Mbomb007
23

CJam, ( 58 56 54 48 46 x 2) * 48% = 44,16

{`"_~"+{_,94\m2/S*a_+\*                       
                       N/23f/Wf%N*}_`'"#)!*}_~

que imprime

                       {`"_~"+{_,94\m2/S*a_+\*
N/23f/Wf%N*}_`'"#)!*}_~                       

Os caracteres não espaciais em cada linha permanecem os mesmos entre os dois quines mútuos.

Mas agora a parte realmente doce:

{`"_~"+{_,94\m2/S*a_+\*{`"_~"+{_,94\m2/S*a_+\*
N/23f/Wf%N*}_`'"#)!*}_~N/23f/Wf%N*}_`'"#)!*}_~

é um quine! :)

Teste aqui.

Como funciona

Eu recomendo que você leia a explicação em minha outra submissão primeiro, uma vez que explica os conceitos básicos de quining no CJam em geral.

Este é um pouco mais complicado. Para o quine mútuo, como no outro caso, modifico a representação em cadeia do bloco adicionando espaços antes ou depois de cada linha e trocando um 0 por um 2, para que o programa resultante coloque os espaços na extremidade oposta.

Observe que os espaços não afetam de maneira alguma os quines mútuos. No primeiro, eles estão em um bloco, que na verdade não é usado, e no segundo, em torno de todo o código.

Para obter um quine regular ao combinar os dois, precisamos encontrar uma maneira de evitar fazer toda essa modificação. Observe que a estrutura do espaço em branco e do código significa que, combinando ambos, inserimos a totalidade de um quine no outro. Portanto, se colocarmos todo o código de modificação em um bloco, podemos executá-lo dependendo do seu conteúdo real.

Então agora eu tenho esse bloco ... para os quines mútuos, ele contém apenas o código que realmente quero executar. Para o quine combinado, ele também contém todo o quine novamente, em uma posição aleatória, o que não faz sentido ... mas, como é um bloco, não é executado automaticamente. Portanto, podemos determinar se a string deve ser modificada com base no conteúdo desse bloco. É para isso que _`'"#)!serve. Duplica o bloco, converte-o em uma cadeia de caracteres, procura o caractere "(que, nas linhas comuns, aparece apenas fora do bloco) - a pesquisa retorna -1se o caractere não for encontrado e, caso contrário, um número inteiro positivo -, incrementa o resultado e nega isso logicamente. Portanto, se um "foi encontrado, isso cede de 0outra forma 1. Agora apenas fazemos*, que executa o bloco uma vez, se o resultado for 1 e não for o caso.

Finalmente, é assim que o código modificador funciona:

_,94\m2/S*a_+\*N/23f/Wf%N*
_,                         "Duplicate the quine string and get its length.";
  94\m                     "Subtract from 94.";
      2/                   "Divide by two.";
        S*                 "Create a string with that many spaces. This will be
                            an empty string for the first mutual quine, and contain
                            23 spaces for the second mutual quine.";
          a_+              "Create an array that contains this string twice.";
             \*            "Join the two copies together with the quine string.";
               N/          "Split into lines.";
                 23f/      "Split each line into halves (23 bytes each).";
                     Wf%   "Reverse the two halves of each line.";
                        N* "Join with a newline.";

Reivindicação da recompensa, (12 x 10) * 48% = 57,6

Acontece que esse código pode ser dividido em mais linhas com muita facilidade com algumas modificações. Adicionamos 2 caracteres, para obter 48 em uma linha, que podemos dividir convenientemente por 8, para que possamos ter 8 linhas com 6 caracteres de código e 6 espaços. Para fazer isso, também precisamos alterar alguns números e reorganizar um operador ou dois, para que eles não sejam divididos nas duas linhas. Isso nos dá uma versão de trabalho com tamanho 12 x 8 ... uma fora do requisito. Então, apenas adicionamos duas linhas que não fazem nada (pressione 1, digite 1, digite 1, digite 1 ...), para obter 12 x 10 :

{`"_~"      
      +{129X
$,m2/S      
      *a_+\*
N/6f/1      
      ;1;1;1
;1;1;1      
      ;Wf%N*
}_`'"#      
      )!*}_~

Como o anterior, isso produz

      {`"_~"
+{129X      
      $,m2/S
*a_+\*      
      N/6f/1
;1;1;1      
      ;1;1;1
;Wf%N*      
      }_`'"#
)!*}_~      

(Observação: não há necessidade de continuar alternando a esquerda e a direita nas linhas intermediárias, apenas a posição da primeira e da última linha é importante. A esquerda e a direita podem ser escolhidas arbitrariamente para todas as outras linhas.)

E por pura coincidência, o quine completo também funciona:

{`"_~"{`"_~"
+{129X+{129X
$,m2/S$,m2/S
*a_+\**a_+\*
N/6f/1N/6f/1
;1;1;1;1;1;1
;1;1;1;1;1;1
;Wf%N*;Wf%N*
}_`'"#}_`'"#      
)!*}_~)!*}_~

(Digo coincidência, porque a parte que cuida de não executar o código interno agora fica estranhamente intercalada com a outra, mas ainda funciona bem.)

Dito isto, eu poderia ter adicionado 44 linhas 1;à minha inscrição original para cumprir o requisito de recompensa, mas 12 x 10parece muito mais organizado. ;)

Edit: Haha, quando eu disse "pura coincidência" eu não poderia estar mais no local. Eu examinei como a solução final agora realmente funciona, e é absolutamente ridículo. Existem três blocos aninhados (4 na verdade, mas o mais interno é irrelevante). A única parte importante do mais interno desses 3 blocos é que ele contém um "(e não o que ele fez na submissão original, mas o '"que é usado no final para verificar esse mesmo caractere). Portanto, a estrutura básica do quine é:

{`"_~"{`"_~"+{___'"___}_`'"#)!*}_~)!*}_~

Vamos dissecar isso:

{`"_~"                               }_~ "The standard CJam quine.";
      {`"_~"+                  }_~       "Another CJam quine. Provided it doesn't do 
                                          anything in the rest of that block, this 
                                          will leave this inner block as a string on 
                                          the stack.";
                                  )      "Slice the last character off the string.";
                                   !     "Negate... this yields 0.";
                                    *    "Repeat the string zero times.";

Portanto, isso realmente faz alguma mágica engraçada, mas como o bloco interno deixa uma única string na pilha, )!*isso transforma uma string vazia. A única condição é que as coisas no bloco interno depois +não façam mais nada na pilha, então vamos ver isso:

             {___'"___}                  "Push a block which happens to contain 
                                          quotes.";
                       _`'"#)!*          "This is from the original code and just 
                                          removes the block if it does contain 
                                          quotes.";
Martin Ender
fonte
4
TLDR; upvote;)
Optimizer
Não deveria estar Y/2na combinação combinada?
amigos estão dizendo sobre schnaader
"E por pura coincidência" nah;)
Timtech
@ Timtech Veja minha edição. Pura coincidência não era um eufemismo. ^^
Martin Ender
10

CJam, 42 37 33 x 2 = 66

{`As_W%er"_~"+S 33*F'Lt1{\}*N\}_~
               L                 

que imprime

               L                 
{`As_W%er"_~"+S 33*F'Lt0{\}*N\}_~

(As linhas são trocadas e um se 1transforma em um 0.)

Teste aqui.

Como funciona

Primeiro, você deve entender o quine básico do CJam:

{"_~"}_~

As chaves simplesmente definem um bloco de código, como uma função, que não é imediatamente executado. Se um bloco não executado permanecer na pilha, seu código-fonte (incluindo chaves) será impresso. _duplica o bloco e ~executa a segunda cópia. O próprio bloco simplesmente empurra a string que contém _~. Portanto, esse código deixa a pilha no seguinte estado:

Stack: [{"_~"} "_~"]

O bloco e a cadeia de caracteres são simplesmente impressos lado a lado no final do programa, o que torna isso uma solução.

A vantagem disso é que podemos fazer o que quisermos no bloco, e isso permanece um problema, porque cada pedaço de código será automaticamente impresso no conteúdo do bloco. Também podemos modificar o bloco, obtendo sua representação de string com `(que é apenas uma string do bloco com chaves).

Agora vamos olhar para esta solução. Observe que qualquer parte do quine mútuo contém o bloco do tipo quine com _~, e um L. O Lempurra uma cadeia vazia para a pilha, o que não contribui para a saída. Então, aqui está o que o bloco faz:

`                             "Convert block to its string representation.";
 As                           "Push 10 and convert to string.";
   _W%                        "Duplicate and reverse, to get another string 01.";
      er                      "Swap 0s and 1s in the block string.";
        "_~"+                 "Append _~.";
             S 33*            "Push a string with 33 spaces.";
                  F'Lt        "Set the character at index 15 to L.";
                      1{ }*   "Repeat this block once.";
                        \     "Swap the code string and the space string.";
                           N\ "Push a newline and move it between the two lines.";

Portanto, isso fará a parte quine, mas troque um 1 por um 0 e também acrescentará outra linha a um L, onde o código acima tem um espaço. O problema é que a ordem dessas duas linhas é determinada pela troca interna { }*. E como a parte externa do quine mútuo 0substitui o a por um 1, ele nunca executa essa troca e, portanto, produz a ordem original novamente.

Martin Ender
fonte
5

CJam, 27 × 2 = 54

{ ` " _ ~ " + N - ) 2 * ' '
 > @ t s G B + / N * } _ ~ 

Saída:

 { ` " _ ~ " + N - ) 2 * ' 
' > @ t s G B + / N * } _ ~

'A'B>compara os caracteres A e B. ' '\n >retorna 1 porque 32> 10 e ' \n' >retorna 0 porque os dois espaços são iguais.

jimmy23013
fonte
2

CJam, 30 29 x 2 = 58

{"_~"SN]_,4=S28*'R+\{N@}*}_~ 
                            R

Saídas:

                            R
{"_~"SN]_,4=S28*'R+\{N@}*}_~ 

que produz a fonte original.

Isso é baseado no mesmo princípio da minha outra solução.

Experimente online aqui

Optimizer
fonte