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

TestSubject06
fonte
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.

xnor
fonte
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.

owacoder
fonte
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).

Lynn
fonte
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"
Dendrobium
fonte
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
Suever
fonte
'@@@@@ 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.
Martin Ender
fonte
2

Python 2, 56 bytes

import re
lambda s,n:re.sub(r'(.)(\1{%d})\1*'%n,r'\2',s)
Lynn
fonte
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.)

Lynn
fonte
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@"
Brad Gilbert b2gills
fonte
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 .

FryAmTheEggman
fonte
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@
Dom Hastings
fonte
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).

someonewithpc
fonte
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
Kevin Cruijssen
fonte
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

applejacks01
fonte
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
milhas
fonte
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

Adão
fonte
0

Ruby, 32 bytes

->s,n{s.gsub(/(.)\1*/){$&[0,n]}}
Jordânia
fonte
-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
brianush1
fonte
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