Escreva o programa de auto-identificação mais curto (uma variante quine)

57

Escreva um programa que gere uma saída "true" se a entrada corresponder ao código-fonte do programa e que gere uma saída "false" se a entrada não corresponder ao código-fonte do programa.

Esse problema pode ser descrito como relacionado a quines, pois o programa deve poder, de alguma forma, computar seu próprio código-fonte no processo.

Este é o código golf: regras padrão se aplicam. Seu programa não deve acessar arquivos especiais, como o arquivo de seu próprio código-fonte.

Editar: se você escolher, verdadeiro / falso pode ser substituído por Verdadeiro / Falso ou 1/0.

Exemplo

Se o código fonte do seu programa for bhiofvewoibh46948732));:/)4, aqui está o que seu programa deve fazer:

Entrada (Stdin)

bhiofvewoibh46948732));:/)4

Saída (saída padrão)

true

Entrada

(Anything other than your source code)

Resultado

false
PhiNotPi
fonte
7
A saída true/ falseé um forte requisito ou as variações ( True/ False, 1/ 0) também são aceitáveis?
Cristian Lupascu
É um problema se o programa produzir um pouco mais do que verdadeiro / falso (se continuar sendo inequívoco e terminar com verdadeiro / falso)?
Denys Séguret
11
Relacionado: Interprete seu idioma, mas não você?
Ilmari Karonen
5
Então você quer dizer um programa narcisista?
PyRulez

Respostas:

33

JavaScript: 26

function f(s){return s==f}

Não sei se um arquivo JavaScript realmente se qualifica como um "programa".

Denys Séguret
fonte
7
+1 Isso funciona porque todos os objetos têm um .toString()método em JavaScript .
Andrew Larsson
Isso pode ser encurtado usando uma função de setaf=s=>s=='f='+f
Jonathan
2
@ Jonathan sim. Mas em 2013 não podia ...
Denys Séguret 03/10
19

JavaScript ES6, 9 caracteres

Essa é a única maneira (de jogar golfe) em JS. ES6 faz com que seja necessário menos caracteres

Execute isso no console da Web mais recente do Firefox:

f=x=>f==x

Exemplo de uso:

