取消重复字符串


33

介绍

让我们观察以下字符串:

AABBCCDDEFFGG

您会看到每个字母都重复了,除了字母E。那意味着这封信E已经被删除了。因此,我们唯一需要做的就是逆转该过程,这为我们提供了以下未重复数据删除的字符串:

AABBCCDDEEFFGG

让我们举一个更困难的例子:

AAAABBBCCCCDD

您会看到连续B的数量不均匀,这意味着其中一个BB已从原始字符串中删除了重复数据。我们只需要取消重复这封信,就可以给我们:

AAAABBBBCCCCDD


挑战

给定一个非空的重复数据删除字符串,该字符串包含字母字符(仅大写或小写),则返回未重复数据删除的字符串。您可以假定字符串中始终至少有一个重复数据删除字符。


测试用例

AAABBBCCCCDDDD    -->    AAAABBBBCCCCDDDD
HEY               -->    HHEEYY
AAAAAAA           -->    AAAAAAAA
N                 -->    NN
OOQQO             -->    OOQQOO
ABBB              -->    AABBBB
ABBA              -->    AABBAA

这是,因此以字节为单位的最短有效提交将获胜!


@ mbomb007是的,这将导致AABBBB
阿德南

1
我不确定我是否理解挑战。为什么要ABBB映射到AABBBB而不是AABBBBBB
丹尼斯

2
@Dennis如果将每组字符分成2组,则会得到以下内容:A BB B。未配对(因此不重复)的字符需要重复,导致AA BB BB,这是未重复数据删除的字符串。
阿德南

8
那么:通过向运行添加最多一个元素,确保每个字符运行都具有偶数个元素?
疯狂物理学家,2016年

1
@MadPhysicist是的,没错
Adnan

Answers:


20

MATL,7个字节

Y'to+Y"

在线尝试!验证所有测试用例

让我们以'ABBA'输入为例。

Y'   % Implicit input. Run-length decoding
     % STACK: 'ABA', [1 2 1]
t    % Duplicate top of the stack
     % STACK: 'ABA', [1 2 1], [1 2 1]
o    % Modulo 2
     % STACK: 'ABA', [1 2 1], [1 0 1]
+    % Add, element-wise
     % STACK: 'ABA', [2 2 2]
Y"   % Run-length encoding. Implicit display
     % STACK: 'AABBAA'


8

Perl,16个字节

15个字节的代码+ -p标志。

s/(.)\1?/$1$1/g

要运行它:

perl -pe 's/(.)\1?/$1$1/g' <<< 'HEY'

7

Haskell,36个字节

u(a:b:c)=a:a:u([b|a/=b]++c)
u x=x++x

用法示例:u "OOQQO"-> "OOQQOO"

如果字符串中至少包含2个元素,请复制第一个元素的两个副本,然后附加带有以下内容的递归调用

  • 如果前两个元素不同,则第二个元素为其余元素,或者
  • 剩下的

如果元素少于两个(一个或零),则获取列表的两个副本。


6

Brachylog,17个字节

