盖革计数器


29

盖革计数器是一种用于检测辐射的设备。

我们将制作盖革计数器程序。

众所周知,当辐射撞击计算机程序时,它会随机删除1个字节。因此,Geiger计数器程序是一个本身不执行任何操作的程序,但是当删除任何字节时,修改后的程序将打印beep,以指示存在辐射。

答案将以字节计分,而字节数越少越好。答案必须至少为1个字节。

您的程序可以打印beep尾随换行符,也可以为空输出打印单个换行符,只要它始终如一。你的程序也可以使用不同的情况下beep,例如BEEPbEEP或者Beep只要它这样做一致。



7
我们可以使用BEL控制字符来输出实际的蜂鸣声吗?
Jo King

2
@JoKing我很喜欢这个主意,这很有趣,但是我不得不拒绝。它太不同了。
小麦巫师

2
我想在视网膜中看到一个解决方案。
mbomb007 '18

3
我试图弄清楚如何在SMBF中执行此操作,但是比较两个单元格的唯一方法是更改​​它们。在SMBF中,您需要检查的单元是程序当前正在运行的单元。因此,就像海森堡不确定性原理一样。因此,您必须仅使用控制流来确定是否有任何更改。
mbomb007 '18

Answers:


24

失落303个293 263 253 238 228字节

