Seu desafio é simples. Escreva dois programas que não compartilhem caracteres que tenham saída um do outro.
Exemplo
Dois programas P e Q são quines mutuamente exclusivos se:
- Saídas P Q
- Q produz P
- Não existe um caractere c que pertença a P e Q
- Cada programa P e Q são quines adequados
- Isso considera quines vazios e quines que lêem seu próprio código-fonte (ou o do outro) como inválido .
Mais regras
- O menor comprimento combinado desses programas vence. Ou seja, tamanho ( P ) + tamanho ( Q ) é a sua pontuação, e a pontuação mais baixa vence.
- Ambos os programas estão no mesmo idioma
- Cada programa pode ser um programa ou função completo e não precisa ser o mesmo.
- Por exemplo, P pode ser um programa completo e Q pode ser uma função.
Verificação
Este Experimente online! O snippet aqui pode verificar se dois programas são ou não mutuamente exclusivos. As entradas são colocadas nos dois primeiros argumentos.
code-challenge
quine
Conor O'Brien
fonte
fonte
Respostas:
> <> , Pontuação: 41 + 41 = 82
Editar: ambos continham um 3. Corrigido
e
Experimente online! (troque as linhas para obter a outra saída) Com a verificação desta vez!
><>
é uma linguagem especialmente difícil de usar aqui, como há apenas uma maneira de caracteres de saída, o comandoo
. Felizmente, podemos usar o comando p ut para colocar umo
no código-fonte durante a execução, como na minha resposta de Programação em um mundo intocado .Este levou muitas tentativas e erros. Comecei com os dois programas mutuamente exclusivos:
e
Cada um se transforma e seus dados por N, o primeiro subtraindo e o segundo adicionando. Em seguida, o resultado é inverso. O ponto é que os dados após cada programa são o outro programa em sentido inverso, deslocados por N. (
X
é o número da célula onde o programa precisa colocar ao
tecla e Y é a célula na qual o ponteiro volta para.?
É onde elao
é colocada) .Ambos seguem a mesma estrutura, representada de maneiras diferentes. Eles executam uma string literal sobre todo o código, adicionando-o à pilha. Eles recriam o comando literal de cadeia de caracteres que eles usaram e o colocam na parte inferior da pilha. Eles passam pela pilha, adicionando / subtraindo N a cada caractere e imprimindo-os.
O primeiro programa usa
'
como a string literal e o simplesd3*}
de criar o valor 39 e empurrá-lo para o final da pilha. O segundo usa"
como a string literal com a mesma função. Eler
everses a pilha,g
ets o caractere na célula 0,0 e inverte a pilha novamente. Em seguida, eleg
define o valor na célula 4,0 (g
) e adiciona 8 a ele para obtero
e coloca isso em X.Ambos os programas usam um método diferente de loop. O primeiro programa usa o comando skip (
!
) para executar apenas metade das instruções enquanto vai para a esquerda, inverte a direção e executa a outra metade. O segundo usa o comando jump (.
) para retroceder para o início do loop na célula Y. Ambos são executados até que não haja mais itens na pilha e os erros do programa.Eu tive vários problemas com a maioria dos valores mais baixos de N, porque a troca de um caractere o tornaria outro caractere essencial para esse programa (e, portanto, não poderia ser usado como dados para o outro programa) ou dois caracteres do dois programas mudariam para o mesmo personagem. Por exemplo:
+
+1 =,
=-
-1.
+2 =0
*
=-
-3g
+4 =k
=o
-4etc.
Finalmente cheguei a 10 (
a
), onde consegui evitar esses problemas. Pode haver uma versão mais curta em que os turnos são revertidos e o primeiro programa está adicionando N enquanto o segundo o subtrai. Isso pode ser pior, porém, como o primeiro programa geralmente está na extremidade inferior da escala ASCII, é melhor subtrair para evitar conflitos.fonte
Quarto (gforth little-endian de 64 bits) , 428 + 637 = 1065 bytes
Experimente online!
Script de verificação
Obrigado a Nathaniel pela idéia de usar o Forth - ele me lembrou nos comentários que Forth não diferencia maiúsculas de minúsculas . Depois vieram as mudanças de humor - eu tenho encontrado razões pelas quais isso não vai funcionar, seguidas por soluções para esses problemas, repetidas vezes. Enquanto gira a minha bicicleta de treinamento indoor como um girador de fidget deformado e deformado (basta pegar uma extremidade do guidão e inclinar um pouco).
Antes de escrever esses programas, rascunhei quais caracteres podem ser usados por qual programa. Especificamente, o segundo programa pode usar apenas letras maiúsculas, dígitos decimais, tabulações e vírgulas. Isso significa que o primeiro programa é todo em minúsculas, mas usei algumas letras maiúsculas para seus valores ASCII.
Como as guias são pesadas, usarei espaços na explicação.
O primeiro programa é do formato
s" code"code
-s"
inicia uma literal de cadeia de caracteres, que é processada pela segunda cópia do código - uma estrutura padrão de quine. No entanto, em vez de emitir seu próprio código-fonte, ele criará o outro programa, que se parece com isso:HERE
64-bit-number-literal ,
length-of-the-string
115 EMIT 34 EMIT 9 EMIT 2DUP TYPE 34 EMIT TYPE
Isso usa o espaço de dados da Forth.
HERE
retorna o ponteiro para o final da área de espaço de dados alocada no momento e,
acrescenta uma célula preenchida com um número a ele. Portanto, os três primeiros pontos de marcador podem ser vistos como uma literal de string criada usandos"
. Para finalizar o segundo programa:EMIT
gera um caractere devido ao seu valor ASCII, portanto:115 EMIT
imprime uma letra minúsculas
34 EMIT
imprime o caractere de citação"
9 EMIT
imprime uma guia2DUP
duplica os dois principais elementos da pilha( a b -- a b a b )
, aqui está o ponteiro e o comprimento da stringTYPE
imprime uma string para gerar a primeira cópia do código34 EMIT
imprime a cotação de fechamento"
e, finalmente,TYPE
gera a segunda cópia do códigoVamos ver como o primeiro programa funciona. Em muitos casos, é necessário evitar números, o que é feito usando a
'x
extensão de sintaxe gforth para literais de caracteres e, algumas vezes, subtraindo o valor ASCII do espaço, que pode ser obtido usandobl
:Para finalizar, gostaria de dizer que tentei usar
EVALUATE
, mas o segundo programa se torna maior que os dois apresentados acima. Enfim, aqui está:Se você conseguir jogar o suficiente para superar minha
s" ..."...
abordagem, vá em frente e publique como sua própria resposta.fonte
Perl,
(311 + 630 = 941 bytes)190 + 198 = 388 bytesAmbos os programas são impressos na saída padrão.
O primeiro programa perl contém principalmente caracteres ASCII imprimíveis e novas linhas, e termina em exatamente uma nova linha, mas as duas letras ÿ representam o byte não ASCII \ xFF:
O segundo contém principalmente bytes não ASCII, incluindo vários caracteres de alto controle que são substituídos por estrelas nesta postagem e nenhuma nova linha:
Um hexdump do primeiro programa com
xxd
é:E um hexdump do segundo programa é:
No segundo programa, a cadeia de caracteres entre aspas (189 bytes de comprimento, delimitada por tildes) é o primeiro programa inteiro, exceto a nova linha final, codificada apenas complementando bit a bit cada bit. O segundo programa simplesmente decodifica a string complementando cada um dos bytes, o que o
~
operador faz em perl. O programa imprime a string decodificada seguida por uma nova linha (osay
método adiciona uma nova linha).Nesta construção, o decodificador do segundo programa usa apenas seis caracteres ASCII diferentes, de modo que o primeiro programa pode ser praticamente arbitrário, desde que contenha apenas caracteres ASCII e exclua esses seis caracteres. Não é difícil escrever nenhum programa perl sem usar esses cinco caracteres. A lógica quine atual está, portanto, no primeiro programa.
No primeiro programa, a lógica quine usa um dicionário de 11 palavras
@f
e monta a saída dessas palavras. As primeiras palavras repetem a maior parte do código fonte do primeiro programa. O restante das palavras são caracteres únicos específicos. Por exemplo, a palavra 5 é um til, que é o delimitador para as duas cadeias literais no segundo programa. A lista de números entre colchetes é a receita para quais palavras serão impressas em que ordem. Este é um método de construção geral bastante comum para quines, a única mudança nesse caso é que as primeiras palavras do dicionário são impressas com seus bytes complementados em bits.fonte
Haskell , 306 + 624 = 930 bytes
Programa 1: Uma função anônima pegando um argumento fictício e retornando uma string.
Experimente online!
Programa 2:
q[[40,...]]
no final, é uma função anônima que pega um argumento fictício e retorna uma string.Experimente online!
Conjunto de caracteres 1 (inclui espaço):
Conjunto de caracteres 2 (inclui nova linha):
Como apenas o conjunto 1 contém caracteres não ASCII, seus bytes UTF-8 também são disjuntos.
Como funciona
O Programa 1 geralmente é escrito com expressões lambda, espaços e parênteses, uso gratuito de funções alfanuméricas incorporadas e com os dados quine como literais de string no final.
a
oub
, que formam seqüências de escape válidas que percorrem o caminhoshow
.a
,b
ec
são as únicas letras minúsculas cujos códigos ASCII são menores que 100, economizando um dígito na codificação numérica usada pelo programa 2.O Programa 2 geralmente é escrito com equações de função de nível superior (exceto a final anônima), literais de caracteres e números decimais, sintaxe de lista / intervalo e operadores, e com os dados quine como uma lista de listas de
Int
s no final.Passo a passo, programa 1
b
ec
são os valores das literais de cadeia de caracteres para o programa 2 e 1, respectivamente, dados como argumentos finais para a expressão lambda.()
é um argumento falso apenas para satisfazer a regra do PPCG de que o programa deve definir uma função.foldr(\a->map pred)b(show()>>c)
decodifica a stringb
no código principal do programa 2 aplicandomap pred
a ela um número de vezes igual ao comprimento deshow()>>c == c++c
, ou182
.tail(show c)
converte a stringc
no código principal do programa 1, com uma aspas dupla final anexada.:pure b
combina isso em uma lista com a sequênciab
.map(map fromEnum)$
converte as seqüências de caracteres em listas de pontos de código.`mappend`show(...)
serializa a lista de listas resultante e, finalmente, anexa-a ao código principal do programa 2.Passo a passo, programa 2
z~z=[[['@','0'..]!!4..]!!z]
é uma função que converte pontos de código em caracteres (necessário para escrever, pois nem todos os caracterestoEnum
estão disponíveis).z
. O marcador de preguiça~
não tem efeito nessa posição, mas evita um caractere de espaço.['@','0'..]
é um intervalo da lista de passos para trás, começando no código ASCII 64 e pulando 16 para baixo a cada passo.!!4
a isso fornece um\NUL
personagem.[ ..]
intervalo fornece uma lista de todos os caracteres, que são!!z
indexados.z
nas listas usando em=<<
vez de indisponívelmap
e<$>
.q[x,q]_=z=<<x++q++[34,34]++x
é uma função que constrói o programa 1 a partir da lista de dados quine.x
são os dados para o núcleo do programa 1 (incluindo uma citação dupla final) e os internosq
são os dados ofuscados para o núcleo do programa 2._
é outro argumento fictício apenas para tornar a função anônima final uma função em vez de apenas uma string.x++q++[34,34]++x
concatena as peças, incluindo duas aspas duplas com o código ASCII 34.z=<<
constrói o programa 1 mapeandoz
a concatenação para converter de pontos de código em caracteres.q[[40,...]]
é uma função anônima combinadaq
com os dados do quine.fonte
Gelatina ,
128 90 87 86 85 7916 + 32 = 48 bytesExperimente online!
Experimente online!
O primeiro programa faz o seguinte:
Isso deixa as strings
79,7806,8318,7885,7769,338,115
eỌṘ
os dois argumentos da cadeia e são implicitamente concatenadas e impressas no final.O segundo programa calcula o
chr
(Ọ
) da lista de números que retornaOṾ⁾ọṙŒs
.Ṙ
imprime“OṾ⁾ọṙŒs”
(entre aspas) e retorna a entrada, deixando“OṾ⁾ọṙŒs”OṾ⁾ọṙŒs
como saída total.fonte
Gol> <> ,
23 + 23 = 4622 + 22 = 4420 + 20 = 40 bytesExperimente online!
Experimente online!
Verifique online!
Como eles trabalham
Adaptado da resposta de Jo King> <> . Tendo muito mais comandos alternativos para saída e repetição, não havia necessidade de
g
oup
, e os dois corpos principais ficaram muito mais curtos.Outra diferença principal é que eu gero a cotação do oponente diretamente no topo da pilha. Dessa forma, era um pouco mais fácil manter o invariante de
quote + my code + opponent code(reversed and shifted)
.fonte