Course la plus longue d'un caractère dans une chaîne


19

Votre défi: écrire une fonction qui prend une chaîne s, un caractère cet trouve la longueur de la plus longue séquence de cin s. La longueur de la course sera l.

Règles :

  • Si sest de longueur 0 ou cvide, ldevrait être 0.
  • S'il n'y a aucune instance de cin s, ldevrait être 0.
  • Échappatoires standard et standard Règles d' E / S sont applicables.
  • Peu importe où se trouve sla série de cs, ldevrait être le même.
  • Tous les caractères ASCII imprimables peuvent apparaître dans set c.

Cas de test :

s,c --> l
"Hello, World!",'l'  -->  2
"Foobar",'o'         -->  2
"abcdef",'e'         -->  1
"three   spaces",' ' -->  3
"xxx xxxx xx",'x'    -->  4
"xxxx xx xxx",'x'    -->  4
"",'a'               -->  0
"anything",''        -->  0

Gagnant :

Comme avec le la réponse la plus courte dans chaque langue l'emporte.



Pourriez-vous inclure les cas de bord de vide set un cqui n'est pas contenu dans un non-vide sdans vos cas de test?
Martin Ender

Quelle plage de caractères peut apparaître dans s/ c?
Martin Ender

6
cpeut être vide? Dans de nombreuses langues, un caractère n'est qu'un entier avec une sémantique spéciale, et vous ne pouvez pas non plus avoir vraiment un entier vide.
Martin Ender

14
Cela n'a pas vraiment de sens pour moi. Vos cas de test suggèrent que nous devons le soutenir. Si nous n'avons pas à le prendre en charge, alors spécifier sa sortie requise n'a pas de sens, car je peux toujours dire que ce n'est pas pris en charge si ma solution ferait autre chose dans ce cas.
Martin Ender

Réponses:


12

05AB1E , 5 octets

Code:

SQγOM

Utilise l' encodage 05AB1E . Essayez-le en ligne!

Explication:

SQ      # Check for each character if it is equal to the second input
  γ     # Split the list of zeros and ones into groups
   O    # Sum each array in the arrays
    M   # Get the maximum

2
Bonne solution! Je savais qu'il y avait un moyen de le faire comme ça, je n'y pensais tout simplement pas.
Riley

γ¢Mne fonctionne pas comme je le pensais, pensait que ce serait un 3 octets.
Magic Octopus Urn

8

Mathematica, 35 octets

