Truncar el carácter consecutivo se ejecuta en n longitud

14

El reto

Dada una cadena de entrada y un número entero n : trunca cualquier ejecución de caracteres consecutivos hasta un máximo de n de longitud. Los caracteres pueden ser cualquier cosa, incluidos los caracteres especiales. La función debe ser sensible a mayúsculas y n puede variar de 0 a infinito.

Ejemplo de entradas / salidas:

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

Puntuación

La puntuación se basa en el número de bytes utilizados. Así

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

Sería 104 puntos.

¡Feliz golf!

Editar: se eliminó la restricción de idioma, pero aún me encantaría ver las respuestas de JavaScript

TestSubject06
fuente
1
¿Por qué no permitir ES6?
TuxCrafting
77
Recomiendo perder el requisito de idioma. Javascript es uno de los idiomas más comunes aquí. La auto respuesta con lo que obtuviste probablemente invitaría a la gente a ayudarte a jugar golf, o trataría de golpearte con otro enfoque. Además, si obtiene suficiente reputación, puede agregar una recompensa a la pregunta con un lenguaje específico en mente. Si eso no le sienta bien, puede modificar esta pregunta en una pregunta de consejos e intentar solicitar ayuda específica para jugar al golf.
FryAmTheEggman
Se eliminó la restricción de idioma y se modificaron las reglas de puntuación como resultado. Todavía me encantaría ver las entradas de JavaScript, pero creo que puedo vivir con algunos idiomas de golf de 4-5 caracteres.
TestSubject06
¡Bienvenido a Programming Puzzles & Code Golf! Los desafíos de golf de código se puntúan por longitud en bytes de forma predeterminada. Si bien la puntuación por longitud en caracteres es posible, seguramente obtendrá algunas respuestas como esta .
Dennis
Oh Dios. Cambiado a la puntuación de bytes.
TestSubject06

Respuestas:

6

Python 2, 52 bytes

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

Escrito como un programa (54 bytes):

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

Itera a través de la cadena de entrada s, agregando cada carácter a la cadena de salida a rmenos que los últimos ncaracteres de rsean ese carácter.

Pensé que esto fallaría n==0porque r[-0:]no son los últimos 0 caracteres (cadena vacía), sino la cadena completa. Pero funciona porque la cadena permanece vacía, por lo que sigue coincidiendo con la cadena de 0 caracteres.

Un recursivo lambdadio 56 debido a la repetición

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

Una estrategia alternativa para mantener un contador ide repeticiones del último personaje también resultó más larga que simplemente verificar los últimos npersonajes directamente.

xnor
fuente
6

C, 81 78

Modifica la cadena entrante.

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 prueba

Requiere dos parámetros, el primero es la cadena para truncar, el segundo es el límite de longitud.

#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;
}

Explicación:

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.

Esto funciona porque el puntero de origen siempre será igual o mayor que el puntero de destino, por lo que podemos escribir sobre la cadena a medida que la analizamos.

owacoder
fuente
Esto es asombroso, ¿puedes explicarlo?
TestSubject06
@ TestSubject06: se agregó una explicación.
owacoder
¿Funciona esto con el caso n = 0? No puedo hacer que compile para probar aquí.
TestSubject06
Si lo hace. Agregué un programa de prueba para que puedas compilar.
owacoder
Impresionante, no pude encontrar ningún contador de ejemplos. Corto y funciona!
TestSubject06
5

Haskell, 36 bytes

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

Versión sin puntos de \n s -> concatMap (take n) (group s).

Lynn
fuente
4

Javascript ES6, 60 54 55 43 bytes

-12 bytes gracias a @ TestSubject06 y @Downgoat

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

Ejecuciones de ejemplo:

f("aaaaaaabbbccCCCcc"      , 2) -> "aabbccCCcc" 
f("aaabbbc"                , 1) -> "abc"
f("abcdefg"                , 0) -> ""
f("aaaaaaabccccccccCCCCCC@", 4) -> "aaaabccccCCCC@"
f("a"                      , 1) -> "a"
Dendrobium
fuente
f ("a", 1) -> ""
TestSubject06
1
Dado que su RegExp no se controla dinámicamente de ninguna manera, puede guardar algunos bytes con RegExp ("(.) \\ 1 *", "g") -> /(.)\1*/g
TestSubject06
1
Convierte RegExp("(.)\\1*","g")a/(.)\1*/g
Downgoat
1
No veo que esto se haga más pequeño en JS a menos que lo hagamos desde un ángulo completamente diferente. Buen trabajo @Dendrobium!
TestSubject06
1
Afeitarse un byte cambiando (s,n)a s=>n, y el uso se vuelvef("aaaaaaabbbccCCCcc")(2)
Patrick Roberts
3

MATL, 9 bytes

Y'i2$X<Y"

Pruébalo en línea

Explicación

        % 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
fuente
'@@@@@ bbbbbcccddeegffsassss' 3 devolvió '@@@ bbbcccddeegffsass' al que le falta la 's' final
TestSubject06
@ TestSubject06 Gracias por señalarlo.
Suever
2

CJam, 12 bytes

