Truncar caracteres consecutivos com comprimento n


14

O desafio

Dada uma sequência de entrada e um número inteiro n - trunca quaisquer execuções de caracteres consecutivos até um máximo de n comprimento. Os caracteres podem ser qualquer coisa, incluindo caracteres especiais. A função deve fazer distinção entre maiúsculas e minúsculas e n pode variar de 0 a infinito.

Exemplos de entradas / saídas:

f("aaaaaaabbbccCCCcc", 2) //"aabbccCCcc" 
f("aaabbbc", 1) //"abc"
f("abcdefg", 0) //""
f("aaaaaaabccccccccCCCCCC@", 4) //"aaaabccccCCCC@"

Pontuação

A pontuação é baseada no número de bytes usados. portanto

function f(s,n){return s.replace(new RegExp("(.)\\1{"+n+",}","g"),function(x){return x.substr(0, n);});}

seria 104 pontos.

Feliz golfe!

Edit: removeu a restrição de idioma, mas ainda assim gostaria de ver respostas em javascript


1
Por que não permitir o ES6?
— TuxCrafting 08/07/16

7
Eu recomendo perder o requisito de idioma. Javascript é um dos idiomas mais comuns aqui. A auto-resposta com o que você conseguiu provavelmente convidaria as pessoas a ajudá-lo a jogar golfe, ou tentaria vencê-lo com outra abordagem. Além disso, se você tiver reputação suficiente, poderá adicionar uma recompensa à pergunta com um idioma específico em mente. Se isso não lhe agradar, você pode modificar essa pergunta em uma pergunta de dicas e tentar pedir ajuda específica para o golfe.
— FryAmTheEggman 08/07/16

Removida a restrição de idioma e alteradas as regras de pontuação como resultado. Eu ainda adoraria ver entradas javascript, mas acho que posso viver com algumas línguas de golfe de 4-5 caracteres.
— TestSubject06

Bem-vindo à programação de quebra-cabeças e código de golfe! Os desafios de código de golfe são pontuados por comprimento em bytes por padrão. Embora seja possível pontuar em caracteres, é possível obter algumas respostas como esta .
— Dennis

Oh Deus. Alterado para pontuação de bytes.
— TestSubject06 /

Respostas:


6

Python 2, 52 bytes

lambda s,n:reduce(lambda r,c:r+c*(r[-n:]!=c*n),s,'')

Escrito como um programa (54 bytes):

s,n=input();r=''
for c in s:r+=c*(r[-n:]!=c*n)
print r

Repete a sequência de entrada s, acrescentando cada caractere à sequência de saída, a rmenos que os últimos ncaracteres rsejam esse caractere.

Eu acho que isso falharia n==0porque r[-0:]não são os últimos 0 caracteres (sequência vazia), mas a sequência inteira. Mas, ele funciona porque a cadeia permanece vazia, mantendo a correspondência com a cadeia de 0 caracteres.

Um recursivo lambdadeu 56 por causa da repetição

f=lambda s,n:s and s[:f(s[1:],n)[:n]!=s[0]*n]+f(s[1:],n)

Uma estratégia alternativa para manter um contador ide repetições do último caractere também ficou mais tempo do que apenas verificar os últimos ncaracteres diretamente.


6

C, 81 78

Modifica a sequência de entrada.

c,a;f(p,n)char*p;{char*s=p;for(;*p;s+=c<n)*s=*p++,a^*s?c=0:++c,a=*s;c=a=*s=0;}

Programa de teste

Requer dois parâmetros, o primeiro é a sequência a ser truncada, o segundo é o limite de comprimento.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, const char **argv)
{
    char *input=malloc(strlen(argv[1])+1);
    strcpy(input,argv[1]);
    f(input,atoi(argv[2]));
    printf("%s\n",input);
    free(input);
    return 0;
}

Explicação:

c,a;                 //declare two global integers, initialized to zero.
                     //c is the run length, a is the previous character
