赞美Puzles和Colf:压缩字符串


25

花了一些时间在这个网站上,我开始享受尽可能短的事情。这可能就是为什么我最近被包含多个相同字符的字符串冒犯的原因。您的工作是编写根据以下规则压缩给定字符串的函数或程序:

  • 0压缩开始,即寻找相同字符的第一对(最左边),中间还有0个其他字符。如果找到了这样的一对,请删除两个字符之一,然后通过执行另一个0压缩来重新启动算法。如果找不到这样的对,请继续下一步。示例:
    programming-C0-> programing
    aabbcc-C0-> abbcc
    test-C0->test

  • 然后执行1压缩,即寻找第一对相同的字符,它们之间还有1个其他字符。如果找到了这样的一对,请删除其中的一个以及它们之间的所有字符,然后0缩进重新开始。如果找不到这样的对,请继续下一步。示例:
    abacac-C1-> acac
    java-C1->ja

  • 继续进行2-缩合,依此类推,直到n缩合,其中n为原始字符串的长度,每次在缩合除去一些字母后重新启动。示例:
    programing-C2-> praming
    abcdafg-C3->afg

生成的字符串称为压缩字符串,每个字符串最多包含一次。


输入:

可打印的ascii字符的小写字符串。

输出:

所述冷凝根据上述规则的字符串。

例子:

examples     -> es
programming  -> praming
puzzles      -> puzles
codegolf     -> colf
andromeda    -> a
abcbaccbabcb -> acb
if(x==1):x++ -> if(x+
fnabnfun     -> fun
abcdefae     -> abcde

详细示例以阐明算法的工作原理:

fnabnfun -C0-> fnabnfun -C1-> fnabnfun -C2-> fnfun -C0-> fnfun -C1-> fun -C0-> fun 
 -C1-> fun -C2-> ... -C8-> fun

abcbaccbabcb -C0-> abcbacbabcb -C0-> abcbacbabcb -C1-> abacbabcb -C0-> abacbabcb 
 -C1-> acbabcb -C0-> acbabcb -C1-> acbcb -C0-> acbcb -C1-> acb -C0-> acb 
 -C1-> ... -C12-> acb

只要您的解决方案和算法为所有允许的输入返回相同的输出,您的方法就不必从上面实现算法。这是一个挑战。


感谢@Linus提供有用的沙箱评论!


@MartinEnder Riley的测试用例仍然是必需的,因为这是我的Retina解决方案无法使用的唯一测试用例。
mbomb007 '16

@ mbomb007啊,我明白了。好点子。
马丁·恩德

输入字符串是否会包含不可打印的字符(例如空格)?
mbomb007 '16

@ mbomb007不,假设仅可打印的ASCII字符是可以的。
Laikoni's

@ mbomb007但是据我所知,空格视为可打印的ASCII字符,例如here
Laikoni

Answers:


6

JavaScript(ES6),74个字节

f=
(s,n=0,m=s.match(`(.).{${n}}\\1`))=>s[n]?m?f(s.replace(...m)):f(s,n+1):s
;
<input oninput=o.textContent=f(this.value)><pre id=o>


非常好,比我想象的要短。
ETHproductions 2016年

5

Perl,38 31 30 29字节

这应该使非高尔夫语言远远落后...

-1 $-[0]感谢赖利

-1 @{-}感谢Dada

包括+1的 -p

在STDIN上输入

condense.pl

#!/usr/bin/perl -p
s/(.)\K.{@{-}}\1// while/./g

这个27字节的版本应该可以使用,但是不能,因为perl不会@-在正则表达式中进行插值(请参阅/programming/39521060/why-are-etc-not-interpolated-in-strings

#!/usr/bin/perl -p
s/(.)\K.{@-}\1// while/./g

@{\@-}零件如何工作?我以为@-保留了每个匹配项的索引,因此它如何在每次迭代中“计数”。另外,如果您@{\@-}在每次替换之前和之后进行打印,则只会打印1或
Riley

1
@Riley /./g每次在字符串中以1 递增,除非字符串更改,否则它将重置为0。如果在s @-之后/./g但在之前打印,s///则会看到它上升(使用测试,其中剩余字符串足够大)
Ton Hospel '16

印刷$-[0]给出了我期望的数字。确实@{\@-}表现得像$-[0]由于某种原因,打印时,由于正则表达式的上下文,但不?$-[0]@{\@-}它们相同时短一个字节。
莱利

"@{\@-}"@{\@-}(不带")不同。
莱利

@Riley不,但"@{\@-}"与相同"@-"。对于正则表达式替换也应该如此,但事实并非如此。类似地$-[0]应该可以,但不能。PS:您@-在打印时可能会以某种方式应用标量上下文,因此您总是得到1或2
Ton Hospel

3

CJam,35个字节

rL{_,{{(_@_@#I={I)>]sj}*}h]s}fI}j

在线尝试!


rL{                            }j   | run recursion on input
   _,{                      }fI     | for I from 0 to length(input)
      {                 }h]s        | one pass & clean up
       (_@                          | slice and store leading element A
          _@#I={      }*            | if next A is I steps away
                I)>                 | slice off I+1 element
                   ]sj              | clean up & recursion

您可以通过插入来查看各个缩合ed


2

Python 2中,117个 104 101字节

递归地进行必要的替换。我动态构建正则表达式。

import re
def f(s,i=0):t=re.sub(r"(.)%s\1"%("."*i),r"\1",s);e=s==t;return i>len(t)and t or f(t,i*e+e)

在线尝试


两条返回线可以压缩成return i>len(t) and t or s!=t and f(t) or f(t,i+1)一个-4字节的网
Quelklef

可以通过将其更改为return t if i>len(t)else s!=t and f(t)or f(t,i+1))
Quelklef

甚至e=s==t;return i>len(t)and t or f(t,i*e+e)可以再删除i=0函数定义中的,但是必须从0开始调用。
Quelklef

我将假定存在四个空格不是因为您使用的是四个空格,而是因为SE自动扩展了它们。如果不是这种情况,则可以将所有空格更改为制表符,也可以将单个空格更改为-9个字节。
基金莫妮卡的诉讼

@Quelklef该meta禁止使用其他参数。
mbomb007 '16

1

Perl 53 52

包括+1的-p

for($i=0;$i<length;){$i=(s/(.).{$i}\1/\1/)?0:$i+1;}

ideone上尝试一下。


1

Mathematica,101个字节

NestWhile[i=0;StringReplace[#,a_~~_~RepeatedNull~i++~~a_:>a,1]&,#,SameQ,2,ByteCount@#]&~FixedPoint~#&

应该有一种方法可以缩短这个时间...


1

PHP,90字节

for($s=$argv[$c=1];$s[$i=++$i*!$c];)$s=preg_replace("#(.).{{$i}}\\1#","$1",$s,1,$c);echo$s;

或92个字节

for($s=$argv[1];$s[$i];$i=++$i*!$c)$s=preg_replace("#(.).{".+$i."}\\1#","$1",$s,1,$c);echo$s;   

1
1)第一个版本:+$i代替$i+=0(-2)。2)for循环而不是while可以节省两个字节并允许删除卷发(-4)。3)$i=++$i*!$c代替$i=$c?0:$i+1(-1)。4)\\2不需要,删除括号(-2)。5)您可以允许限制9而不是1速度(+0)
Titus

@Titus很好的主意。我had't看到这个感谢
约尔格Hülsermann

现在,我再想一想... +$i在每种情况下都行不通。尝试hammer。PHP不会抱怨正则表达式中的空括号;但它与想要的不匹配。顺便说一句:我是91,而不是90。但是请尝试新的1)for($s=$argv[$c=1];$s[$i=++$i*!$c];)
Titus

