Tronquer les séquences de caractères consécutives à n longueurs

14

Le défi

Étant donné une chaîne d'entrée et un entier n - tronquez toute série de caractères consécutifs jusqu'à une longueur maximale de n . Les caractères peuvent être n'importe quoi, y compris des caractères spéciaux. La fonction doit être sensible à la casse et n peut aller de 0 à l'infini.

Exemples d'entrées / sorties:

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

Notation

La notation est basée sur le nombre d'octets utilisés. Donc

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

serait de 104 points.

Bon golf!

Edit: suppression de la restriction de langue, mais j'aimerais toujours voir les réponses javascript

TestSubject06
la source
1
Pourquoi ne pas autoriser ES6?
TuxCrafting
7
Je recommanderais de perdre l'exigence linguistique. Javascript est l'une des langues les plus courantes ici. Répondre à vous-même avec ce que vous avez obtenu inviterait probablement des gens à vous aider à jouer au golf ou à essayer de vous battre avec une autre approche. De plus, si vous obtenez suffisamment de réputation, vous pouvez ajouter une prime à la question avec une langue spécifique à l'esprit. Si cela ne vous convient pas, vous pouvez modifier cette question en une question de conseils et essayer de demander une aide spécifique au golf.
FryAmTheEggman
Suppression de la restriction de langue et modification des règles de notation en conséquence. J'aimerais toujours voir les entrées javascript, mais je suppose que je peux vivre avec des langues de golf de 4 à 5 caractères.
TestSubject06
Bienvenue sur Programmation Puzzles & Code Golf! Les défis de golf de code sont marqués par longueur en octets par défaut. Bien que la notation par longueur en caractères soit possible, vous obtiendrez certainement des réponses comme celle-ci .
Dennis
Oh mon Dieu. Changé en notation octet.
TestSubject06

Réponses:

6

Python 2, 52 octets

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

Écrit en tant que programme (54 octets):

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

Itère à travers la chaîne d'entrée s, en ajoutant chaque caractère à la chaîne de sortie, rsauf si les derniers ncaractères de rsont ce caractère.

Je pensais que cela échouerait n==0car ce r[-0:]n'est pas les 0 derniers caractères (chaîne vide), mais la chaîne entière. Mais, cela fonctionne parce que la chaîne reste vide, donc elle continue de correspondre à la chaîne de 0 caractères.

Un récursif a lambdadonné 56 à cause de la répétition

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

Une stratégie alternative pour garder un compteur ide répétitions du dernier caractère s'est également avérée plus longue que la simple vérification ndirecte des derniers caractères.

xnor
la source
6

C, 81 78

Modifie la chaîne 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;}

Programme de test

Nécessite deux paramètres, le premier est la chaîne à tronquer, le second est la longueur limite.

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

Explication:

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.

Cela fonctionne car le pointeur source sera toujours égal ou supérieur au pointeur de destination, nous pouvons donc écrire sur la chaîne pendant que nous l'analysons.

owacoder
la source
C'est incroyable, pouvez-vous l'expliquer?
TestSubject06
@ TestSubject06 - Ajout d'une explication.
owacoder
Est-ce que cela fonctionne avec le cas n = 0? Je n'arrive pas à le compiler pour le tester ici.
TestSubject06
Oui. J'ai ajouté un programme de test pour que vous puissiez compiler.
owacoder
Génial, je n'ai trouvé aucun contre-exemple. Bref et ça marche!
TestSubject06
5

Haskell, 36 octets

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

Version sans point de \n s -> concatMap (take n) (group s).

Lynn
la source
4

Javascript ES6, 60 54 55 43 octets

-12 octets grâce à @ TestSubject06 et @Downgoat

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

L'exemple s'exécute:

f("aaaaaaabbbccCCCcc"      , 2) -> "aabbccCCcc" 
f("aaabbbc"                , 1) -> "abc"
f("abcdefg"                , 0) -> ""
f("aaaaaaabccccccccCCCCCC@", 4) -> "aaaabccccCCCC@"
f("a"                      , 1) -> "a"
Dendrobium
la source
f ("a", 1) -> ""
TestSubject06
1
Étant donné que votre RegExp n'est en aucun cas contrôlé dynamiquement, vous pouvez enregistrer quelques octets avec RegExp ("(.) \\ 1 *", "g") -> /(.)\1*/g
TestSubject06
1
Convertir RegExp("(.)\\1*","g")vers/(.)\1*/g
Downgoat
1
Je ne vois pas cela devenir plus petit dans JS, sauf si nous y arrivons sous un angle complètement différent. Bon travail @Dendrobium!
TestSubject06
1
Rasez un octet en changeant (s,n)en s=>n, et l'utilisation devientf("aaaaaaabbbccCCCcc")(2)
Patrick Roberts
3

MATL, 9 octets

Y'i2$X<Y"

Essayez-le en ligne

Explication

        % 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
la source
'@@@@@ bbbbbcccddeegffsassss' 3 a retourné '@@@ bbbcccddeegffsass' qui manque la finale '
TestSubject06
@ TestSubject06 Merci de l'avoir signalé.
Suever
2

CJam, 12 octets

