输出源,一次一位


18

编写一个非空程序或函数,当被调用时输出单个值1或0,并且被多次调用时,输出数字将生成程序源代码的二进制表示形式(在编译代码的同一代码页中) /解释)。

例如,如果您的源代码是abc(ASCII),则输出将是:

1st call:  0           // ASCII letter 'a'
2nd call:  1
3rd call:  1
4th call:  0
5th call:  0
6th call:  0
7th call:  0
8th call:  1

9th call:  0           // ASCII letter 'b'
10th call: 1
11th call: 1
12th call: 0
13th call: 0
14th call: 0
15th call: 1
16th call: 0

17th call: 0           // ASCII letter 'c'
18th call: 1
19th call: 1
20th call: 0
21st call: 0
22nd call: 0
23rd call: 1
24th call: 1

After the 24th call, the behaviour is undefined.

源的二进制表示形式必须至少包含一个0位和一个1位。

您可以输出任意两个不同的一致值(例如truefalse),而不是1和0 。

允许输出原始源二进制表示形式的自修改程序,前提是它们不读取源代码以找出下一步要打印的内容。

这是,因此最短的答案以字节为单位。

Answers:


8

时髦47 41 37字节

返回代表一位的数字。

f=_=>1&("%b"%("f="+f)[i//8])>>7-i++%8

使用的quine格式f=_=>"f="+f。它在位置⌊i/8⌋处获取字符,然后通过获取n >> 7-i%8where n是当前字符的ascii值的成对获取位。

这是一个迭代函数,i每次调用都会递增,一旦它超出源代码,它将永远写入代码n

在线尝试!


这是JavaScript的多语言吗?
Stan Strum,

9

Bash,105个字节

trap -- 'trap|xxd -b -c1|cut -d\  -f2|tr -d \\n|cut -c`x=\`cat f||echo 1\`;echo $((x+1))>f;echo $x`' EXIT

注意:确保f要测试的目录中没有重要文件。


如果要对此进行测试,可以使用以下命令:

for i in $(seq 848); do bash path/to/script.sh 2> /dev/null; done | tr -d \\n

哪个应该给出相同的输出xxd -c1 -b path/to/script.sh|cut -d\ -f2|tr -d \\n

说明

这就是trap窍门- traptrap动作内部调用只会打印该行。接下来,输出通过管道传递到xxd该管道,并将其转换为二进制(不幸的xxd -bp是不起作用-因此,使用cut&的变通方法tr):

xxd -c1 -b $0|cut -d\  -f2|tr -d \\n

因此,我们只对N可以使用选择的一位(说)感兴趣cut -cN

要了解N我们正在使用什么(记住那是每次调用后需要增加的部分),只需尝试将其设置x为文件的内容,f如果不存在,则将其设置为1:

x=`cat f||echo 1`

最后要做的是更新文件f-写入文件x+1

echo $((x+1))>f

7

TI-基本(TI-83系列),592个 357 309字节

"123456789ABCDEF02A3132333435363738394142434445463004AA003FB958833404593FB9588338045A3F3230363FDA582B383F303FCE5A405A6B3232333F5A70BB0FAA002BBB0CAA002B5A2B313FB932BA32F01058713459713511BB0FAA002BBB0CAA002B597031377132722B31→Str1
iPart(X/4→Y
iPart(X/8→Z
206
IS>(X,8
0
If Z and Z<223
Z+inString(Str1,sub(Str1,Z,1
iPart(2fPart(2^(X-4Y-5)inString(Str1,sub(Str1,Y+17-2Ans,1

该表是计算器的源代码二进制表示形式的可能参考,尽管最终我只是使用了Virtual TI的调试器。

为了比较和/或具有历史意义:用TI-Basic写的第一个奎因

怎么运行的

Str1存储源代码(现在使用光彩的十六进制,比以前的二进制版本节省了很多空间),而忽略了Str1表示自身内容的位。

我们假设该程序在刚刚清除内存的计算器上开始,所以X也是如此0。每次通过程序,我们都会递增X

通常,我们只是弄清楚我们要从中提取一点的半字节,从中读取出来Str1,从十六进制转换为二进制,然后打印出来。如果我们在存储的源代码中Str1(占程序总长度的三分之二),那么我们首先移至字符串的相应部分,存储3132依此类推。


4

爪哇8,249个 241 237 234 148字节的

int i;v->{String s="int i;v->{String s=%c%s%1$c;return s.format(s,34,s).charAt(-i/8)>>(--i&7)&1;}";return s.format(s,34,s).charAt(-i/8)>>(--i&7)&1;}

抱歉,不便解释。:)

  • @Nevay节省了多达 89个字节。

在这里尝试。

说明:

int i;                     // Index-integer on class-level
v->{                       // Method with empty unused parameter and integer return-type
  String s="int i;v->{String s=%c%s%1$c;return s.format(s,34,s).charAt(-i/8)>>(--i&7)&1;}";
                           //  String containing the unformatted source code
  return s.format(s,34,s)  //    Quine to get the source code,
      .charAt(-i/8)        //     and get the character at index `-i/8`
     >>                    //    And bitwise right-shift it with:
       (--i&7)             //     `i-1` bitwise-AND 7
                           //     by first decreasing `i` by 1 with `--i`
      &1;                  //   Then bitwise-AND everything above with 1
}                          // End of method

附加说明:

-part:

  • String s 包含未格式化的源代码
  • %s 用于将String本身放入 s.format(...)
  • %c%1$c34用于格式化双引号("
  • s.format(s,34,s) 放在一起

在此处尝试一下,删除/修改某些部分,以验证quine输出是其自身的源代码。

部分:


旧的233个字节的答案:

int i;v->{String s="int i;v->{String s=%c%s%1$c;return Long.toString((s.format(s,34,s).charAt(i/8)&255)+256,2).substring(1).charAt(i++%%8);}";return Long.toString((s.format(s,34,s).charAt(i/8)&255)+256,2).substring(1).charAt(i++%8);}

在这里尝试。

说明:

int i;                           // Index-integer on class-level
v->{                             // Method with empty unused parameter and char return-type
  String s="int i;v->{String s=%c%s%1$c;return Long.toString((s.format(s,34,s).charAt(i/8)&255)+256,2).substring(1).charAt(i++%%8);}";
                                 //  String containing the unformatted source code
  return Long.toString(
          (s.format(s,32,s)      //  Quine-formatting
          .charAt(i/8)           //  Take the current character
           &255)+256,2).substring(1)
                                 //  Convert it to an 8-bit binary-String 
         .charAt(i++%8);         //  And return the bit at index `i` modulo-8
                                 //  and increase index `i` by 1 afterwards with `i++`
}                                // End of method

附加说明:

-part:

与上述相同的解释,并增加了:

  • %%是模数符号(%)的转义形式

在此处尝试一下,删除/修改某些部分,以验证quine输出是其自身的源代码。

部分:

  • i/8将自动截断整数除法,因此当i为0-7时,它将变为0;如果i是8-15,它将变为1; 等等
  • 因此s.charAt(i/8),将源代码的当前字符彼此相隔八次。在此处尝试使用修改后的版本。
  • 2550xFF11111111(无符号字节的最大值)
  • 2560x100100000000
  • &ASCII字符转换为整数。那时,它介于02550000000011111111)之间。
  • Long.toString(...,2) 将其转换为9位二进制String表示形式
  • +256.substring(1)确保前导零,并将9位转换为8位。

在此处尝试一下,删除/修改某些部分以验证整个字节。


1
149个字节:int i;v->{String s="int i;v->{String s=%c%s%1$c;return 1&s.format(s,34,s).charAt(-i/8)>>(--i&7);}";return 1&s.format(s,34,s).charAt(-i/8)>>(--i&7);}
Nevay

@Nevay节省了88个字节。谢谢!由于实际上它与我原来的方法大不相同,因此我保留了旧答案,并添加了新答案。(如果您希望我再次删除它,可以自己发布,但是您以前告诉我,您更喜欢高尔夫别人的-主要是我的
XD-

2

JavaScript的ES6,73个 58 52字节

o=_=>`o=${o}`.charCodeAt((o.n=1+o.n|0)/8)>>(7-o.n%8)&1

说明

代码明细:

  • o=_=>:定义一个函数。
  • `o=${o}`:构造一个字符串;o被转换为字符串,在这种情况下为函数的源代码。
  • .charCodeAt(:获取字符串中的一个字符作为其ASCII字符代码。
  • (o.n=1+o.n|0)/8:选择一个字符。这也是计数器递增的地方。
  • )>>(7-o.n%8):移动结果字符代码,以便所需的位在正确的位置。
  • &1:将所有其他位设置为0。

您可以使用lambda将其缩短为o=_=>(o+'').charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco,2017年

这算作定义函数。
ATaco

1
试试o=_=>('o='+o).charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco

取而代之的是,'n'in top?++n:n=0您不能使用++n||(n=0)++n?n:n=0n=++n||0n=1+n||0两者都利用虚假NaN递增的方法undefined
Bergi

1
o=_=>('o='+o).charCodeAt((o.n=1+o.n|0)/8)>>(~o.n&7)&1
tsh

2

q / kdb +,45字节

解:

a:-1;f:{((,/)0b vs'4h$"a:-1;f:",($).z.s)a+:1}

例:

q)f[] / call function f with no parameters
0b   
q)f[]
1b   
q)f[]
1b   
q)f[]
0b   
q)f[]
0b   
q)f[]
0b   
q)f[]
0b   
q)f[]
1b   
q)f[]  
q)"c"$0b sv 01100001b / join back to a byte and cast to a character
"a"

说明:

我听得很简短。

首先设置a起始值为的全局变量-1。Function f构建以垃圾开头的函数的字符串表示形式(包括在内的所有内容{})的二进制表示形式a:-1;f:,并在索引a处索引此二进制列表(每次调用递增)。

a:-1;f:{(raze 0b vs'4h$"a:-1;f:",string .z.s)a+:1} / ungolfed solution
a:-1;                                              / stick -1 in variable a
     f:{                                         } / define function f
                                             a+:1  / increment a by 1 (:: is required as a is a global variable), indexes into the left
        (                                   )      / do all this together
                                 string .z.s       / z.s is the function, string converts it to a string
                       "a:-1;f:",                  / prepend "a:-1;f:" to the start
                    4h$                            / cast to bytes
              0b vs'                               / convert each byte to binary
         raze                                      / flatten binary into long list

2

Python 2,164字节

lambda s='lambda s=%r,i=[]:i.append(1)or"{:08b}".format(ord((s%%s)[~-len(i)/8]))[~-len(i)%%8]',i=[]:i.append(1)or"{:08b}".format(ord((s%s)[~-len(i)/8]))[~-len(i)%8]

在线尝试!

说明

让我们从一个标准的Python 2 quine开始。

s = '...'; print s % s

好的,这就是这样输出的。我们需要二进制!

s = '...'; print "\n".join("\n".join("{:08b}".format(ord(i))) for i in s % s)

是的,这只是将所有内容转换为二进制。但是标题说“一次一点”。我们需要一些东西可以多次运行。我知道,让我们使其具有功能!

lambda s = '...': "\n".join("\n".join("{:08b}".format(ord(i))) for i in s % s)

等等,这无济于事...嗯,我们如何跟踪需要输出的位的索引?哦,哦,让我们有一个整数来跟踪。

lambda s = '...', i = 0: "{:08b}".format(ord((s % s)[i / 8]))[i % 8]

嗯...总是输出第一位。哦,我们需要增加跟踪器!糟糕,Python不允许将整数作为默认参数进行修改。而且赋值不是Python中的表达式,因此您不能在lambda中实现。Welp,在Python中是不可能的,大小写已关闭。

...嗯,不完全是。Python 确实允许将列表作为默认参数进行修改。(而且它一直困扰着Python程序员。)让我们使用它的长度!

lambda s = '...', i = []: "{:08b}".format(ord((s % s)[len(i) / 8]))[len(i) % 8]

但这仍然不能修改跟踪器...我们可以在跟踪器上添加一些内容以增加其长度...但是如何?啊,嗯,我们有list.appendlst.append(1)等同于lst += [1]。大!

lambda s = '...', i = []: i.append(1) and "{:08b}".format(ord((s % s)[len(i) / 8]))[len(i) % 8]

糟糕,这会跳过第一位,因为在输出该位之前,跟踪器的长度为1。我们需要减少使用它的长度。

lambda s = '...', i = []: i.append(1) and "{:08b}".format(ord((s % s)[(len(i) - 1) / 8]))[(len(i) - 1) % 8]

在那里,伙计们!打高尔夫,你有我的解决方案!


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.