f(char*p,int n){...} //define function f to truncate input
char*s=p;            //copy p to s; p is source, s is destination
for(;*p              //while there is a source character
;s+=c<n)             //increment copied pointer if run is under the limit
*s=*p++,             //copy from source to destination, increment source
a^*s?c=0:++c,        //if previous character != current then run=0 else increment run
a=*s;                //previous character = current source character
c=a=*s=0;            //after loop, terminate destination string with NUL and reset c and a.

Isso funciona porque o ponteiro de origem sempre será igual ou maior que o ponteiro de destino, para que possamos escrever sobre a string enquanto a analisamos.


Isso é incrível, você pode explicar?
— TestSubject06 /

@ TestSubject06 - Adicionada uma explicação.
— 27416 owacoder

Isso funciona com o caso n = 0? Não consigo compilar para testar aqui.
— TesteSubject06

Sim. Eu adicionei um programa de teste para que você possa compilar.
— 27433 owacoder

Incrível, não foi possível encontrar nenhum exemplo de contador. Curto e funciona!
— TestSubject06

5

Haskell, 36 bytes

import Data.List
(.group).(=<<).take

Versão sem pontos de \n s -> concatMap (take n) (group s).


4

Javascript ES6, 60 54 55 43 bytes

-12 bytes graças a @ TestSubject06 e @Downgoat

(s,n)=>s.replace(/(.)\1*/g,x=>x.slice(0,n))

Exemplo é executado:

f("aaaaaaabbbccCCCcc"      , 2) -> "aabbccCCcc" 
f("aaabbbc"                , 1) -> "abc"
f("abcdefg"                , 0) -> ""
f("aaaaaaabccccccccCCCCCC@", 4) -> "aaaabccccCCCC@"
f("a"                      , 1) -> "a"

f ("a", 1) -> ""
— TestSubject06 08/07/16

1
Desde a sua RegExp não é controlado dinamicamente em qualquer maneira que você pode economizar alguns bytes com RegExp ( "() \\ 1 *.", "G") -> /(.)\1*/g
— TestSubject06

1
Converta RegExp("(.)\\1*","g")para/(.)\1*/g
— Downgoat 08/07/16

1
Não vejo isso ficando menor no JS, a menos que cheguemos a isso de um ângulo completamente diferente. Bom trabalho @Dendrobium!
— TestSubject06

1
Barbeie um byte, alterando (s,n)para s=>n, e o uso se tornaf("aaaaaaabbbccCCCcc")(2)
— Patrick Roberts

3

MATL, 9 bytes

Y'i2$X<Y"

Experimente Online

Explicação

        % Implicitly grab input as a string
Y'      % Perform run-length encoding. Pushes the values and the run-lengths to the stack
i       % Explicitly grab the second input
2$X<    % Compute the minimum of the run lengths and the max run-length
Y"      % Perform run-length decoding with these new run lengths
        % Implicitly display the result

'@@@@@ bbbbbcccddeegffsassss' 3 retornou '@@@ bbbcccddeegffsass' que está faltando o final 's'
— TestSubject06

@ TestSubject06 Obrigado por apontar isso.
— Suever 08/07/16

2

CJam, 12 bytes

