Desduplicando a duplicação de strings


33

Introdução

Vamos observar a seguinte string:

AABBCCDDEFFGG

Você pode ver que todas as letras foram duplicadas , exceto a letra E. Isso significa que a carta Efoi duplicada . Portanto, a única coisa que precisamos fazer aqui é reverter esse processo, o que nos fornece a seguinte string não-duplicada :

AABBCCDDEEFFGG

Vamos dar um exemplo mais difícil:

AAAABBBCCCCDD

Você pode ver que há um número desigual de consecutivos B, o que significa que um dos BBfoi desduplicado da string original. Precisamos apenas de-duplicar esta carta, o que nos dá:

AAAABBBBCCCCDD


O desafio

Dada uma sequência desduplicada não vazia , consistindo apenas em caracteres alfabéticos (somente em maiúsculas ou apenas minúsculas), retorne a sequência não desduplicada . Você pode assumir que sempre haverá pelo menos um caractere deduplicado na string.


Casos de teste

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

Isso é , então o menor envio válido em bytes vence!


@ mbomb007 Sim, isso resultaria em AABBBB.
Adnan

1
Não sei se entendi o desafio. Por que ABBBmapear para AABBBB, não AABBBBBB?
Dennis

2
@ Dennis Se você separar cada grupo de personagens em grupos de 2, você terá a seguinte: A BB B. Os caracteres que não estão emparelhados (e, portanto, não estão duplicados) precisam ser duplicados, resultando em AA BB BB, que é a sequência não desduplicada.
21716 Adnan

8
Portanto: garanta que cada execução de caracteres tenha um número par de elementos adicionando no máximo um elemento à execução?
Mad Physicist

1
@MadPhysicist Sim, isso está correto #
Adnan

Respostas:


20

MATL , 7 bytes

Y'to+Y"

Experimente online! Ou verifique todos os casos de teste .

Vamos dar 'ABBA'como exemplo de entrada.

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'

11

Retina , 11 bytes

(.)\1?
$1$1

Experimente online - contém todos os casos de teste


1
Eu esperava que Retina ganhasse.
Adám

@ Adám Sim, é bem curto, mas a resposta do MATL é ótima. Todas as línguas do golfe acabaram com soluções mais curtas.
mbomb007

8

Perl, 16 bytes

15 bytes de código + -psinalizador.

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

Para executá-lo:

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

7

Haskell, 36 bytes

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

Exemplo de uso: u "OOQQO"-> "OOQQOO".

Se a sequência tiver pelo menos 2 elementos, faça duas cópias da primeira e acrescente uma chamada recursiva com

  • o segundo elemento e o resto se os dois primeiros elementos diferirem ou
  • apenas o resto

Se houver menos de dois elementos (um ou zero), faça duas cópias da lista.


6

Braquilog , 17 bytes

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

Experimente online!

Explicação

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

Ruby, 21 bytes

20 bytes mais o -psinalizador.

gsub(/(.)\1?/){$1*2}

4

JavaScript (ES6), 37 30 bytes

Salvo 7 bytes usando os muito mais eficientes '$ 1 $ 1' como [outros] [respostas] fez

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

Casos de teste


4

Mathematica, 41 bytes

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

Função sem nome que insere uma string e gera uma string. Desduplicar completamente e desduplicar completamente. Não é muito curto, mas não poderia fazer melhor por enquanto.


4

Entre 98 , 24 bytes

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

Experimente Online!

$pode ser facilmente substituído por -e o segundo @por ;.

Eu acho que isso pode ser jogado ainda mais devido ao -início de ambos -,(ou $,acima) e -\,.

Quão?

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 bytes

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

Ungolfed:

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

Código do teste:

Experimente aqui.

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"));
  }
}

Saída:

AABBCCDDEEFFGG
AAAABBBBCCCCDD
AAAABBBBCCCCDDDD
HHEEYY
AAAAAAAA
NN
OOQQOO
AABBBB
AABBAA

2

PHP, 65 bytes, sem regex

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

recebe entrada do argumento da linha de comando. Corra com -r.

regex? No PHP, o regex usado pela maioria das respostas duplica todos os caracteres. seria 44 bytes:

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

2

Brain-Flak 69 Bytes

Inclui +3 para -c

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

Experimente Online!

Explicação:

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 bytes

ͨ.©±½/±±

TryItOnline

Apenas encontre e substitua regex como todo o resto do encadeamento. A única diferença é que eu posso substituir qualquer coisa que exija um \na frente dele pelo caractere com o mesmo valor ascii, mas com o conjunto de bits alto. (Assim (, 00101000 se torna ¨, 10101000)


1

Perl 6 , 17 bytes

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

com a opção de linha de comando -p

Exemplo:

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

1

Raquete 261 bytes

(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)))])))

Ungolfed:

(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)))] ))))

Teste:

(f "ABBBCDDEFFGGG")

Saída:

"AABBBBCCDDEEFFGGGG"

1

05AB1E , 10 bytes

.¡vy¬ygÉ×J

Experimente online!

Explicação

.¡           # 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 bytes

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

Obrigado ao xnor por salvar 8 bytes! -> bithack.


Isso não mantém as letras na ordem certa.
Xnor

@xnor Obrigado por mencionar! Fixo.
Yytsi

Parece bom. Você pode escrever a expressão x+x%2como x&-2.
Xnor

@ xnor eu tentei s.count(c)&-2e ele retornou uma string vazia ...: / Alguma idéia?
Yytsi

1
Oh, você está certo e eu cometi um erro. eu acho quex+1&-2 deveria fazê-lo. Os pares vão para si mesmos e as probabilidades aumentam para pares.
xnor

1

R, 81 bytes

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

Lê uma string de stdin, splin no vetor de caracteres e executa a codificação no comprimento da execução (rle). Em seguida, repita os valores de cada regra, a soma dos comprimentos e os mods de comprimentos 2.

Se pudermos ler a entrada separada por espaço (implicitamente como um vetor / array de caracteres), podemos pular a parte de divisão e o programa reduzirá para 64 bytes:

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

1

> <> (Peixe) 39 bytes

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

Certamente isso pode ser muito praticado, usando uma técnica diferente.

Ele recebe uma entrada e compara com o item atual da pilha; se for diferente, imprimirá o primeiro item da pilha duas vezes; se o mesmo imprimir os dois.

A pilha quando vazia é fornecida com um 0 que não imprime nada, portanto pode ser anexada sempre.


1

Pitão, 15 bytes

Vrz8p*+hN%hN2eN

Verifique todos os casos de teste aqui.

Agradecimentos a Luis Mendo pela metodologia.

Explicação

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

Como costuma ser o caso, sinto que isso poderia ser mais curto. Eu acho que deveria haver uma maneira melhor de extrair elementos da lista do que o que estou usando aqui.


1

PowerShell , 28 bytes

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

Experimente online!(inclui todos os casos de teste)

Resposta do porto da Retina . Os únicos pontos de observação são os que temos em $argsvez do habitual $args[0](uma vez -replaceque iterarão sobre cada item na matriz de entrada, podemos jogar fora do índice) e as '$1$1'aspas precisam ser de aspas simples para que sejam substituídas pelo regex variáveis ​​em vez de serem tratadas como variáveis ​​do PowerShell (o que aconteceria se fossem aspas duplas).


1

C, 67 bytes

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

Ligue para:

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

1

brainfuck, 22 bytes

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

Experimente online.

Imprime o caractere atual duas vezes, a menos que seja igual a um caractere que acabou de ser impresso duas vezes.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.