编写输出其镜像级别的程序


31

有95个可打印的ASCII字符:

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Consolas字体(默认为Stack Exchange代码块)中,某些字符在垂直对称轴周围具有镜像:

  • 这些字符对是彼此的镜像: () [] {} <> /\
  • 这些字符是它们自身的镜像:(! "'*+-.8:=AHIMOTUVWXY^_ovwx|请注意空格是一个。)
  • 这些没有镜子: #$%&,012345679;?@BCDEFGJKLNPQRSZ`abcdefghijklmnpqrstuyz~

il0#,,可能其他字符都是自己的镜子一些字体,但我们会坚持到索拉的形状。)

如果仅用39个镜像字符制成字符串,则该字符串就是其自身的镜像,其排列方式使该字符串具有中心垂直对称线。所以](A--A)[是自身的镜子,但](A--A(]并非如此。

编写一个单行的偶数程序,该程序是其自身的镜像。当它的左半部分的N个副本已被添加到它的前面,并且已将其右半部分的N个副本添加到它的后面时,它应输出N + 1。N是一个非负整数。

例如,如果程序为](A--A)[(左半部分:](A-,右半部分:)-A)[,则:

  • 运行](A--A)[应该输出1。(N = 0)
  • 运行](A-](A--A)[-A)[应该输出2。(N = 1)
  • 运行](A-](A-](A--A)[-A)[-A)[应该输出3。(N = 2)
  • 运行](A-](A-](A-](A--A)[-A)[-A)[-A)[应该输出4。(N = 3)
  • 。。。
  • 运行](A-](A-](A-](A-](A-](A-](A-](A-](A-](A--A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[应该输出10。(N = 9)
  • 等等

规则

  • 输出到标准输出或您的语言最接近的替代产品。可能会有一个可选的尾随换行符。请勿输入任何内容。
  • 在给定足够的内存和计算能力的情况下,该过程理论上应适用于N达2 15 -1或更高。
  • 需要完整的程序,而不仅仅是REPL命令。

最短的初始程序(N = 0,以字节为单位)获胜。


在某些字体中,#它也是自己的选择,但是,您是对的,而不是在consolas中。
SuperJedi224

1
允许使用repls吗?换句话说:我们应该编写一个完整的有效程序还是一个表达式就足够了?我正在考虑在ghci中运行时可以运行的Haskell条目,但它不是有效的完整程序。
2015年

@Bakuriu需要完整的程序。Haskell答案无效。
加尔文的爱好2015年

4
为什么“ b”和“ d”镜不是彼此的?这使我的计划无法实现:P
Thijs ter Haar

1
@ThijsterHaar我实际上没有考虑过,但是看起来他们的Consolas形状略有不同,对不起:P
卡尔文的爱好2015年

Answers:


20

点,12 8 4字节

现在减少了66%的字节!

x++x
  • x是一个变量,已预先初始化为""。在数字上下文中,变为0
  • 上半部(不含决赛)+表达了这种形式x+x+...+x。这是不执行任何操作的有效语句。
  • 后半部分(包括上半部分的最后+部分)表达了形式++x+x+...+x++x递增x1,其余的将其添加到自身N次。由于表达式是在Pip中从左到右求值的,因此可以保证增量首先发生,并且结果等于镜像级别的数量。
  • 最后,该表达式的值将自动打印。

不幸的是,Pip处理巨大的表达式效果不佳:此解决方案会导致maximum recursion depth exceededN大于500时出现错误。这是以前的解决方案,长度为8个字节

x++oo++x

更多关于点子


好的,除非有人发布了一个2字节的答案,否则好像您已经把这个装在袋子里了。顺便说一句,我不知道您是否使用N = 32767运行它,但是实际输出是Fatal error: maximum recursion depth exceeded while calling a Python object
丹尼斯

@Dennis是的,实际上我遇到了-它开始得很早,大约600之前就开始了。原因是首先通过对所有子表达式进行递归求值来对表达式求值,从而x+x+...+x生成O(N)递归深度。也许这使答案无效。我会加一个便条。
DLosc

递归限制可以在Python中轻松调整,不是吗?
丹尼斯

@Dennis是的,尽管如果设置得太高,它会对系统产生严重的警告,所以我从未尝试过。;)此外,无法在Pip中进行配置,因此对我来说似乎有点作弊。但是,如果您想尝试一下,我会对听到结果感兴趣。
DLosc

我试过了。在我的机器上,将递归限制增加到20000已经存在段错误。但是由于答案只有在足够的内存和计算能力的情况下才能起作用,所以这不是问题。
丹尼斯

34

GolfScript,10个字节

!:{)::(}:!

使用Web Golfscript在线尝试:N = 0N = 1N = 2N = 3N = 41

Web GolfScript的字符数限制为1024,但是Ruby解释器完美地处理了N = 32767

$ curl -Ss http://www.golfscript.com/golfscript/golfscript.rb > golfscript.rb
$ echo '"!:{):"32768*":(}:!"32768*' | ruby golfscript.rb > mirror-level-32767.gs
$ ruby golfscript.rb mirror-level-32767.gs
32768

怎么运行的

没有任何输入,GolfScript最初在堆栈上有一个空字符串。

在左上半部分,发生以下情况:

  • !将逻辑NOT应用于空字符串。这推1

  • :{将整数保存在变量中的堆栈中{

    是的,尽管没有办法检索存储的值,但这是一个有效的标识符。

  • ) 在堆栈上增加整数。

  • : 是不完整的说明。

随后的左半部分,发生以下情况:

  • :!:之前的剩余数)将整数保存在变量中的堆栈中!

    是的,这也是一个有效的标识符。这会中断该!命令,但我们不再使用它。

  • :{):像以前一样工作。

在右上半部分,发生以下情况:

  • :::之前的剩余数)将整数保存在变量中的堆栈中:

    是的,即使那是有效的标识符。与一样{,无法检索存储的值。

  • ( 递减堆栈上的整数,得到左半部分的数量。

  • },因为它不匹配并立即终止执行。

    这是一个未记录的功能。我称它们为超赞

其余代码将被忽略。


}在镜像竞争中,在代码的第二部分中拥有无与伦比的东西似乎很奇怪。
ballesta25

