缩小Brainfuck


22

根据以下规则,您面临的挑战是缩小Brainfuck代码:

  • 删除不属于的任何内容+-><[].,
  • 对于任何一组连续的+-字符,如果量+S和-s是相同的,将其删除。
  • 执行与上述相同的操作,但使用><
  • +-><如果不执行任何操作,请删除字符序列。例如,您应该删除+>-<->+<。(这可能是最棘手和最难实现的。)确保您没有得到任何误报,例如+>-<+>-<,不应删除。

测试用例:

输入项

++++++[->++++++<]>.   prints a $
[-]<                  resets tape
>,[>,]<[.<]           reverses NUL terminated input string
++-->><<              does nothing

输出量

++++++[->++++++<]>.[-],[>,]<[.<]

输入项

Should disappear: ++>>+<+++<->-->-<<->-<
Should disappear: +++>-<--->+<
Should stay: +++>-<+>---<

输出量

+++>-<+>---<

您可以根据需要接受输入和输出-stdin / stdout,函数等,但是输入可能未进行硬编码。

这是,因此字符计数中最短的代码将获胜。


4
我知道这是一个古老的挑战,但是测试用例不足。++>>++<<--应该输出>>++<<,这没有涵盖。请添加更多测试用例。
mbomb007 '16

@ mbomb007您是否检查了最后一个测试用例+++>-<+>---<?可以将其缩短以避免不必要的指针移动,但是预期的输出使其保持不变。根据对问题和答案的了解,我的理解是,Doorknob很酷,对规范的宽松要求非常高。我们必须消除任何空操作连续+-><序列明确规定,超越它允许做一些额外的缩小文件在你的榜样++>>++<<--,我们还可以重排,只要他们不改变代码,例如功能性>+<++>+<
米奇·施瓦兹

@MitchSchwartz“如果不执行+-> <字符序列,则将其删除+>-<->+<。例如,您应该删除。(这可能是最棘手和最难实现的。)请确保您没有得到任何误报,例如+>-<+>-<,不应删除。” -这是一个模糊的那种
mbomb007

@ mbomb007第二和第三个项目符号点是多余且不必要的,因为它们包含在第四个项目符号点中。所以呢?这是一项很酷的任务。我的评论是具有建设性的,旨在提供澄清,而不是攻击您。请按照我的意图进行,或者告诉我我应该怎么说的。因为您没有真正解决我写的内容;好像您是在试图防御自己而不真正具有建设性。您以哪种方式感到含糊?您将如何重写它?您要编辑问题吗?你想问门把手吗?
米奇·施瓦兹

1
哦,所以我们只需要删除连续的序列?
mbomb007 '16

Answers:


10

叛军-104

_/^_$/$</([^][<>.,+-]|\+-|-\+|<>|><)//((?<X>(<|>))+[+-]+(?!\2)(?<-X><|>)+(?(X)(?!)))([+-]+)/$3$1/.+/$>$&

用法:

输入:从标准输入读取一行。

输出:将一行输出到标准输出。

异常*:

  • 输入将_导致另一行被读取和使用,而不是什么也不输出。
  • 第二个测试输出++++>----<代替+++>-<+>---<。没关系,对吗?;)
  • >-<+等被替换为+>-<

扰流板:

实施异常#3会使事情变得微不足道。

* 这不是一个错误,这是一个功能!


“这不是一个功能缺陷” +1!
Rohan Jhunjhunwala

36

Brainfuck,579字节

,[<<+>>>>+<<[[<+>>+<-]++++++[>-------<-]>-[-[-[-[--------------[--[<+++++[>-----
-<-]>+[--[<<[-]>>-]]<]>[>>-<<<<<[-]<[<]<<<[<]>>>>>>>>[<]<-[+>]+[->+]>>>>+>[<-]<[
>+<-<]>]<]>[<<<[-]-[<]>>>>>>>>>>>[<]<<<<<<[<]<-[+>]+[-<+]<<<+<[>-<<<]>[-<+<]]]<]
>[+>[-<]<[<<]<[-]>>]]<]+>[-[<-]<[>+>+<<-<]<[-]>+>]<<[>-]>[,>]<]<+<[>]>[>>>[<<<<[
-<]<<<]>>>+>>>>[<<<<->>>>[>>>[-<]>>>>]]]>[<<<[<+[-->>]]>[-[.[-]]]>[<]>[<<++++++[
>+++++++<-]>+>>[<<.>>-]<<++>-[<.>-]+++[<+++++>-]+<<<<<<+>[<<[>->>>>>.[[-]<<<<]<<
<+>>>]>[->->>>>[-]]]<[->+[>>>>>]>>[<]<<<<<<<<[[-]<]>[++.[-]>>>>>>>]<]]>>]<[>>>>>
>>]+[-<<<<<[-]<<],]