{e`\af.e<e~}

Pruébalo en línea!

Explicación

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
fuente
2

Python 2, 56 bytes

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

gs2, 6 bytes

Codificado en CP437 :

╠c╨<ΘΣ

Esta es una función anónima (bloque) que espera un número en la parte superior de la pila y una cadena debajo de ella.

     Σ   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.

Pruébalo en línea. (El código aquí es lines, dump, read number, [the answer], run-block).

Lynn
fuente
1

Perl 6 ,  38  36 bytes

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

Explicación:

-> $_, \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
  }/
}

Prueba:

#! /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
fuente
0

Javascript ES5, 73

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

Reutiliza la expresión regular de Lynn de su respuesta de Python .

FryAmTheEggman
fuente
Su código no maneja el caso donde n es cero, solo devuelve la cadena original completa.
TestSubject06
Sí, en Firefox, puede soltar los corchetes y la declaración de devolución , aunque esa sintaxis está (lamentablemente) en desuso y se eliminará (en realidad estuvo ausente algunas versiones, no se dio cuenta de que la trajeron de vuelta).
Dendrobium
También puede soltar la newpalabra clave por -4 bytes.
Dendrobium
@ TestSubject06 Gracias, he editado mi respuesta y creo que ahora pasa los casos de prueba.
FryAmTheEggman
0

Perl 5, 50 bytes

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

Toma el número para truncar a través de -i.

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

Uso

perl -i4 -pe 's!(.)\1+!$&=~s/(.{$^I}).+/$1/r!ge' <<< 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@
Dom Hastings
fuente
¿Por qué -psolo hay un byte?
someonewithpc
@someonewithpc cuando se puede combinar con -eestas opciones solo consume 1 byte. Si el script tiene que ejecutarse desde un archivo, cuesta 3 por el espacio y se marca. Hay una meta publicación que intentaré encontrar pero ahora estoy en el móvil.
Dom Hastings
0

Bash 46 bytes

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

Uso: Ingrese el número de caracteres a limitar, presione enter e ingrese la cadena. Ctrl+ Dpara salir sed(enviar EOF).

alguien con pc
fuente
0

Java 7, 107106 bytes

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

Alternativa anterior en línea for-loop para la concatenación de cadenas (que es 1 byte más que String s="";for(int i=-1;++i<j;)s+="$1";desafortunadamente):

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

Sin golf y casos de prueba:

Pruébalo aquí.

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

Salida:

aabbccCCcc
abc

aaaabccccCCCC@
@@@@@bbbbbcccddeegffsassss
Kevin Cruijssen
fuente
0

Javascript (usando una 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

Enlace a lib: https://github.com/mvegh1/Enumerable

Explicación del código: cargue la cadena en la biblioteca, que se analiza internamente como matriz de caracteres. Aplique un acumulador en la secuencia, pasando un objeto personalizado como valor inicial. La propiedad a es el elemento actual, b es la cadena acumulada y c es el recuento secuencial del elemento actual. El acumulador verifica si el valor de iteración actual, n, es igual al último valor del elemento, ca Si no, restablecemos el recuento a 1 y establecemos el elemento actual. Si el recuento del elemento actual es menor o igual que la longitud deseada, lo acumulamos en la cadena de retorno. Finalmente, devolvemos la propiedad b, la cadena acumulada. No es el código más golfista, pero feliz de haber obtenido una solución que funciona ...

ingrese la descripción de la imagen aquí

applejacks01
fuente
0

J, 31 30 bytes

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

Agrupa la cadena de entrada en corridas (subcadenas) de caracteres idénticos y toma el mínimo de la longitud de esa corrida y la longitud máxima que se ingresó para truncar la cadena. Luego copia el primer personaje de cada carrera tantas veces.

Uso

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

   4 f 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@

Explicación

((<.#@>)#{.@>@])]<;.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
millas
fuente
0

Dyalog APL , 22 20 bytes

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

Solicita n toma la cadena de entrada como argumento.

(la función tácita ...
    aplanar
    ⊢↑¨⍨cada elemento del argumento (es decir, cada partición) truncado al
    ⎕⌊⍴¨mínimo de la entrada numérica y la longitud actual
)[final de la función tácita] aplicada a
⊢⊂⍨la entrada particionada en los ᴛʀᴜᴇ s de
1, ᴛʀᴜᴇ antepuestos a (el primer carácter no es igual a su predecesor no existente)
2≠/⊢el par de caracteres no iguales en la entrada

Adán
fuente
0

Ruby, 32 bytes

->s,n{s.gsub(/(.)\1*/){$&[0,n]}}
Jordán
fuente
-1

TCC, 7 5 bytes

$~(;)

La entrada es una cadena y un número, separados por espacio.

Pruébalo en línea!

       | Printing is implicit
$~     | Limit occurence
  (;   | First part of input
    )  | Second part of input
brianush1
fuente
1
Ninguna de las revisiones de su respuesta funcionó con el tcc.luaarchivo con marca de tiempo 16-07-25 16:57 UTC, que no tenía la capacidad de leer múltiples entradas a la vez. Si su respuesta requiere una versión del idioma posterior al desafío, debe etiquetarla como no competitiva en el encabezado. Eliminaré mi voto negativo cuando lo hagas.
Dennis