这是回文式变体中的常见技巧。在中"\""/",由于第二个引号已转义,因此第四个双引号也将不匹配。
丹尼斯

27

Z80机器码,8 6字节*

<8ww8> *通过从Amstrad BASIC输入来假设某些条件

<   INC A         // A=A+1
8w  JR C, #77     ## C is unset unless A has overflowed, does nothing

w   LD (HL), A    // Saves A to memory location in HL (randomly initialised)
8>  JR C, #3E     ## C is still unset, does nothing

A从BASIC输入时最初为0。它递增A n次,然后将n次写入相同的内存位置(BASIC将其设置为稍微随机的位置)!将JR跳转相对操作从来不做事,因为C标志是始终没有设置,所以用来“注释掉”后面的字节!通过假定某些输入条件(即从BASIC保证A始终为0),此版本略有作弊。(HL)不能保证的位置是安全的,实际上,这可能是危险的位置。下面的代码更加健壮,这就是为什么它更长的原因。

Z80机器码,30个字节

作为ASCII: o!.ww.!>A=o>{))((}<o=A<!.ww.!o

基本上,前半部分保证创建一个零值,后半部分将其递增并将其写入内存。在下面的扩展版本中,##表示在镜子的一半没有作用的代码。

o   LD L, A       ## 
!.w LD HL, #772E  // Load specific address to not corrupt random memory!
w   LD (HL), A    ## Save random contents of A to memory
.!  LD L, #21     ## 
>A  LD A, #41     // A=#41
=   DEC A         // A=#40
o   LD L, A       // L=#40
>{  LD A, #7B     ## 
)   ADD HL, HL    // HL=#EE80
)   ADD HL, HL    // HL=#DD00. L=#00 at this point