带有格式和一些注释:

,
[
  <<+>> >>+<<
  [
    [<+> >+<-]
    ++++++[>-------<-]
    >-
    [
      not plus
      -
      [
        not comma
        -
        [
          not minus
          -
          [
            not period
            --------------
            [
              not less than
              --
              [
                not greater than
                <+++++[>------<-]>+
                [
                  not open bracket
                  --
                  [
                    not close bracket
                    <<[-]>>-
                  ]
                ]
                <
              ]
              >
              [
                greater than
                >>-<<
                <<<[-]<[<]<<<[<]
                >>>>>>>>[<]
                <-[+>]
                +[->+]
                >>>>+>[<-]
                <[>+<-<]
                >
              ]
              <
            ]
            >
            [
              less than
              <<<[-]-[<]
              >>>> >>>>>>>[<]
              <<<<<<[<]
              <-[+>]
              +[-<+]
              <<<+<[>-<<<]
              >[-<+<]
            ]
          ]
          <
        ]
        >
        [
          minus
          +>[-<]
          <[<<]
          <[-]>>
        ]
      ]
      <
    ]
    +>
    [
      plus
      -[<-]
      <[>+>+<<-<]
      <[-]>+>
    ]
    <<
    [
      comma or period or bracket
      >-
    ]
    >[,>]
    <
  ]
  comma or period or bracket or eof
  <+<
  [
    start and end same cell
    >
  ]
  >
  [
    >>>
    [
      <<<<[-<]<<<
    ]
    >>>+>>>>
    [
      start right of end
      <<<<->>>>
      [>>>[-<]>>>>]
    ]
  ]
  >
  [
    <<<
    [
      <+[-->>]
    ]
    >[-[.[-]]]
    >[<]
    >
    [
      <<++++++[>+++++++<-]>+>>
      [<<.>>-]
      <<++>-[<.>-]
      +++[<+++++>-]
      +<<<<< <+>
      [
        <<
        [
          go left
          >->>>>>.
          [[-]<<<<]
          <<<+>>>
        ]
        >
        [
          toggle left right
          ->->>>>[-]
        ]
      ]
      <
      [
        toggle right left
        ->+[>>>>>]>>[<]
        <<<<<<<<
        [
          [-]<
        ]
        >
        [
          go right
          ++.[-]
          >>>>>>>
        ]
        <
      ]
    ]
    >>
  ]
  <[>>>>>>>]
  +[-<<<<<[-]<<]
  ,
]

这使用与Keith Randall解决方案相同的方法,+-<>通过仿真将所有连续序列最小化。例如,+++>-<+>---<变为++++>----<>+<+<<+>+<->>>>变为+<+>>+>

在线尝试。 (如果模拟单元的绝对值接近256,则将出现溢出问题。)

整体结构是

while not EOF:
  while not EOF and next char not in ",.[]":
    process char
  print minified sequence (followed by the char in ",.[]" if applicable)

磁带分为7个单元的节点。在内部循环的开始,内存布局是

0 s 0 c 0 a b

其中s是起始单元格的布尔值标志,c是当前字符,a是模拟单元格值的负数部分(加1),b是模拟单元格值的正数部分。

打印缩小的序列时,内存布局为

d n e 0 0 a b

其中d是用于方向的布尔标志,a并且b如之前(而成为一个印刷时/零),n并且e是唯一的非零对端节点; n与看到该节点的次数有关,并且e是停止内部循环的char的值(加1)。

最初,我考虑跟踪每个节点的更多信息:最左边和最右边的节点作为布尔标志,以及节点相对于开始节点和结束节点的位置。但是我们可以通过在需要时查看相邻单元格并进行左右扫描以找到起始节点来避免这种情况。