{e`\af.e<e~}

Experimente online!

Explicação

e`   e# Run-length encode the input. Gives a list of pair [length character].
\a   e# Swap with maximum and wrap in an array.
f.e< e# For each run, clamp the run-length to the given maximum.
e~   e# Run-length decode.


2

Python 2, 56 bytes

import re
lambda s,n:re.sub(r'(.)(\1{%d})\1*'%n,r'\2',s)

2

gs2, 6 bytes

Codificado no CP437 :

╠c╨<ΘΣ

Esta é uma função anônima (bloco) que espera um número no topo da pilha e uma string abaixo dela.

     Σ   Wrap previous five bytes in a block:
╠          Pop number into register A.
 c         Group string.
    Θ      Map previous two bytes over each group:
  ╨<         Take the first A bytes.

Experimente online. (O código aqui é lines, dump, read number, [the answer], run-block.)


1

Perl 6 ,  38  36 bytes

->$_,$n {S:g/(.)$0**{$n..*}/{$0 x$n}/}
->$_,\n{S:g/(.)$0**{n..*}/{$0 x n}/}

Explicação:

-> $_, \n { # pointy block lambda
  # regex replace ( return without modifying variant )
  # globally
  S:global /
    # a char
    (.)
    # followed by 「n」 or more identical chars
    $0 ** { n .. * }
  /{
    # repeat char 「n」 times
    $0 x n
  }/
}

Teste:

#! /usr/bin/env perl6
use v6.c;
use Test;

my &truncate-char-runs-to = ->$_,\n{S:g/(.)$0**{n..*}/{$0 x n}/}

my @tests = (
  ("aaaaaaabbbccCCCcc", 2) => "aabbccCCcc",
  ("aaabbbc", 1) => "abc",
  ("abcdefg", 0) => "",
  ("aaaaaaabccccccccCCCCCC@", 4) => "aaaabccccCCCC@",
);

plan +@tests;

for @tests -> $_ ( :key(@input), :value($expected) ) {
  is truncate-char-runs-to(|@input), $expected, qq'("@input[0]", @input[1]) => "$expected"';
}
1..4
ok 1 - ("aaaaaaabbbccCCCcc", 2) => "aabbccCCcc"
ok 2 - ("aaabbbc", 1) => "abc"
ok 3 - ("abcdefg", 0) => ""
ok 4 - ("aaaaaaabccccccccCCCCCC@", 4) => "aaaabccccCCCC@"

0

Javascript ES5, 73

function f(s,n){return s.replace(RegExp("(.)(\\1{"+n+"})\\1*","g"),"$2")}

Reutiliza a expressão regular de Lynn em sua resposta em Python .


Seu código não lida com o caso em que n é zero, apenas retorna a string original inteira.
— TestSubject06 /

Sim, no Firefox, você pode descartar as chaves e a declaração de retorno , embora essa sintaxe seja (infelizmente) obsoleta e será removida (na verdade estavam ausentes algumas versões, não percebemos que a trouxeram de volta).
— Dendrobium

Você também pode soltar a newpalavra - chave por -4 bytes.
— Dendrobium

@ TestSubject06 Obrigado, editei minha resposta e acredito que ela passa nos casos de teste agora.
— FryAmTheEggman

0

Perl 5, 50 bytes

Código de 46 bytes + 3 para -ie 1 para-p

Leva o número para truncar para via -i.

s!(.)\1+!$&=~s/(.{$^I}).+/$1/r!ge

Uso

perl -i4 -pe 's!(.)\1+!$&=~s/(.{$^I}).+/$1/r!ge' <<< 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@

Por que -papenas um byte?
— Someonewithpc

@someonewithpc quando pode ser combinado com -eessas opções, consome apenas 1 byte. Se o script precisar ser executado a partir de um arquivo, ele custará 3 para o espaço e ele será sinalizado. Há uma meta post que vou tentar encontrar, mas estou no celular agora.
— Dom Hastings


0

Bash 46 bytes

read c;sed -r ":l;s/(.)(\1{$c})(.*)/\2\3/;t l"

Uso: Digite o número de caracteres a serem limitados, pressione enter e digite a string. Ctrl+ Dpara sair sed(envie EOF).


0

Java 7, 107 106 bytes

String c(String s,int i){String x="";for(int i=-1;++i<j;)x+="$1";return s.replaceAll("(.)\\1{"+i+",}",x);}

Loop alternativo inline alternativo anterior para concatenação de String (que é 1 byte a mais do que String s="";for(int i=-1;++i<j;)s+="$1";infelizmente):

String c(String s,int i){return s.replaceAll("(.)\\1{"+i+",}",new String(new char[i]).replace("\0","$1")));}

Casos não testados e de teste:

Experimente aqui.

class Main {
  static String c(String s, int i){
    String x="";
    for(int j = -1; ++j < i;){
      x += "$1";
    }
    return s.replaceAll("(.)\\1{"+i+",}", x);
  }

