编写最短的自我识别程序(quine变体)


57

编写一个程序,如果输入与程序的源代码匹配,则生成一个“ true”输出;如果输入与程序的源代码不匹配,则生成一个“ false”输出。

可以将这个问题描述为与quines有关,因为程序必须能够以某种方式在该过程中计算其自己的源代码。

这是代码高尔夫球:适用标准规则。您的程序不得访问任何特殊文件,例如其自身源代码的文件。

编辑:如果您选择,则可以将True / False替换为True / False或1/0。

如果您的程序的源代码是bhiofvewoibh46948732));:/)4,则您的程序必须执行以下操作:

输入(标准输入)

bhiofvewoibh46948732));:/)4

输出(标准输出)

true

输入项

(Anything other than your source code)

输出量

false

7
true/ false输出强烈的要求,或者是变化(True/ False1/ 0)上可接受的呢?
Cristian Lupascu 2013年

如果程序输出的结果比true / false多一点(如果它始终是模棱两可并以true / false结尾),这是一个问题吗?
DenysSéguret13年


5
所以您的意思是自恋程序?
PyRulez

Answers:



19

JavaScript ES6,9个字符

这是在JS中执行此操作的唯一方法。ES6只需占用很少的字符

在最新的Firefox的Web控制台中运行此命令:

f=x=>f==x

用法示例:

f("check") // returns false
f("x=>f==x") // returns true

1
@phinotpi-我的条目是否仍有资格被选为答案?
Optimizer

6
可以争论的是,在这种情况下,源f=x=>f==x不是x=>f==x,而DenysSéguret的版本确实检查了整个源。
Hankrecords

@Hankrecords让JavaScript决定。 f=x=>f==x function f() f.toSource() "x=>f==x"(基本上评价控制台代码,然后评价f.toSource()在支持该方法的浏览器。
优化

不允许使用匿名函数(将代码缩短为x=>f==x)编辑:没关系,f在函数内部被引用
MilkyWay90

9

Haskell,72个字符

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

注意:脚本末尾没有行尾字符。

$ runhaskell Self.hs < Self.hs
True

8

GolfScript,11个字符

{`".~"+=}.~

没有=,此代码将是一个将其自身的源代码生成为字符串的quine。将=使它比较这字符串输入和输出1,如果他们匹配,并且0如果他们不这样做。请注意,比较是精确的-特别是,输入末尾的换行符将导致它失败。

说明:

  • { } 是GolfScript中的代码块文字;
  • .复制此代码块,并~执行第二个副本(将第一个副本保留在堆栈中);
  • `对代码块进行字符串化,并在其后加上".~"+ .~
  • 最后,=将结果字符串与输入进行比较(在程序启动之前,GolfScript解释器将其作为字符串推送到堆栈中),并返回1它们是否匹配0

7

Perl,Infinity 41 38个字符

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

更新:该程序不再以换行符结尾,这意味着它将在多行文件上正常运行。您必须输入来自STDIN的输入,而无需按Enter。在Windows上,我只能通过读取文件来执行此操作。

原始解决方案:

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(...

1
做得很好!。。。
暴徒

无法找到以代码开头的文件,例如(cat id.pl; echo foo)|perl id.pl
Geoff Reedy 2013年

@GeoffReedy,谢谢;该程序之前未处理多行输入。现在已更正。

该死,这是代码保龄球吗?
马修·卢

7

> <>,68个字节

鱼喜欢吃鱼便。现在我们知道他们可以与朋友区分开来。

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

您可以在线尝试


1
1也会输出代码的任何前缀
Jo King

@JoKing比脚本的前缀还糟糕,它也接受了截断的行!我已经修复了它,但令我失望的是它不像我希望的那样通用,我不得不在脚本末尾检查到达的单元格以确保整个代码都匹配。当然可以改进,但是我不确定我会打扰。
亚伦

6

Python 2,55

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

经测试:

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

(anything else) -> False


3
以第一行开头的任何文件失败a='a=%r;print a%%a==raw_input()';print a%a==raw_input()
standby

不支持真实的多行输入。
flornquake 2013年

一个简单的解决方法是将替换raw_input()__import__('sys').stdin.read()
feersum'2

我对挑战性措词感到困惑(因为我对英语语法不好)。可以吗?print raw_input()==open(__file__).read()?它只有40个字节,使用您的raw_input()方法,但会读取其代码。
西蒙

1
@Simon这是不允许的,它是此类挑战的标准漏洞之一。是的,这是什么意思Your program must not access any special files, such as the file of its own source code.
PunPun1000

6

JavaScript ES6,16 14字节

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

减去两个字节,多亏了尼尔。

如果必须通过提示符输入,则为31个字节。

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

如果必须通过警报输出,则为38个字节。

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

这是正确的方法,因为Optimizer的答案不能接受整个源代码。


1
尼斯,虽然我只是写'$='+$
尼尔

哦,是的。@Neil
Conor O'Brien

1
我很确定您需要结尾,;$()因为函数调用是quine的一部分。这也意味着您需要切换prompt到帐户进行输入。
Mama Fun Roll

1
那不是问题。该函数调用是必需的,因为它是quine的一部分。允许用户将其作为函数调用会破坏奎因。
妈妈趣味卷

1
试试$=_=>prompt()==`$=${$};$()`;$()
Mama Fun Roll

5

Node.js:54

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

您可以通过将其保存到文件f.js(确切的名称无关紧要)并使用

node f.js "test"

(输出假)或

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

(输出为true)

我还根据eval做了一个不同的版本:

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

现在是72个字符,如果有时间,我会尽量缩短。


1
@ dan1111为什么?它不访问任何文件。我只是向不熟悉node.js的人指出了如何启动该程序。它不会读取文件。
DenysSéguret13年

1
所有Javascript解决方案都利用了您可以在JS中访问自己的源代码这一事实。从技术上讲,这可能不是“访问其自身源代码的文件 ”,但它可以实现完全相同的功能。不过,我认为您的回答是合法的,因为该问题并未明确禁止这样做。

好吧,您可以访问程序的一部分函数的源代码(准确地说,仅是主体)。就像在D中使用mixin()一样。但是,我不认为其他两个JS答案(包括我自己的一个答案)真的符合“程序”的资格。
DenysSéguret13年

@dystroy实际上在D中的mixin更像是使用eval而不是阅读源代码
棘手怪胎

@ratchetfreak是的,你是对的。但是我认为您的程序使用一种枚举值的toString,对吗?而且,使用eval / mixin的任何代码与使用函数源的技巧大致相同。
DenysSéguret13年

5

Smalltalk(Pharo 2.0方言)

在String中实现此41个 chars方法(代码高尔夫球的格式很丑):

isItMe^self=thisContext method sourceCode

然后在工作区中对此进行评估(使用传统的Smalltalk方法printIt)
,不从stdin读取输入,它只是我们向其发送消息的字符串(Smalltalk中还有什么程序?):

'isItMe^self=thisContext method sourceCode' isItMe.

但是我们在作弊,sourceCode读取了一些源文件...
这是一个带有51个字符的变体,但没有:

isItMe
    ^ self = thisContext method decompileString

并测试:

'isItMe
    ^ self = thisContext method decompileString' isItMe

如果在工作区中的字符串不被视为一个有效的输入,那么让我们来看看如何使用一些对话框,在116个字符
就评价这句话:

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

由于反编译格式包括CR和TAB,因此我们使用SeparatorsCompacted对其进行更改。
然后,我们跳过前7个字符为“ doIt ^”

最后,使用stdin 的105个字符的变体,只是从命令行解释了这句话,只是觉得更加主流:

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

4

flex-312个字符

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');

可以使它更短一些,但是它适用于多行输入(由于源代码是多行,因此是必需的),甚至适用于包含程序作为子字符串的输入。到目前为止,似乎很多答案都无法解决其中一个或两个问题。

编译命令: flex id.l && gcc -lfl lex.yy.c


3

D(133个字符)

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);

3

JavaScript(V8),35

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

呼叫i(),它将提示输入


+[]应是可选的,因为JS会自动型投它
Downgoat


3

Python 2,47个字节

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

添加了支票的简单奎因。


这行不通。print是一个功能是Python 3的你需要做的print(_%%_==input())';print(_%_==input()),或者改变到Python 2
美高

3

CJam,12个字节

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

在线尝试!

说明

这仅使用标准的CJam quine框架。

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

该块的作用是:

 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.

这正是我的._解决方案。
Esolanging Fruit

2

Tcl,111个字符

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

2

Perl,52个字符

$_='$/=$\;$_="\$_=\47$_\47;eval";print<>eq$_|0';eval

2

Python,187个字节

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))