{e`\af.e<e~}

Essayez-le en ligne!

Explication

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
la source
2

Python 2, 56 octets

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

gs2, 6 octets

Encodé en CP437 :

╠c╨<ΘΣ

Il s'agit d'une fonction anonyme (bloc) qui attend un nombre en haut de la pile et une chaîne en dessous.

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

Essayez-le en ligne. (Le code ici est lines, dump, read number, [the answer], run-block.)

Lynn
la source
1

Perl 6 ,  38  36 octets

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

Explication:

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

Tester:

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

Javascript ES5, 73

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

Réutilise l'expression régulière de Lynn à partir de sa réponse Python .

FryAmTheEggman
la source
Votre code ne gère pas le cas où n est zéro, il renvoie simplement la chaîne d'origine entière.
TestSubject06
Oui, dans Firefox, vous pouvez supprimer les accolades et la déclaration de retour , bien que cette syntaxe soit (malheureusement) obsolète et sera supprimée (elle était en fait absente de quelques versions, je ne savais pas qu'elles l'avaient ramenée).
Dendrobium du
Vous pouvez également supprimer le newmot clé pour -4 octets.
Dendrobium
@ TestSubject06 Merci, j'ai édité ma réponse et je crois qu'elle passe les cas de test maintenant.
FryAmTheEggman
0

Perl 5, 50 octets

Code de 46 octets + 3 pour -iet 1 pour-p

Prend le nombre à tronquer à via -i.

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

Usage

perl -i4 -pe 's!(.)\1+!$&=~s/(.{$^I}).+/$1/r!ge' <<< 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@
Dom Hastings
la source
Pourquoi -pun seul octet?
someonewithpc
@someonewithpc lorsqu'il peut être combiné avec -eces options ne consomme que 1 octet. Si le script doit être exécuté à partir d'un fichier, il en coûte 3 pour l'espace et il se marque lui-même. Il y a une méta-publication que j'essaierai de trouver, mais je suis actuellement sur mobile.
Dom Hastings
0

Bash 46 octets

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

Utilisation: Entrez le nombre de caractères à limiter, appuyez sur Entrée et entrez la chaîne. Ctrl+ Dpour quitter sed(envoyer EOF).

quelqu'un avec pc
la source
0

Java 7, 107 106 octets

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

Alternative précédente pour la boucle en ligne pour la concaténation de chaînes (qui est 1 octet de plus que String s="";for(int i=-1;++i<j;)s+="$1";malheureusement):

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

Cas non testés et testés:

Essayez-le ici.

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

Production:

aabbccCCcc
abc

aaaabccccCCCC@
@@@@@bbbbbcccddeegffsassss
Kevin Cruijssen
la source
0

Javascript (en utilisant une bibliothèque externe) (115 octets)

(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

Lien vers la bibliothèque: https://github.com/mvegh1/Enumerable

Explication du code: chargez la chaîne dans la bibliothèque, qui analyse en interne en tant que tableau de caractères. Appliquez un accumulateur sur la séquence, en passant un objet personnalisé comme valeur de départ. La propriété a est l'élément actuel, b est la chaîne accumulée et c est le nombre séquentiel de l'élément actuel. L'accumulateur vérifie si la valeur d'itération actuelle, n, est égale à la dernière valeur d'élément, ca Sinon, nous remettons le compte à 1 et définissons l'élément actuel. Si le compte de l'élément courant est inférieur ou égal à la longueur souhaitée, nous l'accumulons dans la chaîne de retour. Enfin, nous retournons la propriété b, la chaîne accumulée. Pas le code le plus golfique, mais heureux d'avoir une solution qui fonctionne ...

enter image description here

applejacks01
la source
0

J, 31 30 octets

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

Regroupe la chaîne d'entrée en exécutions (sous-chaînes) de caractères identiques et prend le minimum de la longueur de cette exécution et la longueur maximale qui a été entrée pour tronquer la chaîne. Copie ensuite le premier caractère de chaque manche autant de fois.

Usage

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

   4 f 'aaaaaaabccccccccCCCCCC@'
aaaabccccCCCC@

Explication

((<.#@>)#{.@>@])]<;.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
miles
la source
0

Dyalog APL , 22 20 octets

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

Invite pour n et prend la chaîne d'entrée comme argument.

(la fonction tacite ...
    aplatit
    ⊢↑¨⍨chaque élément de l'argument (c'est-à-dire chaque partition) tronqué au
    ⎕⌊⍴¨minimum de l'entrée numérique et la longueur actuelle
)[fin de la fonction tacite] appliquée à
⊢⊂⍨l'entrée partitionnée aux ᴛʀᴜᴇ s de
1, ᴛʀᴜᴇ précédée de (la le premier caractère n'est pas égal à son prédécesseur non existant)
2≠/⊢le couple non égal de caractères dans l'entrée

Adam
la source
0

Rubis, 32 octets

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

TCC, 7 5 octets

$~(;)

L'entrée est une chaîne et un nombre, séparés par un espace.

Essayez-le en ligne!

       | Printing is implicit
$~     | Limit occurence
  (;   | First part of input
    )  | Second part of input
brianush1
la source
1
Aucune des révisions de votre réponse n'a fonctionné avec le tcc.luafichier avec horodatage 16-07-25 16:57 UTC, qui n'avait pas la possibilité de lire plusieurs entrées à la fois. Si votre réponse nécessite une version de la langue postérieure au défi, vous devez la marquer comme non concurrente dans l'en-tête. Je supprimerai mon downvote quand vous le ferez.
Dennis