  public static void main(String[] a){
    System.out.println(c("aaaaaaabbbccCCCcc", 2));
    System.out.println(c("aaabbbc", 1));
    System.out.println(c("abcdefg", 0));
    System.out.println(c("aaaaaaabccccccccCCCCCC@", 4));
    System.out.println(c("@@@@@bbbbbcccddeegffsassss", 5));
  }
}

Resultado:

aabbccCCcc
abc

aaaabccccCCCC@
@@@@@bbbbbcccddeegffsassss

0

Javascript (usando biblioteca externa) (115 bytes)

(s,r)=>_.From(s).Aggregate((c,n)=>{if(c.a!=n){c.c=1;c.a=n}else{c.c++}if(c.c<=r){c.b+=n}return c},{a:"",b:"",c:0}).b

Link para lib: https://github.com/mvegh1/Enumerable

Explicação do código: Carregue a string na biblioteca, que analisa internamente como matriz de caracteres. Aplique um acumulador na sequência, passando um objeto personalizado como um valor inicial. A propriedade a é o elemento atual, b é a cadeia acumulada e c é a contagem sequencial do elemento atual. O acumulador verifica se o valor atual da iteração, n, é igual ao valor do último elemento, ca. Caso contrário, redefinimos a contagem para 1 e configuramos o elemento atual. Se a contagem do elemento atual for menor ou igual ao comprimento desejado, acumulamos na string de retorno. Finalmente, retornamos a propriedade b, a string acumulada. Não é o código mais golfista, mas feliz por ter uma solução que funciona ...

insira a descrição da imagem aqui


0

J, 31 30 bytes

((<.#@>)#{.@>@])]<;.1~1,2~:/\]

Agrupa a sequência de entrada em execuções (substrings) de caracteres idênticos e assume o mínimo do comprimento dessa execução e o comprimento máximo que foi inserido para truncar a sequência. Em seguida, copia o primeiro caractere de cada execução tantas vezes.

Uso

   f =: ((<.#@>)#{.@>@])]<;.1~1,2~:/\]
   2 f 'aaaaaaabbbccCCCcc'
aabbccCCcc
   1 f 'aaabbbc'
abc
   0 f 'abcdefg'

   4 f 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@

Explicação

((<.#@>)#{.@>@])]<;.1~1,2~:/\]  Input: k on LHS, s on RHS
                             ]  Get s
                        2~:/\   Test if each pair of consecutive chars are not equal
                      1,        Prepend a 1
                ]               Get s
                 <;.1~          Chop s where a 1 occurs to get the runs in s
    #@>                         Get the length of each run
  <.                            Take the min of the length and k
         {.@>@]                 Get the head of each run
        #                       Copy the head of each run min(k, len(run)) times
                                Return that string as the result

0

Dyalog APL , 22 20 bytes

(∊⊢↑¨⍨⎕⌊⍴¨)⊢⊂⍨1,2≠/⊢

Solicita ne aceita a string de entrada como argumento.

(a função tácita ...
    ∊achatar
    ⊢↑¨⍨cada elemento do argumento (ou seja, cada partição) truncado para
    ⎕⌊⍴¨o mínimo da entrada numérica e o comprimento atual
)[final da função tácita] aplicado à
⊢⊂⍨entrada particionada nos ᴛʀᴜᴇ s de
1, ᴛʀᴜᴇ prefixados a (o primeiro caractere não é igual ao seu antecessor não existente)
2≠/⊢o par não é igual a caracteres na entrada



-1

TCC, 7 5 bytes

$~(;)

Entrada é uma sequência e um número, separados por espaço.

Experimente online!

       | Printing is implicit
$~     | Limit occurence
  (;   | First part of input
    )  | Second part of input

1
Nenhuma revisão de sua resposta funcionou com o tcc.luaarquivo com carimbo de data / hora 16-07-25 16:57 UTC, que não tinha a capacidade de ler várias entradas de uma só vez. Se sua resposta exigir uma versão do idioma que pós-desafio, você deve rotulá-la como não concorrente no cabeçalho. Vou remover meu voto negativo quando você o fizer.
— Dennis
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.