Tronca sequenze di caratteri consecutivi a n lunghezza


14

La sfida

Data una stringa di input e un numero intero n - tronca qualsiasi sequenza di caratteri consecutivi ad un massimo di n lunghezza. I personaggi possono essere qualsiasi cosa, compresi i caratteri speciali. La funzione dovrebbe fare distinzione tra maiuscole e minuscole e n può variare da 0 a infinito.

Esempi di ingressi / uscite:

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

punteggio

Il punteggio si basa sul numero di byte utilizzati. così

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

sarebbe 104 punti.

Buon golf!

Modifica: rimossa la restrizione linguistica, ma mi piacerebbe comunque vedere le risposte javascript


1
Perché non consentire ES6?
TuxCrafting

7
Consiglierei di perdere il requisito linguistico. Javascript è una delle lingue più comuni qui. La risposta autonoma a ciò che hai probabilmente inviterebbe le persone ad aiutarti a giocare a golf, o proverebbe a batterti con un altro approccio. Inoltre, se hai abbastanza reputazione puoi aggiungere una generosità alla domanda con una lingua specifica in mente. Se questo non ti soddisfa, potresti modificare questa domanda in una domanda di suggerimenti e provare a chiedere aiuto specifico per il golf.
FryAmTheEggman,

Rimossa la limitazione della lingua e di conseguenza le regole di punteggio modificate. Mi piacerebbe ancora vedere le voci javascript, ma immagino di poter vivere con alcune lingue da golf di 4-5 caratteri.
TestSubject06

Benvenuto in Programmazione di puzzle e codice golf! Per impostazione predefinita, le sfide del codice golf sono assegnate in base alla lunghezza in byte . Mentre è possibile segnare per lunghezza nei personaggi , sei obbligato a ottenere alcune risposte come questa .
Dennis,

Oh Dio. Modificato in punteggio byte.
TestSubject06

Risposte:


6

Python 2, 52 byte

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

Scritto come programma (54 byte):

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

Scorre la stringa di input s, aggiungendo ogni carattere alla stringa di output a rmeno che gli ultimi ncaratteri di non rsiano quel carattere.

Ho pensato che questo avrebbe fallito n==0perché r[-0:]non sono gli ultimi 0 caratteri (stringa vuota), ma l'intera stringa. Funziona perché la stringa rimane vuota, quindi continua a corrispondere alla stringa di 0 caratteri.

Un ricorsivo ha lambdadato 56 a causa della ripetizione

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

Una strategia alternativa per mantenere un contatore idi ripetizioni dell'ultimo personaggio si è rivelata più lunga del semplice controllo ndiretto degli ultimi personaggi.


6

C, 81 78

Modifica la stringa in arrivo.

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

Programma di test

Richiede due parametri, il primo è la stringa da troncare, il secondo è il limite di lunghezza.

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

Spiegazione:

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.

Questo funziona perché il puntatore di origine sarà sempre uguale o maggiore del puntatore di destinazione, quindi possiamo scrivere sulla stringa mentre la analizziamo.


È fantastico, puoi spiegarlo?
TestSubject06

@ TestSubject06 - Aggiunta una spiegazione.
owacoder,

Funziona con il caso n = 0? Non riesco a compilare per testare qui.
TestSubject06

Sì, lo fa. Ho aggiunto un programma di test in modo da poterlo compilare.
owacoder,

Fantastico, non sono riuscito a trovare nessun esempio contatore. Corto e funziona!
TestSubject06

5

Haskell, 36 byte

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

Versione senza punti di \n s -> concatMap (take n) (group s).


4

Javascript ES6, 60 54 55 43 byte

-12 byte grazie a @ TestSubject06 e @Downgoat

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

Esempi di esecuzione:

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

f ("a", 1) -> ""
TestSubject06

1
Poiché RegExp non è controllato in modo dinamico in alcun modo, è possibile salvare alcuni byte con RegExp ("(.) \\ 1 *", "g") -> /(.)\1*/g
TestSubject06

1
Converti RegExp("(.)\\1*","g")in/(.)\1*/g
Downgoat l'

1
Non vedo che questo si riduce in JS a meno che non ci arriviamo da una prospettiva completamente diversa. Ottimo lavoro @Dendrobium!
TestSubject06