@b:{~b#=.l#e,|}ac

在线尝试!

说明

Example input: "ABBB"

@b                  Blocks: Split into ["A", "BBB"]
  :{          }a    Apply the predicate below to each element of the list: ["AA", "BBBB"]
                c   Concatenate: "AABBBB"

    ~b#=.             Output is the input with an additional element at the beginning, and
                        all elements of the output are the same (e.g. append a leading "B")
        .l#e,         The length of the Output is an even number
             |        Or: Input = Output (i.e. do nothing)


4

JavaScript(ES6),37个 30字节

通过使用更有效的“$ 1 $ 1”像保存7个字节[其他] [答案]

s=>s.replace(/(.)\1?/g,'$1$1')

测试用例


4

Mathematica,41个字节

s=StringReplace;s[s[#,a_~~a_->a],b_->b~~b]&

输入字符串并输出字符串的未命名函数。完全重复数据删除,然后完全不重复数据删除。并不是很短,但是我现在不能做得更好。


4

Befunge 98,24字节

#@~#;:::#@,~-:!j;$,;-\,;

在线尝试!

$可以很容易地更换-,并且第二@;

我认为,由于--,(或$,以上)的开头都可以进一步打高尔夫球-\,

怎么样?

Stack notation:  bottom [A, B, C, D] top

#@~     Pushes the first character onto the stack (C henceforth) and ends if EOF
#;      No-op to be used later
:::     Now stack is [C, C, C, C]

#@,~    Prints C, and if EOF is next (odd consecutive Cs), prints again and ends
        Lets call the next character D

-       Now stack is [C, C, C-D]
:!j;    If C == D, go to "$," Else, go to "-\,"

===(C == D)===

$,      C == D (i.e. a pair of Cs) so we discard top and print C (Stack is now [C])
;-\,;   Skipped, IP wraps, and loop starts again

===(C != D)===

-       Stack is [C, C-(C-D)]  By expanding: [C, C - C + D] or just [C, D]
\,      Prints C (Stack is now [D])

;#@~#;  This is skipped, because we already read the first character of a set of Ds,
        and this algorithm works by checking the odd character in a set of
        consecutive similar characters. We already read D, so we don't
        need to read another character.

3

Java 7,58个字节

String c(String s){return s.replaceAll("(.)\\1?","$1$1");}

取消高尔夫:

String c(String s){
  return s.replaceAll("(.)\\1?", "$1$1");
}

测试代码:

在这里尝试。

class M{
  static String c(String s){return s.replaceAll("(.)\\1?","$1$1");}

  public static void main(String[] a){
    System.out.println(c("AABBCCDDEFFGG"));
    System.out.println(c("AAAABBBCCCCDD"));
    System.out.println(c("AAABBBCCCCDDDD"));
    System.out.println(c("HEY"));
    System.out.println(c("AAAAAAA"));
    System.out.println(c("N"));
    System.out.println(c("OOQQO"));
    System.out.println(c("ABBB"));
    System.out.println(c("ABBA"));
  }
}

输出:

AABBCCDDEEFFGG
AAAABBBBCCCCDD
AAAABBBBCCCCDDDD
HHEEYY
AAAAAAAA
NN
OOQQOO
AABBBB
AABBAA

2

PHP,65字节,无正则表达式

while(""<$c=($s=$argv[1])[$i])if($c!=$s[++$i]||!$k=!$k)echo$c.$c;

从命令行参数获取输入。用运行-r

正则表达式? 在PHP中,大多数答案使用的正则表达式会复制每个字符。将是44个字节:

<?=preg_replace("#(.)\1?#","$1$1",$argv[1]);

2

脑筋急躁 69字节

包括+3 -c

{((({}<>))<>[({})]<(())>){((<{}{}>))}{}{(<{}{}>)}{}}<>{({}<>)<>}<>

在线尝试!

说明:

Part 1:
{((({}<>))<>[({})]<(())>){((<{}{}>))}{}{(<{}{}>)}{}}<>

{                                                  }   # loop through all letters
 (   {}     [ {} ]<(())>){((<{}{}>))}{}                # equals from the wiki   
                                                       # but first:
  ((  <>))<>                                           # push the top letter on the other 
                                                       # stack twice  
             (  )                                      # push the second letter back on
                                       {        }      # if they were equal:
                                        (<    >)       # push a 0 to exit this loop
                                          {}{}         # after popping the 1 from the 
                                                       # comparison and the next letter
                                                       # (the duplicate)
                                                 {}    # pop the extra 0
                                                    <> # switch stacks

Part 2 (at this point, everything is duplicated in reverse order):
{({}<>)<>}<>

{        }   # for every letter:
 ({}<>)      # move the top letter to the other stack
       <>    # and switch back
          <> # Finally switch stacks and implicitly print


1

V 10字节

ͨ.©±½/±±

在线试用

只需像查找线程中的所有其余部分一样查找并替换正则表达式即可。唯一的区别是,我可以用\具有相同ascii值但高位设置的字符替换任何需要在其前面加上a的字符。(因此(,00101000变为¨,10101000)


1

Perl 6、17个字节

s:g/(.)$0?/$0$0/

使用-p命令行开关

例:

$ perl6 -pe 's:g/(.)$0?/$0$0/' <<< 'AAABBBCCCCDDDD
> HEY
> AAAAAAA
> N
> OOQQO
> ABBB
> ABBA'
AAAABBBBCCCCDDDD
HHEEYY
AAAAAAAA
NN
OOQQOO
AABBBB
AABBAA

1

拍子261字节

(let((l(string->list s))(r reverse)(c cons)(e even?)(t rest)(i first))(let p((l(t l))(ol(c(i l)'())))
(cond[(empty? l)(list->string(if(e(length ol))(r ol)(r(c(i ol)ol))))][(or(equal?(i ol)(i l))(e(length ol)))
(p(t l)(c(i l)ol))][(p(t l)(c(i l)(c(i ol)ol)))])))

取消高尔夫:

(define (f s)
  (let ((l (string->list s)))
    (let loop ((l (rest l))
               (ol (cons (first l) '())))
      (cond
        [(empty? l)
         (list->string(if (even? (length ol))
                          (reverse ol)
                          (reverse (cons (first ol) ol))))]
        [(or (equal? (first ol) (first l)) 
             (even? (length ol)))
         (loop (rest l) (cons (first l) ol))]
        [else
         (loop (rest l) (cons (first l) (cons (first ol) ol)))] ))))

测试:

(f "ABBBCDDEFFGGG")

输出:

"AABBBBCCDDEEFFGGGG"

1

05AB1E,10个字节

.¡vy¬ygÉ×J

在线尝试!

说明

.¡           # split string into groups of the same char
  v          # for each group
   y         # push the group
    ¬        # push the char the group consists of
     yg      # push the length of the group
       É     # check if the length of the group is odd
        ×    # repeat the char is-odd times (0 or 1)
         J   # join to string

1

Python3,102个 94字节

from collections import*
lambda s:"".join(c*(s.count(c)+1&-2)for c in OrderedDict.fromkeys(s))

感谢xnor节省了8个字节!-> bithack。


这不能使字母顺序正确。
xnor

@xnor感谢您的提及!固定。
Yytsi '16

看起来不错。您可以将表达式写x+x%2x&-2
xnor

@xnor我尝试过s.count(c)&-2,它返回了一个空字符串...:/有什么想法吗?
Yytsi '16

1
哦,你是对的,我弄错了。我认为x+1&-2应该这样做。偶数会消失,几率会增加到偶数。
xnor

1

R,81个字节

r=rle(el(strsplit(scan(,""),"")));cat(do.call("rep",list(r$v,r$l+r$l%%2)),sep="")

从stdin读取字符串,将splin转换为字符向量,然后执行游程编码(rle)。随后,从rle重复每个值,长度之和和长度mod2

如果我们可以读取以空格分隔的输入(隐式表示为字符的向量/数组),则可以跳过分隔部分,程序将减少为64个字节:

r=rle(scan(,""));cat(do.call("rep",list(r$v,r$l+r$l%%2)),sep="")

1

> <>(鱼)39字节

0v ;oo:~/:@@:@=?!voo
 >i:1+?!\|o !:  !<

可以肯定的是,可以使用其他技术打很多球。

它接受一个输入并与当前堆栈项目进行比较,如果不同,它将打印第一个堆栈项目两次,如果相同,则将它们都打印出来。

堆栈为空时会提供一个0,该字符不会打印任何内容,因此可以随时附加。


1

Pyth,15个字节

Vrz8p*+hN%hN2eN

在这里验证所有测试用例。

感谢路易斯·门多Luis Mendo)的方法。

说明

Vrz8p*+hN%hN2eN    z autoinitializes to the input
 rz8               run-length encode the input, returned as list of tuples (A -> [[1,"A"]])
V                  for every element N in this list
      +hN          add the head element of N (the number in the tuple)
         %hN2      to the head element of N mod 2
     *       eN    repeat the tail element of N that many times (the letter in the tuple)
    p              print repeated character without trailing newline

通常,我觉得这可能会更短。我认为应该有一种比我在这里使用的方法更好的方法来从列表中提取元素。


1

PowerShell,28字节

$args-replace'(.)\1?','$1$1'

在线尝试!(包括所有测试用例)

该港视网膜答案。唯一需要注意的是,我们已经获得$args了平常的东西$args[0](因为-replace它将遍历输入数组中的每个项目,因此我们可以取消索引),并且'$1$1'需要用单引号将它们替换为正则表达式变量而不是被视为PowerShell变量(如果使用双引号,则会发生这种情况)。


1

C,67字节

i;f(char*s,char*d){i=*s++;*d++=i;*d++=i;*s?f(i-*s?s:++s,d):(*d=0);}

致电:

int main()
{
    char *in="AAABBBCCCCDDDD";
    char out[128];
    f(in,out);
    puts(out);
}

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.