((  JR Z, #28     ## 
}   LD A, L       // A=L
<   INC A         // A=L+1
o   LD L, A       // L=L+1
=   DEC A         // A=L
A   LD B, C       ## 
<   INC A         // A=L+1
!.w LD HL, #772E  // Load address back into HL
w   LD (HL), A    // Save contents of A to memory
.!  LD L, #21     ## 
o   LD L, A       // L=A

允许的指令明细:

n   op    description
--  ----  -----------
28  LD    LoaD 8-bit or 16-bit register
3   DEC   DECrement 8-bit or 16-bit register
1   INC   INCrement 8-bit or 16-bit register
1   ADD   ADD 8-bit or 16-bit register

Available but useless instructions:
3   JR    Jump Relative to signed 8-bit offset
1   DAA   Decimal Adjust Accumulator (treats the A register as two decimal digits
          instead of two hexadecimal digits and adjusts it if necessary)
1   CPL   1s ComPLement A
1   HALT  HALT the CPU until an interrupt is received

在允许的39条指令中,有28条是装载操作(从0x40到0x7F的块都是单字节LD指令),大多数操作在这里没有帮助!仍然唯一允许加载到内存的指令是LD (HL), A,这意味着我必须将值存储在中A。由于这是A剩下的唯一一条带有允许INC指令的寄存器,因此实际上非常方便!

我不能A以0x00开头,因为ASCII 0x00是不允许的字符!所有可用值均远离0,并且所有数学和逻辑指令均被禁止!除了...我仍然可以做ADD HL, HL,将16位HL本身添加!除了直接加载值(此处不使用!),INCrementing A和DECrementing之外AL否则HL这是我更改寄存器值的唯一方法!实际上,有一个专门的指令在上半年可能会有所帮助,但在下半年会遇到麻烦,而补码的指令在这里几乎没有用,只会占用空间。

因此,我找到了最接近0的值:0x41。那怎么接近0?二进制为0x01000001。因此,我将其递减,将其加载L并执行ADD HL, HL两次!L现在为零,我将其载入A!不幸的是,的ASCII码ADD HL, HL是,)所以我现在需要使用(两次。幸运的是,(JR Z, ee下一个字节在哪里。因此它吞噬了第二个字节,我只需要通过小心Z标志来确保它不会做任何事情!影响Z标志的最后一条指令是DEC A(反直觉地,ADD HL, HL不更改它),由于我知道A那时候是0x40,因此可以保证Z未设置该标志。

下半部的第一条指令JR Z, #28在前255次中将不执行任何操作,因为仅当A从255溢出到0时才可以设置Z标志。此后输出将是错误的,但是由于无论如何它仅保存8位值没关系。该代码不应扩展超过255次。

由于不允许使用所有干净返回的方法,因此必须将代码作为摘要执行。所有的RETurn指令都在0x80以上,并且允许的几个跳转操作只能跳转到正偏移量,因为所有8位负值也都被禁止!


6
什么。这是什么。
cloudfeet

4
现在,我已经使用GolfScript / J / etc看到了这个答案。好像在作弊。:p
cloudfeet

是否有带有16位A寄存器的Z80兼容处理器?我问,因为这个问题要求代码必须适用于N = 32767
丹尼斯

1
@Dennis若要使程序工作于N = 32767,它的长度必须至少为2 x 3276765534字节。Z80只能寻址65536字节的内存,这使这成为不可能完成的任务,因为我不相信我可以使程序小于6字节!的A寄存器总是8位,否则所述处理器将不与Z80兼容。我要说的是,这里已经涵盖了足够的内存和计算能力
CJ丹尼斯

1
@Dennis您了解为什么没有Z80兼容处理器会拥有A8位以外的寄存器吗?例如,将其更改为16位将破坏依赖 255 + 1 = 0的代码。您将必须发明一个CPU,将其称为Z160,它使用默认的16位寄存器,但仍使用与Z80相同的8位指令集。奇怪的!
CJ丹尼斯

19

J,16 14字节

(_=_)]++[(_=_)

用途:

   (_=_)]++[(_=_)
1
   (_=_)]+(_=_)]++[(_=_)+[(_=_)
2
   (_=_)]+(_=_)]+(_=_)]++[(_=_)+[(_=_)+[(_=_)
3

说明:

  • J从右到左求值。

  • (_=_)inf equals inf,它的值为true,1所以表达式变为1+]...[+1。((8=8)也可以,但是看起来更酷。:))

  • [并分别]返回左参数和右参数(如果有2个参数)。如果他们只得到1,则返回该值。

  • +添加2个参数。如果只得到1,则返回该值。

现在让我们评估一个3级表达式(从右到左):

(_=_)]+(_=_)]++[(_=_)+[(_=_)  NB. (_=_) is 1

1]+1]+1]++[1+[1+[1  NB. unary [, binary +

1]+1]+1]++[1+[2  NB. unary [, binary +

1]+1]+1]++[3  NB. unary [, unary +

1]+1]+1]+3  NB. unary +, binary ]