@Titus是的,的确是我回过头来$i+=0,稍后将尝试您的建议。锤子是什么意思?
约尔格Hülsermann

@Titus好了同样的问题,如果puzzle还是别的什么类似(.)//1,但它是好的,你的建议或$i´=0
约尔格Hülsermann

1

Ruby,75 64 57字节

(56个字节的代码+ p命令行选项。)

在正则表达式中使用字符串插值来控制要替换的匹配项的长度。

i=0
~/(.).{#{i}}\1/?sub($&,$1)&&i=0: i+=1while i<$_.size

测试:

$ ruby -p condense.rb <<< fnabnfun
fun

1

Haskell97 88字节

(0?)
(a:s)!(b:t)|a==b=a:t|1<3=a:s!t
s!_=s
m?s|length s<m=s|a<-s!drop m s=sum[m+1|a==s]?a

在线尝试!


旧的97字节bersion:

(a:s)!(b:t)|a==b=a:t|1<3=a:s!t
s!_=s
m?s|length s==m=s|a<-s!drop m s=(last$0:[m+1|a==s])?a
c=(0?)

在ideone上尝试一下

说明:

(a:s)!(b:t)|a==b = a:t         --perform condensation
           |1<3  = a:s!t       --recursively compare further
 s   ! _         = s           --no condensation performed

所述(!)功能执行一个正缩合时给定的一个字符串一次整体并且一旦移除了前n个字符,例如abcdbecdbe通过递归地比较两个前导字符用于2缩合,。

m?s|length s==m   = s         --stop before performing length-s-condensation
   |a <- s!drop m s           --a is the m-condensation of s
    = (last$0:[m+1|a==s])?a   --disguised conditional:
                              -- if a==s       if the m-condensation did not change s
                              -- then (m+1)?a  then perform m+1-condensation
                              -- else 0?a      else restart with a 0-condensation

c=(0?)                        -- main function, initialise m with 0
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.