1
Radere un byte cambiando (s,n)in s=>ne l'uso diventaf("aaaaaaabbbccCCCcc")(2)
Patrick Roberts il

3

MATL, 9 byte

Y'i2$X<Y"

Provalo online

Spiegazione

        % 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 ha restituito '@@@ bbbcccddeegffsass' a cui mancano le 's'
finali

@ TestSubject06 Grazie per averlo sottolineato.
Suever,

2

CJam, 12 byte

{e`\af.e<e~}

Provalo online!

Spiegazione

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 byte

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

2

gs2, 6 byte

Codificato in CP437 :

╠c╨<ΘΣ

Questa è una funzione anonima (blocco) che prevede un numero in cima allo stack e una stringa sotto di esso.

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

Provalo online. (Il codice qui è lines, dump, read number, [the answer], run-block.)


1

Perl 6 ,  38  36 byte

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

Spiegazione:

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

Test:

#! /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")}

Riutilizza la regex di Lynn dalla sua risposta Python .


Il tuo codice non gestisce il caso in cui n è zero, restituisce solo l'intera stringa originale.
TestSubject06

Yes, in Firefox, you can drop the braces and return statement, although that syntax is (sadly) deprecated and will be removed (it was actually absent a few versions back, didn't realize they brought it back).
Dendrobium

You can also drop the new keyword for -4 bytes.
Dendrobium

@TestSubject06 Thanks, I've edited my answer and I believe it passes the test cases now.
FryAmTheEggman

0

Perl 5, 50 bytes

46 bytes code + 3 for -i and 1 for -p

Takes the number to truncate to via -i.

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

Usage

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

Why is -p only one byte?
someonewithpc

@someonewithpc when it can be combined with the -e these options only consume 1 byte. If the script has to be run from a file it costs 3 for the space and he flag itself. There's a meta post I'll try and find but I'm on mobile right now.
Dom Hastings


0

Bash 46 bytes

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

Usage: Enter the number of characters to limit, press enter and enter the string. Ctrl + D to exit sed (send 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);}

Previous alternative inline for-loop for String concatenation (which is 1 byte more than String s="";for(int i=-1;++i<j;)s+="$1"; unfortunately):

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

Ungolfed & test cases:

Try it here.

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

Output:

aabbccCCcc
abc

aaaabccccCCCC@
@@@@@bbbbbcccddeegffsassss

0

Javascript (using external library) (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 to lib: https://github.com/mvegh1/Enumerable

Code explanation: Load the string into library, which internally parses as char array. Apply an accumulator on the sequence, passing in a custom object as a seed value. Property a is the current element, b is the accumulated string, and c is the sequential count of the current element. The accumulator checks if the current iteration value, n, is equal to the last element value, c.a. If not, we reset the count to 1 and set the current element. If the count of the current element is less than or equal to the desired length, we accumulate it to the return string. Finally, we return property b, the accumulated string. Not the golfiest code, but happy I got a solution that works...

enter image description here


0

J, 31 30 bytes

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

Groups the input string into runs (substrings) of identical characters, and takes the minimum of the length of that run and the max length that was input for truncating the string. Then copies the first character of each run that many times.

Usage

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

   4 f 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@

Explanation

((<.#@>)#{.@>@])]<;.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≠/⊢

Prompts for n and takes input string as argument.

( the tacit function ...
     flatten
    ⊢↑¨⍨ each element of the argument (i.e. each partition) truncated to
    ⎕⌊⍴¨ the minimum of the numeric input and the current length
) [end of tacit function] applied to
⊢⊂⍨ the input partitioned at the ᴛʀᴜᴇs of
1, ᴛʀᴜᴇ prepended to (the first character is not equal to its non-extant predecessor)
2≠/⊢ the pair-wise not-equal of characters in the input


0

Ruby, 32 bytes

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

-1

TCC, 7 5 bytes

$~(;)

Input is a string and a number, seperated by space.

Try it online!

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

1
Neither revision of your answer worked with the tcc.lua file with timestamp 16-07-25 16:57 UTC, which didn't have the ability to read multiple inputs at once. If your answer requires a version of the language that postdates the challenge, you must label it as non-competing in the header. I'll remove my downvote when you do.
Dennis
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.