1]+1]+3  NB. unary +, binary ]

1]+3  NB. unary +, binary ]

3

如我们所见,的的右半部分1被添加,而的的左半部分1被省略,从而得到所需的整数N,即镜像级别。

在这里在线尝试。


12

Haskell,42个字节

(8-8)-(-(8-8)^(8-8))--((8-8)^(8-8)-)-(8-8)

幸运的是,Haskell中的行注释(-> --)是可镜像的,其中一半(-> -)是有效函数。剩下的是一些数学来得到数字01。基本上,我们在每个步骤中都有(0)-(-1)一个注释,N=0(0)-(-1)-放在前面。

如果允许输出浮点数,我们可以18/826个字节开始构建并获得:

Haskell,26个字节

(8-8)-(-8/8)--(8\8-)-(8-8)

输出1.02.0等等。


2
从技术上讲这是无效的,因为它必须是完整程序。
加尔文的爱好2015年

@ Calvin'sHobbies:我知道了。我们对整个课程的最低要求是否达成共识?我已经搜索了meta,但是只发现了有关函数而不是程序的讨论。根据完整程序的定义,我也许可以修复我的解决方案。
nimi 2015年

如果您可以将其保存在文件中program.hs,然后从命令行运行$ runhaskell program.hs并查看输出,则可以将其称为完整程序。我不了解Haskell,所以我无法确切地说出需要更改的内容。
加尔文的爱好2015年

2
@ Calvin'sHobbies:runhaskell是一个Shell脚本,它设置了一些环境并最终调用ghcHaskell编译器。您可以直接与我的代码运行ghcghc -e "(8-8)-(-8/8)--(8\8-)-(8-8)"。这将启动ghc,它评估作为参数提供的代码,打印结果并退出。没有REPL,没有互动。当然,这会使+1的字节数增加+1 -e
nimi 2015年

@nimi:-e在这种情况下对得分没有贡献。我们不计算字节数perl -Egcc -std=c99两者都不计。
丹尼斯

11

CJam,14个字节

]X+:+OooO+:+X[

在CJam解释器中在线尝试:N = 0N = 1N = 2N = 3N = 41

请注意,此代码以错误消息结尾。使用Java解释器,可以通过关闭或重定向STDERR来抑制该错误消息。1个

怎么运行的

在左半部分,发生以下情况:

  • ] 将整个堆栈包装成一个数组。

  • X追加1到该数组。

  • :+ 计算所有数组元素的总和。

  • Oo 打印空数组的内容(即不打印任何内容)。

在右上半部分,发生以下情况:

  • o 在堆栈上打印整数,这是所需的输出。

  • O+ 尝试将空数组追加到堆栈的最顶层。

    但是,堆栈在推入之前是空的O。这将失败并终止程序的执行。

其余代码将被忽略。

1 根据meta民意调查应该允许提交错误退出吗?,这是允许的。


由于出现错误,我会对此表示怀疑,但是由于它没有获奖,所以我不太担心。
加尔文的爱好2015年

考虑到这是一种高尔夫语言,在CJam中很难完成这样的任务。即使未执行的块中出现语法错误(例如,未定义的运算符),也会阻止整个程序执行。我仍在尝试消除错误。
丹尼斯
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.