v^"peeb"<\>"beepvv"((>@@>>%%>>(((((([[[[[[\
>>>>>>>>>//>>>>>>>>>>>>>>/>>/>>>>>>>>>>>>>\\
>>>>>>>>//>>>>\>>>>>>>>>>/>>>>>>>>>>>>>>>>>\\
>/>>>>>>>/>>>>>>>>>>>>\>>>>>>>>>>>>>>>>>>>>>\\
>>>>>>>>>>>>>>>>>>>>>>\\>>>>\>>>>>>>>>>>>>>>>\

在线尝试!

验证脚本(从用户202729的答案借来)。不幸的是,这一次只能测试一半的代码,但是请放心,我已经测试了整个程序。

哎呀,这是一个艰难的过程。我将引用WW的已删除答案:

迷失也许是应对这一挑战最有趣的语言。在“丢失”中,指针的起始位置和方向是完全随机的,因此要进行确定性程序,必须考虑所有可能的起始位置和方向。同时,由于这种挑战的性质,您还必须考虑删除任何单个字节。

不幸的是,他的回答没有考虑到删除换行符,而换行符使一切搞砸了。

说明:

(请注意,一些字节可能到处都是)

首先让我们谈谈代码的一般结构:

v^^"peeb"<<\/"beepvv"((>>>@@>>%%>>(((((([[[[[[[\       Processing line
>>>>>>>>>>>//>>>>>>>>>>>>>>>>>>>/>>>>>>>>>>>>>>\\      Beep line
>>>>>>>>>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\\     Back-up beep line
>//>>>>>>>>>>>>>>>>>>>>\\>>>>>>>>>>>>>>>>>>>>>>>>\\    Back-up return line
>>>>>>>>>>>>>>>>>>>>>>>>\\>>>>>>\>>>>>>>>>>>>>>>>>\    Return line

除处理线以外的所有内容都必须完全由>或其中之一组成\/。为什么?好吧,作为一个例子,让我们删除一个换行符:

v^^"peeb"<<\/"beepvv"((>>>@@>>%%>>(((((([[[[[[[\>>>>>>>>>>>//>>>>>>>>>>>>>>>>>>>/>>>>>>>>>>>>>>\\
>>>>>>>>>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\\
>//>>>>>>>>>>>>>>>>>>>>\\>>>>>>>>>>>>>>>>>>>>>>>>\\
>>>>>>>>>>>>>>>>>>>>>>>>\\>>>>>>\>>>>>>>>>>>>>>>>>\

第一行是现在的方式长于块的其余部分。如果指针在>\/垂直移动的非角色上生成,那么它将陷入无限循环。


辐射探测器最大的部分是每行末端的部分。

 \
 \\
 >\\
 >>\\
 >>>\

通常,从第一行通过此IP的IP将退出最后一行。但是,如果删除了该行上的任何字符,则该行将向下移动一个字符,例如:

 \
 \\
 >\\
 >\\
 >>>\

IP而是退出缺少一个字节的行(最后一行除外,它从倒数第二行退出)。

从那里开始,前四行中的每一行都将重定向到第二行:

v
>>>>>>>>>>
>>>>>>>>//
>/

然后将导致两个错误之一beep

v^"peeb"<<\/"beepvv"((>
>>>>>>>>>>//

如果前一个字节中的任何字节beep已被删除,则转至第二个字节:

v^^"peb"<<\/"beepvv"((>
>>>>>>>>>>>//

beep然后,双方都回到第一行并终止@

其他一些杂项:

(((((([[[[[[[使用时,该指针的一对引号和端部向上推动整个第一行到堆的内部开始清除堆栈。不幸的是,它必须这么长,因为可以删除第一行换行符,以使第一行换成两倍大小。尝试生成beep使用算术而不是引号的结果会花费更长的时间。

通过将指针重定向到正确的行,分散在行中的\s和/s会在代码的第一行中到达高尔夫球字节。由于大多数底线只是填充物,因此只有顶线可以打高尔夫球。如果有人对较短的防辐射堆栈更清晰有任何想法,那么我现在要发表评论。


出于好奇,我在聊天室中发布的部分答案有多有用?我看到了早期版本中的一些相似之处,我想知道自己是否走在正确的轨道上。
小麦巫师

@WW那时我已经在进行此工作,但是通过将推\/键分开beep以及只有一个引号需要退出子句这一事实有所帮助
Jo King

20

六边形,38字节

.....;p;<>b;e;/<b;e;;p...@@.......;@..

在线尝试!

验证程序。


说明

我们在这里利用Hexagony对六角形边长的自动检测。

如果未删除任何字节,则程序的边长为4,如下所示:

程序不删除任何字节

但是,如果删除了一个字节。有2种情况。

  1. 删除的字节在第二个之后<

    执行流程为:

    删除最后一个字节的程序

    @在第5行上有2个连续的,因此,即使其中之一被删除,IP也将安全地命中@

  2. 删除的字节在第二个或第二个之前<

    然后,后半部分将保持不变,并且IP不再通过该地址向上重定向<。执行流程的图像:

    删除第二个<code> << / code>的程序


19

六角34 29字节

//..>;e;<b@;p;/|/;e;;\.b@;p<@

在线尝试! 验证!

说明:

这是使用HexagonyColorer格式化为适当六边形的普通代码:

没有癌症...

//开头的double 可以确保始终采用此路径。如果删除了任何字符,则将@其从路径中删除,或者向后移或自身删除:

癌症!

在这种情况下,我们在后面删除了一个字符|,使其遵循以下路径,打印beep

第一次蜂鸣

如果我们改为从|(或|本身)之前删除一个字符,我们将跟随另一台蜂鸣器:

哔哔声

然后,我们考虑了所有可能性,只beep使用了程序中未辐照的部分。


13

自我修改Brainfuck73 63字节

<<[[[[<<]]>[[.>>..>>.[,>]]]]   bbeepp+[<<<]>>[[>]>>>.>>..>>.,+]

在线尝试! 验证!

代码中间的空格实际上代表NUL字节。

说明:

该代码在中间被3个NUL字节分成两部分。beep如果辐照了另一部分,则基本上都可以打印(有两个例外)。

首先,<<[[开始时要确保所有]s在任何时间都匹配。[旨意不尝试寻找一个匹配],如果该细胞是积极的,而]小号。如果有任何一个]跳回到这些括号中的一个,则通常会立即返回,因为该单元格是0

下一部分,[[<<]]>然后检查第2部分的长度是否均匀。如果是这样,它将执行第1节的另一半,并beep使用bbeepp第2节开头的进行打印。

[[.>>..>>.[,>]]]]

然后清除第2节的所有内容,使其不执行。

在第2节中,我们检查是否部1的长度和NUL字节是整除3+[<<<]>>

[[>]>>>.>>..>>.,+]

同样,我们打印beep


10

Z80Golf53 36 34字节

感谢@Lynn -16个字节感谢@Neil
-2个字节

由于这只是Z80机器码,因此这是很多不可打印的内容,因此有一个- xxd -r可逆的十六进制转储:

00000000: ddb6 2120 10dd b615 280c 003e 62ff 3e65  ..! ....(..>b.>e
00000010: ffff 3e70 ff76 003e 62ff 3e65 ffff 3e70  ..>p.v.>b.>e..>p
00000020: ff76                                     .v

在线尝试!(Python中的详尽测试器)

说明

z80golf是Anarchy Golf假设的Z80机器,其中call $8000是putchar,call $8003是getchar,halt使解释器退出,您的程序放置在$0000,而所有其他内存都填充零。使程序在汇编时防辐射非常困难,但是一种通用的有用技术是使用一个字节的幂等指令。例如,

or c        ; b1    ; a = a | c

只是一个字节,而a | c | c == a | c,因此只需重复执行指令即可使其防辐射。在Z80上,8位立即数是两个字节(其中立即数在第二个字节中),因此您也可以可靠地将某些值加载到寄存器中。这是我最初在程序开始时所做的,因此您可以分析答案底部存储的较长的变体,但后来我意识到有一种更简单的方法。

该程序由两个独立的有效载荷组成,其中一个有效载荷可能已被辐射损坏。我通过检查一些绝对内存地址的值来检查是否删除了一个字节,以及删除的字节是否在有效负载的第二个副本之前。

首先,如果没有观察到辐射,我们需要退出:

    or a, (ix+endbyte) ; dd b6 21 ; a |= memory[ix+0x0021]
    jr nz, midbyte     ; 20 10    ; jump to a halt instruction if not zero

如果删除了任何字节,则所有字节将移位并$0020包含last 76,因此$0021将为零。即使实际上没有冗余,我们也可以负担辐射程序的开始时间:

  • 如果$10消除了跳变偏移,则可以正确检测到辐射,不会发生跳变,并且该偏移也无关紧要。下一条指令的第一个字节将被消耗,但是由于它被设计为可抵抗字节删除,因此这无关紧要。
  • 如果$20删除了跳转操作码,则跳转偏移量$10将解码为djnz $ffe4(将下一个指令字节用作偏移量-参见上文),这是一个循环指令-递减B,如果结果不为零,则跳转。因为ffe4-ffff用零填充(nops),并且程序计数器回绕,所以它将在程序的开头运行256次,然后最终继续。我对此工程感到惊讶。
  • 删除$dd时,片段的其余部分将解码为or (hl) / ld ($1020), hl,然后滑入程序的下一部分。该or不会改变任何重要的寄存器,而且由于HL为零,在这一点上,写也会抵消。
  • 删除$b6将使其余部分解码ld ($1020), ix并按上述步骤进行。
  • 删除$21将使解码器吃掉$20,从而触发djnz行为。

请注意,由于集成了零校验功能,使用or a, (ix+*)节省了两个字节ld a, (**) / and a / and a

现在,我们需要确定要执行的有效负载的两个副本中的哪个:

    or (ix+midbyte)  ; dd b6 15
    jr z, otherimpl  ; 28 0c
    nop              ; 00
    ; first payload
    ld a, 'b'        ; 3e 62
    rst $0038        ; ff
    ld a, 'e'        ; 3e 65
    rst $0038        ; ff
    rst $0038        ; ff
    ld a, 'p'        ; 3e 70
    rst $0038        ; ff
midbyte:
    halt             ; 76
otherimpl:
    nop              ; 00
    ld a, 'b'        ; 3e 62
    ; ...            ; ...
    rst $0038        ; ff
endbyte:
    halt             ; 76

由于使用了相对跳转来在两个副本之间进行选择,因此两个副本之间用nop分隔,并且辐射可能会使程序移位,从而使跳转跳过了目的地之后的第一个字节。另外,nop被编码为零,这使得检测移位字节变得容易。请注意,如果交换机本身已损坏,则选择哪个有效负载都没有关系,因为这样两个副本都是安全的。但是,请确保它不会跳入未初始化的内存:

  • 删除$dd将使接下来的两个字节解码为or (hl) / dec d。ClobbersD。没什么大不了的。
  • 删除$b6将为创建未记录的更长编码dec d。同上。
  • 删除$15将改为读取,$28作为偏移量,然后执行将在处进行$0c,如下所示。
  • $28消失时,$0c解码为inc c。有效负载并不在乎c
  • 删除$0c-这就是nop的目的。否则,将读取有效载荷的第一个字节作为跳转偏移量,并且程序将跳转到未初始化的内存中。

有效负载本身非常简单。我认为字符串的小尺寸使该方法比循环小,并且以这种方式使位置无关更加容易。将ebeep重复的,因此我可以剃去一个ld a。同时,由于之间的所有内存$0038$8000归零,我可以告吹,并使用更短rst的变体call指令,该指令只适用于$0$8$10等等,最多$38

较旧的方法

64字节

00000000: 2e3f 3f2e 3f3f 7e7e a7a7 201f 1e2b 2b1e  .??.??~~.. ..++.
00000010: 2b2b 6b00 7ea7 2814 003e 62cd 0080 3e65  ++k.~.(..>b...>e
00000020: cd00 80cd 0080 3e70 cd00 8076 003e 62cd  ......>p...v.>b.
00000030: 0080 3e65 cd00 80cd 0080 3e70 cd00 8076  ..>e......>p...v

58个字节

00000000: 2e39 392e 3939 7e7e a7a7 2019 3a25 00a7  .99.99~~.. .:%..
00000010: 2814 003e 62cd 0080 3e65 cd00 80cd 0080  (..>b...>e......
00000020: 3e70 cd00 8076 003e 62cd 0080 3e65 cd00  >p...v.>b...>e..
00000030: 80cd 0080 3e70 cd00 8076                 ....>p...v

53个字节

这个在编辑历史中有一个解释,但是并没有太大的区别。

00000000: 3a34 00a7 a720 193a 2000 a728 1400 3e62  :4... .: ..(..>b
00000010: cd00 803e 65cd 0080 cd00 803e 70cd 0080  ...>e......>p...
00000020: 7600 3e62 cd00 803e 65cd 0080 cd00 803e  v.>b...>e......>
00000030: 70cd 0080 76                             p...v

如果发生以下情况,该怎么办:任何非空输出都可以,而不是发出哔声

1个字节

v

halts通常是该程序,但是如果辐射将其删除,则内存将充满零,从而$8000执行无限次,并打印很多空字节。


由于a从零开始,您不能使用or a, (N);代替ld a, (N); and a;吗?看来您可以这样节省几个字节。
尼尔,

@Neil好问题!不幸的是,在Z80上,只有加载指令才能采用这样的地址。
NieDzejkob

gh,距离我进行Z80编程已经太久了……也许我在想or a, (ix + N)
尼尔

@Neil实际上存在,并且IX也从零开始......不幸的是,在该区域中保存一个字节会使字节以这样的方式移位,即20 19开始处的变为20 18,并删除20创建一个无条件的向后跳转,因此在程序中的第一个跳转之后必须添加nop,从而反转字节保存。
NieDzejkob

啊,真可惜。感谢您的检查!
尼尔,


4

Klein,每种拓扑之一,总计291个字节

看到WW的答案后使用该001拓扑,我决定查看为每个拓扑进行盖革计数器的难度。(扰流器:非常难。很难弄清楚没有手势的指针会往哪里走,这使我看起来像是在弄清楚我的左手是哪只手)

验证!

(我还考虑过编写一个在所有拓扑上都是有效的Geiger计数器的程序,但是可能需要等待。如果其他人想尝试,我将提供500 rep赏金)

000和010,21个字节

<<@"peeb"/
.@"peeb"<\

在线尝试000!在线尝试010!

这是从我的><>解决方案移植过来的。这显然适用于000,因为这是大多数2D语言的默认拓扑,但是令我惊讶的是它也适用于010

001和011,26个字节

!.<<@"peeb"/
.@"peeb"..<..

在线尝试001!在线尝试011!

这是直接从WW的答案中复制。谢谢!

100,21字节

//@"peeb"\
@"peeb".</

在线尝试!

101,21字节

//@"peeb"/
@"peeb".<!

在线尝试!

110,26字节

<.<@"peeb"\\
.\@."peeb".\<

在线尝试!

111,24字节

<<@"peeb"<\
...@"peeb"//

在线尝试!

200,21字节

<<@"peeb"\
@"peeb".!/

在线尝试!

201,31字节

\\.\.@"peeb"</./
./...@"peeb"<\

在线尝试!

迄今为止最烦人的。

210,26字节

/\\@"peeb"</\
/@.."peeb"<\

在线尝试!

211,27字节

\\."peeb"((</
!/@@<"peeb"<\

在线尝试!

我必须处理的唯一一个要从右侧进入蜂鸣器的地方。


我会很高兴地获得第二笔赏金。
小麦巫师

3

自修改Brainfuck144个 102字节

无法打印的内容显示为转义序列(例如\x01)。

\xa8<<[[<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[[[.<-]>[>-]\x01qffb\x00\x00beep\x00]]]<[>]<<[>[-<+>]+<<]>[[>]>>[.>]]\x01

验证!


2

符文附魔,29字节

>>yyLL@"peeb"/
     @"peeb"L\

在线尝试!

本质上与Klein 000答案或> <>答案相同(我从Klein答案开始)。真正需要做的唯一更改是<转入L.转入 (命令符号的翻译),插入IP入口点(需要2,否则删除将导致未编译的程序),并插入dela y命令以获取密码。两个IP合并(因此仅打印一个beep),再次需要两个IP 。还需要插入其他NOP以保持线长相同。克莱因还方便地@用于“打印并终止”。

无法利用左下方的空白,因为任何改变方向的反射器都会抑制检测辐射的能力。例如(26个字节,受辐照y):

/yLL@"peeb"/
\<<  @"peeb"L\

由于弯曲的入口部分导致重新反射回到下一行的终结器,因此不输出任何输出。



1

Wumpus37 34 32 31字节

777*7..@ $o&4"beep"|"@peeb"4&o@

在线尝试! 验证!

该解决方案使用以下事实: .一个跳到程序长度的位置模数。

或者对于相同数量的字节


" @o&4"beep"}@
@o&4"beep"}$}  

在线尝试! 验证!

对于奇数和偶数行长,这利用了指针方向的差异。(我真的不知道"删除换行符时第一个的实际工作原理)


1

克莱因(001),26个字节

!.<<@"peeb"/
.@"peeb"..<..

在线尝试!

校验!

说明

该程序利用了Klein独特的拓扑,特别是001拓扑,它是一个Klein瓶。

未经编辑的程序遵循执行路径:

橙色路径

从程序中删除字节可以通过四种方式(每种颜色不同)来影响程序:

程序部分

首先要注意的是,<<始终会在开始时将ip偏向原点的左侧。如果<s中的一个被删除,则另一个替换。因此,如果从红色部分中删除了任何字节,则将遵循以下执行路径:

红色路径

如果删除了蓝色字节,我们将获得非常简单的路径:

在此处输入图片说明

如果删除了换行符,我们将得到以下路径:

绿色之路

黄色路径要复杂一些。由于底行比顶行长,因此在执行开始时对程序进行平方运算时,会将虚拟字符添加到第一行的末尾以使其大小相同。如果删除了第二行上的任何字节,则该行将缩短,并且不会添加该虚拟字符。这很重要,因为!通常会跳过虚拟角色,但是如果没有虚拟角色,它将跳过/

黄径


1
您可以将我的><>解决方案移植00021个字节
Jo King

@JoKing我认为这样做会更好。
小麦巫师

1

反手25 21字节

vv""ppeeeebb""jjHH@

在线尝试! 验证!

这利用了Backhand的功能来更改指针步长值,从而每步都跳过一条指令并巧妙地解决了冗余问题。然后,它使用该j命令通过跳到最后一个字符(@,暂停),然后跳到倒数第二个(H,暂停并输出堆栈),检查代码是否受到照射。

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.