注意不要在末尾添加换行符。拥有更好的Python-fu的人也许可以缩短它。


2
您可以C=chr用来删除几个字节。另外,缩短变量名code
扎克·盖茨

2
既然没有人说了一年多,欢迎来到PPCG!
暴民埃里克(Erik the Outgolfer)

2

外壳,11个字节

=hS+s"=hS+s

在线尝试!

说明

该解释用于¨分隔字符串(以避免不可读的转义):

     "=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?

通过删除该函数,=您可以验证它确实仅与源本身匹配。


2

> <>,24个字节

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

在线尝试!

包装字符串文字,然后检查输入是否与堆栈相同,最后检查是否没有更多输入。


2

果冻,10字节

“Ṿ;$⁼”Ṿ;$⁼

在线尝试!

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

2

05AB1E,15 个字节

0"D34çýQ"D34çýQ

通过添加来修改默认 (检查与隐式输入的相等性)0"D34çý"D34çýQ

在线尝试。

说明:

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)

@Grimy提供的凉爽的15 个字节替代:

187745012D27BJQ

在线尝试。

说明:

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)

3
187745012D27BJQ是领带。
Grimy

1

C- 186176个字符

一班轮:

 *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');}

使用空格(请注意,这会破坏程序):

*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');
}




1

符文,11字节

"3X4+kSqi=@

在线尝试!

TIO已更新,读取输入不再有问题(并且不再需要尾随空格)。

说明

>                 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

JoKing的解决方案:

"'<~qi=@|

说明

  <              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


@JoKing非常聪明。
Draco18s

事实上,9个字节避免rEVERSE
乔金

@JoKing我大概应该可以从10字节的解决方案中自己做到这一点,但是我还没有拿到杯咖啡。昨天我已经得出结论,"在左边只有它才是真正可以去的唯一地方,因为在其他地方放置它会使事情复杂化。(但是现在我不得不在调试器中运行它,以查看它在做什么……)
Draco18s

1

R,54个字节

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

在线尝试!

body获取函数的主体(将其拆分一下,以便body(f)[3]从头paste0开始)。有趣的是,body重新格式化代码,在逗号后添加空格等。因此,这是R golf答案中逗号后带有空格的罕见情况。

这是有效的,因为body(f)是类型的对象language,并且存在as.character用于该类型的方法。另一方面,fand args(f)是type closure,据我所知不能将其转换为字符类型。请不要问我语言类型是什么……


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.