Max[Tr/@Split@Boole@Thread[#==#2]]&

Fonction pure prenant une liste de caractères et un autre caractère en entrée et retournant un entier non négatif. Amélioré lors de mon premier effort en utilisant l'observation d'Adnan (montez les votes!) Que l'on devrait tester pour égaliser le caractère spécial avant de diviser le tableau.

Thread[#==#2]vérifie si chaque caractère d'entrée dans le premier argument est égal au caractère donné comme deuxième argument. Booleconvertit les Trues et Falses résultants en 1s et 0s. Splitdivise la liste en séries d'éléments consécutifs; Tr/@additionne chaque sous-liste et Maxtrouve le gagnant. (En raison de la façon dont Maxfonctionne, si le premier argument est la liste vide, cette fonction retourne -∞. Donc, vous savez, ne faites pas cela.)

première soumission (51 octets)

Max[Split@#/.a:{c_String..}:>Boole[c==#2]Length@a]&

Split@#divise l'entrée en séries de caractères consécutifs, comme {{"t"}, {"h"}, {"r"}, {"e", "e"}, {" ", " ", " "}, {"s"}, {"p"}, {"a"}, {"c"}, {"e"}, {"s"}}pour le quatrième cas de test. /.a:{c_String..}:>remplace chaque sous - expression aqui est une liste d'un caractère répété cpar Length@amultiplié par Boole[c==#2], ce qui est le 1cas cest égal au caractère d'entrée et 0autrement. MaxExtrait ensuite la réponse.


7

Japt , 20 18 15 octets

fV+Vî+)ª0)n o l

Essayez-le en ligne!

5 octets enregistrés grâce à obarakon et aux productions ETH


1
J'ai joué avec ma propre solution pendant un certain temps et je me suis retrouvé avec une solution qui était presque la vôtre, mais plus courte. Si vous utilisez fV+Vî+)... je vous laisse comprendre le reste :-)
ETHproductions

@ETHproductions "If s is of length 0 or c is empty, l should be 0", je pourrais peut-être prendre cela trop à la lettre
Tom

Oh, je ne m'étais pas rendu compte que cela échoue chaque fois squ'il ne contient aucun exemple de c.
ETHproductions

7

Python , 38 octets

f=lambda s,c:+(c in s)and-~f(s,c+c[0])

Essayez-le en ligne!

Dennis a économisé 3 octets en mettant cà jour une chaîne de caractères dupliqués plutôt qu'en mettant à jour récursivement un nombre à multiplier cpar.


1
f=lambda s,c:c in s and-~f(s,c+c[0])enregistre 6 octets (3 si False n'est pas autorisé).
Dennis


4

Haskell, 43 39 octets

f c=maximum.scanl(\n k->sum[n+1|c==k])0

Essayez-le en ligne!

Parcourez la chaîne et remplacez le caractère actuel par un compteur qui augmente chaque fois qu'il est égal cou réinitialisé dans le 0cas contraire. Prenez le maximum de la liste.

Merci à @xnor pour 4 octets.


Tu peux le faire sum[n+1|c==k].
xnor

@xnor: Nice! J'ai expérimenté *fromEnum(c==k), à la fois sans point et lambda, mais c'était toujours 2 ou 3 octets de plus.
nimi

4

C # 116 115 octets

Mon premier code golf

Modifié car la soumission initiale était un extrait de code et il manquait l'espace de noms requis pour l'expression régulière

Modifier la réécriture complète n ° 2 pour prendre en charge les caractères avec des significations regex spéciales

en utilisant System.Linq; s => c => System.Text.RegularExpressions.Regex.Replace (s, "[^" + c + "]", ++ c + ""). Split (c) .Max (x => x.Longueur);

using System.Linq;s=>c=>{var r=(char)(c-1);return string.Join("",s.Select(x=>x==c?c:r)).Split(r).Max(x=>x.Length)};

3
Je ne connais pas C # mais il semble que votre code attend des variables cet squ'il soit prédéfini. Nous appelons cela un "extrait de code" et ce n'est pas autorisé. Vous pourriez probablement restructurer votre code en tant que fonction anonyme ou définir ces variables à saisir. Les deux sont autorisés.
Wheat Wizard

Est-ce que ça marche? (Voir la modification ci-dessus)
Broom

1
Encore une fois, je ne connais pas C #, mais il semble que ce soit le cas. Vous voudrez peut-être consulter nos conseils pour jouer au golf en C # ici pour des conseils plus expérimentés en C #.
Wheat Wizard

Merci pour les liens! Je vais certainement parcourir les conseils C #
Broom

3
Salut juste quelques commentaires généraux pour jouer au golf en C #, vous pouvez définir votre fonction comme (s,c)=>. Vous devez soit utiliser System.Text.RegularExpressions.Regexsoit ajouter une instruction using juste avant votre fonction.
LiefdeWen

4

JavaScript (ES6), 54 53 51 octets

-2 octets grâce à @Neil
-1 octets grâce à @apsillers

s=>c=>[...s].map(x=>j=(i=x==c&&i+1)>j?i:j,i=j=0)&&j

Prend entrée dans la syntaxe corroyage: f("foobar")("o").

Extrait de test

f=
s=>c=>[...s].map(x=>j=(i=x==c&&i+1)>j?i:j,i=j=0)&&j
String: <input id=I> Letter: <input id=J maxlength=1 size=1> <button onclick='O.innerHTML+=`f("${I.value}")("${J.value}") = ${f(I.value)(J.value)}\n`'>Run</button><pre id="O"></pre>

Une autre option en utilisant evalet for(54 octets)

s=>c=>eval("i=j=0;for(x of s)i=x==c&&i+1,i>j?j=i:0;j")

Ancienne réponse utilisant Regex (85 octets)

s=>c=>c?Math.max(...s.match(eval(`/${/\w/.test(c)?c:"\\"+c}*/g`)).map(x=>x.length)):0

1
Je pense que x==c?i++:i=0peut-être i=x==c&&i+1depuis un falserésultat sur la x==ccomparaison sera traitée comme 0pour les comparaisons numériques et incréments (et ne sera jamais la valeur de retour, depuis un certain nombre, y compris 0, en jsera toujours la priorité sur le zéro comme falsedans i)
apsillers

@apsillers Merci, mis à jour, mais que voulez-vous dire par le fait qu'il ne s'agit jamais de la valeur de retour?
Justin Mariner

Désolé pour la confusion; false
J'expliquais

1
s=>c=>[...s].map(x=>j=(x!=c?i=0:++i)>j?i:j,i=j=0)&&jsemble économiser quelques octets.
Neil

1
Désolé, j'ai posté le mauvais code, je voulais poster f=s=>c=>[...s].map(x=>j=(i=x==c&&i+1)>j?i:j,i=j=0)&&j, qui est un octet plus court.
Neil

4

JavaScript (Firefox 30-57), 75 72 octets

(s,c)=>Math.max(0,...(for(s of s.split(/((.)\2*)/))if(s[0]==c)s.length))

Extrait compatible ES6:

f=
(s,c)=>Math.max(0,...s.split(/((.)\2*)/).filter(s=>s[0]==c).map(s=>s.length))
<div oninput=o.textContent=f(s.value,c.value)><input id=s><input id=c maxlength=1 size=1><pre id=o>0

split renvoie un tas de chaînes vides et de caractères uniques ainsi que les exécutions mais cela n'affecte pas le résultat.


3

Micro , 112 octets

{T l m 1+:Q # T Q T l~:r}:Z{T[0]+}:X
{i s m:n
n p = if(Z,X)
i L=if(,a)}:a
0\\:C:s:i"":p"":n[0]:T
s l:L
a
T l m:\


2

Perl 6 ,  45 43  42 octets

->$_,$c {$c&&$_??.comb(/$c+/)».chars.max!!0}

Essaye-le

->$_,$c {$c&&$_??.comb(/$c+/).max.chars!!0}

Essaye-le

->$_,$c {$c&$_??.comb(/$c+/).max.chars!!0}

Essaye-le

Étendu:

-> $_, $c {       # pointy block lambda

    $c & $_       # AND junction of $c and $_
                  #   empty $c would run forever
                  #   empty $_ would return 4 ( "-Inf".chars )

  ??              # if True (neither are empty)

    .comb(/$c+/)  # find all the substrings
    .max          # find the max
    .chars        # get the length

  !!              # if False (either is empty)

    0             # return 0
}

2

JavaScript, ES6, 52

Solution récursive qui traite l'entrée de chaîne comme un tableau (remarque: l'entrée initiale est toujours une chaîne) et consomme de gauche à droite C:

f=([C,...s],c,t=0,T=0)=>C?f(s,c,C==c&&++t,t>T?t:T):T

Suit le run actuel tet le meilleur dans le monde T.

Explication:

f=            // function is stored in `f` (for recursion)
  ([C,...s],  // turn input string in first-char `C` and the rest in `s`
   c,         // argument `c` to search for
   t=0,T=0)   // current total `t`, best total `T`
     =>
        C?             // if there is still any char left in the string
          f(s,c,       // recursively call `f`
            C==c&&++t, // increment `t` if char is match, or set `t` to `false`
            t>T?t:T)   // set global `T` to max of `t` and `T`
          :T           // when string is depleted, return `T`

Le réglage tsur falseon non-matches fonctionne car chaque fois qu'il test incrémenté, falseest traité comme 0(c'est-à-dire false + 1est 1) et falsene comparera jamais la râpe à n'importe quelle valeur dans global-max T.


1
Belle solution, je ne connaissais pas la [C,...s]syntaxe. Devrait m'aider slice()hors octets de mes propres messages.
Rick Hitchcock

2

Gelée , 5 octets

=ŒgṀS

Il s'agit d'un lien / fonction dyadique qui prend une chaîne et un caractère. Notez qu'il ne peut pas fonctionner comme un programme complet, car la saisie à partir des arguments de ligne de commande utilise la syntaxe Python et Python - contrairement à Jelly - ne distingue pas les chaînes singleton des caractères.

Essayez-le en ligne!

Comment ça fonctionne

=ŒgṀS  Main link. Left argument: s (string). Right argument: c (character)

=      Compare all characters in s with c, yielding 1 for c and 0 otherwise.
 Œg    Group adjacent, equal Booleans in the resulting array.
   Ṁ   Take the maximum. Note that any array of 1's will be greater than any array
       of 0's, while two arrays of the same Booleans are compared by length.
    S  Take the sum, yielding the length for an array of 1's and 0 otherwise.


2

APL (Dyalog) , 18 11 octets

Nécessite un échange avec dans la version 16.0 ou avoir ⎕ML←3(par défaut sur plusieurs systèmes)

⌈/0,≢¨⊂⍨⎕=⎕

Essayez-le en ligne!

⎕=⎕ Booléen pour l'égalité entre deux entrées

⊂⍨ auto-partition (commencez les partitions où un élément non nul est supérieur à son prédécesseur)

≢¨ compter chacun

0, ajouter un zéro (pour les cas d'entrée vide)

⌈/ max de ceux


Ancienne solution

Demande d'abord s , puis c

⌈/0,(⎕,¨'+')⎕S 1⊢⎕

Essayez-le en ligne!

 invite pour s

 pour ça

(... )⎕S 1PCRE S echerchez pour les longueurs des occurrences de

'+' un signe plus (signifiant un ou plusieurs)

 annexé à chacun des éléments de

 l'invité- c

0, ajouter un zéro (pour les cas d'entrée vide)

⌈/ max de ceux

c doit être donné comme vecteur à 1 élément d'une chaîne fermée s'il a besoin d'être échappé.


2

PHP, 70 67 octets

trois versions:

while(~$c=$argv[1][$i++])$x=max($x,$n=($c==$argv[2])*++$n);echo+$x;
while(~$c=$argv[1][$i++])$x=max($x,$n=$c==$argv[2]?++$n:0);echo+$x;
for(;++$n&&~$c=$argv[1][$i++];)$x=max($x,$n*=$c==$argv[2]);echo+$x;

prend l'entrée des arguments de ligne de commande; courir avec -rou les tester en ligne .


2

PHP , 70 octets

for(;~$c=$argv[1][$i++];)$r[]=$argv[2]==$c?++$n:$n=0;echo$r?max($r):0;

Essayez-le en ligne!

PHP , 75 octets

for(;~$s=substr($argv[1],$i++);)$r[]=strspn($s,$argv[2]);echo max($r?:[0]);

Essayez-le en ligne!

PHP , 83 octets

<?=@preg_match_all("<".preg_quote($argv[2])."+>",$argv[1],$t)?strlen(max($t[0])):0;

Essayez-le en ligne!

+8 octets à éviter @

<?=($a=$argv[2])&&preg_match_all("<".preg_quote($a)."+>",$argv[1],$t)?strlen(max($t[0])):0;

La version 67 octets échouera pour tout caractère spécial regex (et #bien sûr).
Titus

... et ~peut échouer chr(207).
Titus

@Titus Done and Input ne peuvent être que des caractères Ascii
Jörg Hülsermann

bon oeil pour ++$n! Vous vouliez dire ascii imprimable. ;)
Titus

1
echo$r?max($r):0;enregistre un octet
Titus

2

JavaScript (ES6), 47 40 38 octets

(Enregistré 7 octets grâce à @Neil et 2 octets grâce à @HermanLauenstein.)

s=>g=c=>c&&s.includes(c)?1+g(c+c[0]):0

Explication:

Recherche récursivement une exécution plus longue jusqu'à ce qu'aucune ne soit trouvée.

Fragment:


1
Si simple! Brillant!
apsillers

Tu ne peux pas faire f=(s,c)=>c&&s.includes(c)&&1+f(s,c+c[0])?
Neil

Ou mieux encore, au curry s=>g=c=>c&&s.includes(c)&&1+g(c+c[0]).
Neil

Cela fonctionne presque, mais il renvoie "false" et une chaîne nulle pour les deux derniers cas. C'est corrigé en ajoutant ||0, ce qui est encore plus court que ma solution.
Rick Hitchcock

Le f=ne fait pas partie de la version curry, car seule la fonction interne est récursive.
Neil

2

Gelée, 10 9 octets

f⁴L
ŒgÇ€Ṁ

Explication:

f⁴L
f⁴      -Filter by the character argument.
  L     -Return Length of filtered String.

ŒgÇ€»/
Œg      -Group string by runs of characters.
  ǀ    -Run above function on each group.
    Ṁ   -Return the largest in the list.

Essayez-le en ligne!


Vous pouvez enregistrer quelques octets avec Œgf€L€Ṁ.
Dennis


1

Haskell , 66 octets

import Data.List
((maximum.(0:).map length).).(.group).filter.elem

Essayez-le en ligne!

Une version légèrement plus facile à lire - pas sans point:

f c s = maximum (0:(map length (filter (elem c) (group s))))

Regroupe la chaîne par lettre, puis filtre par les groupes qui contiennent le bon caractère, puis trouve les longueurs, ajoute 0 à la liste des longueurs au cas où il n'apparaît pas, et trouve enfin la valeur maximale.


1

Mathematica, 109 bytes

(s=Differences[First/@StringPosition[#,#2]];k=t=0;Table[If[s[[i]]==1,t++;If[k<t,k=t],t=0],{i,Length@s}];k+1)&


input

["xxx xxxx xx","x"]



1

CJam, 20 19 18 16 bytes

0q~e`f{~@=*}$+W=

Try it online!

Explanation

0                 e# Push 0. We'll need it later.
 q~               e# Read and eval input. Pushes c and s to the stack.
   e`             e# Run-length encode s: turns it into an array of [length, char] pairs.
     f{           e# Map over these pairs using c an extra parameter:
       ~          e#  Dump the pair to the stack.
        @=        e#  Bring c to the top, check equality with the char, pushing 0 or 1.
          *       e#  Multiply the length by the result.
           }      e# (end map)
            $     e# Sort the resulting list in ascending order.
             +    e# Prepend the 0 from before, in case it's empty.
              W=  e# Get the last element.

1

Excel, 56 bytes

{=MAX(IFERROR(FIND(REPT(A2,ROW(A:A)),A1)^0*ROW(A:A),0))}

s should be input to A1.
c should be input to A2.
Formula must be an array formula (Ctrl+Shift+Enter) which adds curly brackets { }.

Technically, this can only handle where the longest run is less than 1,048,576 (which is 2^20) because that's how rows the current Excel will let you have in a worksheet. Since it loads the million+ values into memory whenever it recalculates, this is not a fast formula.


1

MATL, 15 bytes

0i0v=dfd1L)0hX>

Try it online!

The basic algorithm is very simple (no use of split!), but I had to throw in 0i0v and 0h to allow for the edge cases. Still, I thought the approach was nice, and perhaps I can still find another technique to handle the edge cases: the algorithm finds the longest run in the middle of a string just fine, but not for single characters or empty strings; I'm still testing if I can 'pad' the variables at better places for better results.

0i0v % Prepends and appends a zero to the (implicit) input.
   = % Element-wise equality with the desired char (implicit input)
   d % Pairwise difference. Results in a 1 at the start of a run, and -1 at the end.
   f % Get indices of 1's and -1's.
   d % Difference to get length of the runs (as well as length of non-runs)
 1L) % Only select runs, throw out non-runs. We now have an array of all run lengths.
  0h % 'Find' (`f`) returns empty if no run is found, so append a zero to the previous array.
  X> % Maximum value.

Does not work on empty c. Then again, I suppose each string contains an infinite run of empty strings between each character :)


1

R, 66 58 bytes

-8 bytes thanks to BLT and MickyT

function(s,c)max((r=rle(el(strsplit(s,''))))$l*(r$v==c),0)

returns an anonymous function. TIO has a 1-byte difference because el doesn't work there for inexplicable reasons.

Try it online!


Save a byte with r=rle(el(strsplit(s,'')))
BLT

1
Ignore my previous comment if you saw it. Got a better one for you function(s,c)max((r=rle(el(strsplit(s,''))))$l*(r$v==c),0)
MickyT

@BLT el doesn't work on TIO (no idea why) and I just copied and pasted it from the working code there so I'll have to remember to put that back in @MickyT very clever! Thanks!
Giuseppe

1

Java 8, 67 65 bytes

s->c->{int t=0,m=0;for(char x:s)m=m>(t=x==c?t+1:0)?m:t;return m;}

-2 bytes thanks to @OlivierGrégoire

Takes input s as a char[], and c as a char

Explanation:

Try it here.

s->c->{          // Method with char[] and char parameters and int return-type
  int t=0,       //  Temp counter-integer
      m=0;       //  Max integer
  for(char a:s)  //  Loop over the characters of the input
    m=m>(
     t=x==c?     //   If the current character equals the input-character:
      t+1        //    Raise `t` by 1
      :          //   Else:
       0)        //    Reset `t` to 0
    ?m:t;        //   If `t` is now larger than `m`, put `t` as new max into `m`
                 //  End of loop (implicit / single-line body)
  return m;      //  Return the resulting max
}                // End of method

1
m=m>(t=x==c?t+1:0)?m:t; is shorter than {t=x==c?t+1:0;m=m>t?m:t;}.
Olivier Grégoire

Even though it's wayyyyyy longer, I like my first thought: s->c->java.util.Arrays.stream(s.split("[^"+c+"]")).mapToInt(z->z.length()).max().orElse(0) ;)
Olivier Grégoire

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.