当打印缩小的序列并决定如何移动模拟指针时,我们可以采用一种通用方法:首先从末端节点移开(如果起始节点和末端节点相同,则朝任意方向移动),在最左端和最右端转向节点,然后根据看到结束节点的次数停止:如果开始节点和结束节点相同,则为3次,否则为2。


2
资料来源:Brainfuck。目标:头脑干。+1
暴民埃里克


1
我要让它引起一些注意,并在一两天内授予赏金
-Lirtosiast

1
@MitchSchwartz您是否碰巧对您的代码进行了测试?您实际上可以缩短它!#meta
WallyWest '16

1
@WallyWest(这似乎节省了7个字节!)没关系,永久链接中的代码带有换行符。
丹尼斯,

7

Python,404个字符

此代码对的所有子序列进行了优化+-<>。比您要求的要多一点,但是就到了。

M=lambda n:'+'*n+'-'*-n                                                           
def S(b):                                                                         
 s=p=0;t=[0];G,L='><'                                                             
 for c in b:                                                                      
  if'+'==c:t[p]+=1                                                                
  if'-'==c:t[p]-=1                                                                
  if G==c:p+=1;t+=[0]                                                             
  if L==c:s+=1;t=[0]+t                                                            
 if p<s:k=len(t)-1;t,p,s,G,L=t[::-1],k-p,k-s,L,G                                  
 r=[i for i,n in enumerate(t)if n]+[s,p];a,b=min(r),max(r);return(s-a)*L+''.join(M(n)+G for n in t[a:b])+M(t[b])+(b-p)*L                                           
s=b=''                                                                            
for c in raw_input():                                                             
 if c in'[].,':s+=S(b)+c;b=''                                                     
 else:b+=c                                                                        
print s+S(b) 

它通过模拟+-<>磁带上的操作来工作ts是磁带上的起始位置,p是当前位置。经过仿真后,它找出[a,b]需要操作的范围,并在一遍优化中完成所有+/-。


1

CoffeeScript- 403 397

i=prompt().replace /[^\]\[,.+-><]/g,''
x=(c)->
 t={};p=n=0
 for d in c
  t[p]?=0;switch d
   when'+'then n=1;t[p]++;when'-'then n=1;t[p]--;when'<'then p--;when'>'then p++
 (n=0if v!=0)for k,v of t;n
s=e=0;((e++;(i=(i.substr 0,s)+i.substr e;e=s=0)if x (i.substr s,e-s).split "")while(i[e]||0)!in['[',']',0];e=++s)while s<=i.length
r=/(\+-|-\+|<>|><|^[<>]$)/g
i=i.replace r,'' while r.test i
alert i

演示(请原谅在此处使用bit.ly,整个URL会破坏降价促销)

未压缩的版本(带有调试代码):

console.clear()
input = """Should disappear: ++>>+<+++<->-->-<<->-<
Should disappear: +++>-<--->+<
Should stay: +++>-<+>---<"""

input = input.replace /[^\]\[,.+-><]/g, ''
console.log input

execute = (code) ->
  stack = {}
  item = 0
  console.log code
  nop = false
  for char in code
    switch char
      when '+' then nop = true; stack[item]?=0;stack[item]++
      when '-' then nop = true; stack[item]?=0;stack[item]--
      when '<' then item--
      when '>' then item++
  console.debug stack
  (nop = false if v != 0) for k,v of stack
  nop
start = 0
end = 0

while start <= input.length
 while input.charAt(end) not in [ '[', ']', '' ]
  end++
  if execute (input.substring start, end).split("")
    input = (input.substring 0, start) + input.substring end
    end = start = 0
    console.log input
 end = ++start
input = input.replace /(\+-|-\+|<>|><|^(<|>)$)/g, '' while /(\+-|-\+|<>|><)/.test input
console.log 'Result: ' + input

发布Coffeescript演示的另一种方法是使用JSFiddle。在左边缘有一个“语言”配置窗格,可让您使用CoffeeScript而不是JS。
彼得·泰勒

@PeterTaylor谢谢,我以前听说过JSFiddle,但不是知道它能够使用CoffeeScript
TimWolla 2013年

这在上失败>+.-<,产生空字符串而不是将其保留不变。
米奇·施瓦兹
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.