f("check") // returns false
f("x=>f==x") // returns true
Optimizer
fonte
11
@phinotpi - Minha inscrição ainda está qualificada para ser escolhida como resposta?
Optimizer
6
No entanto, pode-se argumentar que a fonte nesse caso é f=x=>f==xe não x=>f==x, enquanto a versão de Denys Séguret realmente verifica a fonte inteira.
Hankrecords
@Hankrecords Deixe o JavaScript decidir isso. f=x=>f==x function f() f.toSource() "x=>f==x"(basicamente avaliar o código no console e, em seguida, avaliar f.toSource()em um browser que suporte esse método.
Optimizer
Funções anônimas não são permitidas (reduza o seu código para x=>f==x) EDIT: deixa pra lá, f é referenciado dentro da função
MilkyWay90
9

Haskell, 72 caracteres

main=interact$show.(==s++show s);s="main=interact$show.(==s++show s);s="

Nota: não há caracteres de fim de linha no final do script.

$ runhaskell Self.hs < Self.hs
True
hammar
fonte
8

GolfScript, 11 caracteres

{`".~"+=}.~

Sem o =, esse código seria um quine que gera seu próprio código-fonte como uma string. O =torna comparar esta cadeia para a sua entrada e saída 1se eles combinam e 0se não o fizerem. Observe que a comparação é exata - em particular, uma nova linha final no final da entrada fará com que ela falhe.

Explicação:

  • { } é um literal de bloco de código no GolfScript;
  • .duplica esse bloco de código e ~executa a segunda cópia (deixando a primeira na pilha);
  • `especifica o bloco de código e ".~"+ anexa .~a ele;
  • finalmente, =compara a sequência resultante com a entrada (que é empurrada na pilha como uma sequência pelo intérprete GolfScript antes do início do programa) e retorna 1se elas coincidem e 0se não coincidem .
Ilmari Karonen
fonte
7

Perl, Infinito 41 38 Personagens

$_=q(print<>eq"\$_=q($_);eval"|0);eval

Atualização: o programa não termina mais com uma nova linha, o que significa que funcionará corretamente em arquivos com várias linhas. Você deve inserir a entrada de STDIN sem pressionar Enter. No Windows, eu era capaz de fazer isso apenas lendo um arquivo.

Solução original:

print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(print<>==q(...

fonte
11
Bem feito! . . .
turba
Falhar para um arquivo que começa com o código, por exemplo(cat id.pl; echo foo)|perl id.pl
Geoff Reedy
@GeoffReedy, obrigado; o programa não tratou da entrada de várias linhas antes. Está corrigido agora.
Droga, esse código é boliche?
Matthew Roh
7

> <> , 68 bytes

Os peixes adoram comer cocô de peixe. Agora sabemos que eles podem distinguir os deles dos amigos.

00v      0+1~$^?)0~\;n0\
  >:@@:@gi:0(?\:a=?/=?!/$1+
  0n;n*=f$=2~~/

Você pode experimentá-lo online !

Aaron
fonte
11
Isso gera 1para qualquer prefixo do código também
Jo King
@JoKing foi pior do que apenas prefixos do script, ele também aceitou linhas truncadas! Eu o corrigi, mas estou desapontado por não ser tão genérico quanto queria, tive que verificar a célula atingida no final do script para garantir que o código inteiro fosse correspondido. Certamente pode ser melhorado, mas não tenho certeza se vou me preocupar.
Aaron
6

Python 2, 55

a='a=%r;print a%%a==raw_input()';print a%a==raw_input()

Testado:

a='a=%r;print a%%a==raw_input()';print a%a==raw_input() -> True

(anything else) -> False

flornquake
fonte
3
Falha em qualquer arquivo que comece com a primeira linha igual a a='a=%r;print a%%a==raw_input()';print a%a==raw_input().
usar o seguinte comando
Verdadeiro, a entrada de várias linhas não é suportada.
Flornquake
Uma correção trivial seria substituir raw_input()por __import__('sys').stdin.read().
feersum
Estou confuso com a redação do desafio (porque não sou bom com gramática inglesa). Isso é permitido? print raw_input()==open(__file__).read()? Tem apenas 40 bytes, usa sua raw_input()abordagem, mas lê seu código.
Simon
11
@ Simon Isso não é permitido, é uma das brechas padrão para desafios como este. E sim, é isso que significa #Your program must not access any special files, such as the file of its own source code.
PunPun1000 23/02
6

JavaScript ES6, 16 14 bytes

$=_=>_==`$=`+$

Menos dois bytes, graças a Neil.

31 bytes se for necessário receber entrada via prompt.

$=_=>prompt()==`$=${$};$()`;$()

38 bytes, se precisarmos enviar por alerta.

$=_=>alert(prompt()==`$=${$};$()`);$()

Essa é a maneira correta de fazer isso, pois a resposta do Optimizer não aceita todo o código-fonte.

Conor O'Brien
fonte
11
Legal, embora eu apenas escrevesse '$='+$.
4196 Neil
Ah verdade. @Neil
Conor O'Brien
11
Tenho certeza que você precisa do final, ;$()porque a chamada de função faz parte do quine. Isso também significa que você precisará mudar para prompta conta da entrada.
Mama Fun Roll
11
Esse não é o problema. A chamada de função é necessária porque faz parte do quine. Permitir ao usuário chamá-lo como uma função arruinaria a solução.
Mama Fun rolo
11
Tente$=_=>prompt()==`$=${$};$()`;$()
Mama Fun Roll
5

Node.js: 54

function f(){console.log(f+'f()'==process.argv[2])}f()

Você o testará salvando-o em um arquivo f.js(o nome exato não tem importância) e usando

node f.js "test"

(que gera false) ou

node f.js "$(< f.js)"

(que gera true)

Eu também fiz uma versão diferente com base em eval:

eval(f="console.log('eval(f='+JSON.stringify(f)+')'==process.argv[2])")

Agora são 72 caracteres, tentarei encurtar isso quando tiver tempo.

Denys Séguret
fonte
11
@ dan1111 Por quê? Não acessa nenhum arquivo. Eu estava apenas apontando como iniciar o programa para pessoas não acostumadas ao node.js. Não lê o arquivo.
Denys Séguret
11
Todas as soluções Javascript aproveitam o fato de que você pode acessar seu próprio código-fonte em JS. Isso pode não estar tecnicamente "acessando o arquivo de seu próprio código-fonte", mas realiza exatamente a mesma coisa. Suponho que sua resposta seja legal, pois a pergunta não proíbe isso especificamente.
Bem, você acessa a fonte de uma função (apenas o corpo para ser preciso) que faz parte do programa. É como usar mixin () em D. Mas eu não acho que as outras duas respostas JS, incluindo uma de mim, realmente se qualifiquem como "programas".
Denys Séguret
@dystroy realmente mixin em D é mais parecido com o uso de eval do que ler fonte
catraca aberração
@ratchetfreak sim, você está certo. Mas acho que seu programa usa um tipo de toString do valor enum, certo? E qualquer código usando eval / mixin é quase o mesmo truque que usar a fonte da função.
Denys Séguret
5

Smalltalk (dialeto Pharo 2.0)

Implemente este método de 41 caracteres em String (formatação feia para code-golf):

isItMe^self=thisContext method sourceCode

Em seguida, avalie isso em um espaço de trabalho (printIt da maneira tradicional de Smalltalk)
A entrada não é lida a partir de stdin, é apenas uma String para a qual enviamos a mensagem (o que mais um programa poderia ter no Smalltalk?):

'isItMe^self=thisContext method sourceCode' isItMe.

Mas estamos enganando, o sourceCode lê algum arquivo de origem ...
Aqui está uma variante com 51 caracteres que não:

isItMe
    ^ self = thisContext method decompileString

E teste com:

'isItMe
    ^ self = thisContext method decompileString' isItMe

Se uma String em uma área de trabalho não for considerada uma entrada válida, vamos ver como usar algumas caixas de diálogo em 116 caracteres . Avalie
esta frase:

(UIManager default request: 'type me') = (thisContext method decompileString withSeparatorsCompacted allButFirst: 7)

Como o formato de descompilação inclui CR e TAB, alteramos isso com SeparadoresCompactos.
Então pulamos os 7 primeiros caracteres 'doIt ^'

Finalmente, uma variante de 105 caracteres usando stdin, apenas interprete esta frase na linha de comando, apenas para se sentir mais mainstream:

Pharo -headless Pharo-2.0.image eval "FileStream stdin nextLine = (thisContext method decompileString withSeparatorsCompacted allButFirst: 7)"
aka.nice
fonte
4

flex - 312 caracteres

Q \"
N \n
S " "
B \\
P "Q{S}{B}{Q}{N}N{S}{B}n{N}S{S}{Q}{S}{Q}{N}B{S}{B}{B}{N}P{S}{Q}{P}{Q}{N}M{S}{Q}{M}{Q}{N}%%{N}{P}{N}{M}{N} putchar('1');"
M "(.|{N})* putchar('0');"
%%
Q{S}{B}{Q}{N}N{S}{B}n{N}S{S}{Q}{S}{Q}{N}B{S}{B}{B}{N}P{S}{Q}{P}{Q}{N}M{S}{Q}{M}{Q}{N}%%{N}{P}{N}{M}{N} putchar('1');
(.|{N})* putchar('0');

Provavelmente pode ser reduzido, mas funciona com entrada de várias linhas (necessária, pois o código fonte é várias linhas) e até mesmo para entradas que contêm o programa como uma substring. Parece que muitas das respostas até agora falham em uma ou em ambas.

Comando de compilação: flex id.l && gcc -lfl lex.yy.c

Geoff Reedy
fonte
3

D (133 caracteres)

enum c=q{import std.stdio;import std.algorithm;void main(){auto i=readln();writeln(equal("auto c=q{"~c~"};mixin(c);",i));}};mixin(c);
catraca arrepiante
fonte
3

JavaScript (V8), 35

function i(){alert(prompt()==i+[])}

ligar i()e solicitará a entrada

Griffin
fonte
A +[]deveria ser opcional como JS irá auto-type cast-lo
Downgoat
3

GolfScript - 26

":@;[34]@+2*=":@;[34]@+2*=

Inspirado em http://esolangs.org/wiki/GolfScript#Examples

Outra versão:

"[34].@@;+2*="[34].@@;+2*=

Pena que \é ao mesmo tempo trocar e escapar ...

aditsu
fonte
3

Python 2, 47 bytes

_='_=%r;print _%%_==input()';print _%_==input()

Uma solução simples com a verificação adicionada.

Rɪᴋᴇʀ
fonte
Isso não funciona. printé uma função é Python 3. Você precisaria fazer print(_%%_==input())';print(_%_==input())ou alterar para Python 2.
Mego
3

CJam , 12 bytes

{s"_~"+q=}_~

Experimente online!

Explicação

Isso apenas usa a estrutura padrão do CJam quine.

{s"_~"+q=}    e# Push this block (function literal).
          _~  e# Copy and run it.

O que o bloco faz:

 s            e# Stringify the top element (this block itself).
  "_~"+       e# Append "_~". Now the source code is on the stack.
       q      e# Read the input.
        =     e# Check if it equals the source code.
Gato de negócios
fonte
Esta é exatamente a solução que eu tive.
Esolanging Fruit 27/03
2

Tcl, 111 caracteres

set c {set c {$c};puts [expr {[read stdin] eq [subst -noc \$c]}]};puts [expr {[read stdin] eq [subst -noc $c]}]
Johannes Kuhn
fonte
2

Perl, 52 caracteres

$_='$/=$\;$_="\$_=\47$_\47;eval";print<>eq$_|0';eval
multidão
fonte
2

Python, 187 bytes

import sys;code="import sys;code=!X!;print(sys.stdin.read()==code.replace(chr(33),chr(34)).replace(!X!,code,1))";print(sys.stdin.read()==code.replace(chr(33),chr(34)).replace("X",code,1))

Cuidado para não adicionar nova linha no final. Alguém com melhor Python-fu pode ser capaz de reduzi-lo.

Emilio
fonte
2
Você pode usar C=chrpara soltar vários bytes. Além disso, reduza o nome da variável code.
Zach Gates
2
Como ninguém disse isso por mais de um ano, Bem-vindo ao PPCG!
Erik the Outgolfer
2

Casca , 11 bytes

=hS+s"=hS+s

Experimente online!

Explicação

A explicação usa ¨para delimitar seqüências de caracteres (para evitar escapamentos ilegíveis):

     "=hS+s  -- string literal: ¨=hS+s¨
  S+         -- join itself with
    s        -- | itself "showed": ¨"=hS+s"¨
             -- : ¨=hS+s"=hS+s"¨
 h           -- init: ¨=hS+s"=hS+s¨
=            -- is the input equal?

Ao remover a função, =você pode verificar se ela realmente corresponderá à própria fonte.

ბიმო
fonte
2

> <> , 24 bytes

'1rd3*i={*}50l3-?.~i)*n;

Experimente online!

Quebrando literalmente a sequência de caracteres, seguido de verificação se a entrada é idêntica à pilha, com uma verificação final de que não há mais entrada.

Brincadeira
fonte
2

Gelatina , 10 bytes

“Ṿ;$⁼”Ṿ;$⁼

Experimente online!

“Ṿ;$⁼”Ṿ;$⁼
“Ṿ;$⁼”      String literal: 'Ṿ;$⁼'
        $   Next two links act on the string literal
      Ṿ     Uneval: '“Ṿ;$⁼”'
       ;    Append string: '“Ṿ;$⁼”Ṿ;$⁼' (source code)
         ⁼  Is the string above equal to the input?
dylnan
fonte
2

05AB1E , 15 bytes

0"D34çýQ"D34çýQ

Modifica o padrão 0"D34çý"D34çýadicionando Q(verifique a igualdade com a entrada implícita)

Experimente online.

Explicação:

0                # Push 0 to the stack
                 #  STACK: [0]
 "D34çýQ"        # Push the string 'D34çýQ' to the stack
                 #  STACK: [0, 'D34çýIå']
         D       # Duplicate this string
                 #  STACK: [0, 'D34çýIå', 'D34çýIå']
          34ç    # Push '"' to the stack
                 #  STACK: [0, 'D34çýIå', 'D34çýIå', '"']
             ý   # Join the stack by this '"' delimiter
                 #  STACK: ['0"D34çýIå"D34çýIå']
              Q  # Check if it's equal to the (implicit) input
                 # (and output the top of the stack implicitly as result)

Legal alternativa de 15 bytes fornecida pelo @Grimy :

187745012D27BJQ

Experimente online.

Explicação:

187745012        # Push integer 187745012 
                 #  STACK: [187745012]
         D       # Duplicate it
                 #  STACK: [187745012, 187745012]
          27     # Push integer 27
                 #  STACK: [187745012, 187745012, 27]
            B    # Convert 187745012 to base-27
                 #  STACK: [187745012, "D27BJQ"]
             J   # Join the values on the stack together
                 #  STACK: ["187745012D27BJQ"]
              Q  # Check if it's equal to the (implicit) input
                 # (and output the top of the stack implicitly as result)
Kevin Cruijssen
fonte
3
187745012D27BJQé um empate.
Grimmy 13/06
1

C - 186 176 caracteres

Um forro:

 *a="*a=%c%s%c,b[999],c[999];main(){sprintf(b,a,34,a,34);gets(c);putchar(strcmp(b,c)?'0':'1');}",b[999],c[999];main(){sprintf(b,a,34,a,34);gets(c);putchar(strcmp(b,c)?'0':'1');}

Com espaço em branco (observe que isso interrompe o programa):

*a="*a=%c%s%c,b[999],c[999];main(){sprintf(b,a,34,a,34);gets(c);putchar(strcmp(b,c)?'0':'1');}",b[999],c[999];
main() {
  sprintf(b,a,34,a,34);
  gets(c);
  putchar(strcmp(b,c)?'0':'1');
}
Josh
fonte
1

q, 8 bytes

{x~.z.s}

Retornar booleano na entrada correspondente ao .zs auto-referencial

Thaufeki
fonte
1

Rúnico , 11 bytes

"3X4+kSqi=@

Experimente online!

O TIO foi atualizado e não há mais um problema de leitura de entrada (e não requer mais um espaço em branco à direita).

Explicação

>                 Implicit entry
 "                Begin reading as string
  3X4+kSqi=@      Pushed to the stack as a string, loop around
 "                End reading as string
  3X4+            Push 3*10 and 4 to the stack, add them together
      k           Convert to character (")
       S          Swap the top two items on the stack
        q         Concatenate. This leaves only "3X4+kSqi=@ on the stack
         i        Read input
          =       Compare using .Equals, push 1 if equal, else 0
           @      Print and terminate

Solução da JoKing:

"'<~qi=@|

Explicação

  <              Entry
 '               Read character (loop around)
"                Push "
         |       Mirror
"                Begin reading string (loop around)
 '<~ri=@|        Push the string '<~qi=@| (loop around)
"                End reading string
 '<~             Push the character < and then discard it
    q            Concatenate, stack contains only "'<~qi=@|
      i          Read input
       =         Compare
        @        Print and terminate
Draco18s
fonte
11
10 bytes
Jo King
@JoKing Muito inteligente.
Draco18s
Na verdade, 9 bytes evitam o rinverso
Jo King
@JoKing Eu provavelmente deveria ter conseguido chegar a esse ponto (da solução de 10 bytes), mas ainda não tive meu cawfee . Eu já havia descoberto ontem que ter a "esquerda é o único lugar para onde realmente pode ir, porque tê-la em outro lugar complica as coisas. (Mas agora eu tinha que executá-lo no meu depurador para ver o que estava fazendo ...)
Draco18s
1

R , 54 bytes

f=function(s)s==paste0("f=function(s)s==", body(f)[3])

Experimente online!

bodyobtém o corpo da função (dividindo-a um pouco, de modo que body(f)[3]é tudo a partir paste0de então). Curiosamente, bodyreformata o código, adicionando espaços após vírgulas, etc. Este é um caso raro de uma resposta de golfe R com um espaço após uma vírgula.

Isso funciona porque body(f)é um objeto do tipo languagee existe um as.charactermétodo para esse tipo. Por outro lado, fe args(f)são do tipo closure, e não podem ser convertidos em tipo de caractere até onde eu sei. Por favor, não me pergunte qual é o tipo de idioma…

Robin Ryder
fonte