# Find max sequence length

Assume we have a string, and we want to find the maximum repeated sequence of every letter.

For example, given the sample input:

"acbaabbbaaaaacc"


Output for the sample input can be:

a=5
c=2
b=3


Rules:

• Your code can be function or a program - for you to choose
• Input can be by stdin, file or function parameter
• The output should contain only characters that appear in the input
• Input max length is 1024
• The output order does not matter, but it has to be printed in the form [char]=[maximum repeated sequence][delimiter]
• The string can contain any character

The competition ends on Thursday 3rd at 23:59 UTC.

• Is there a maximum to the length of the input string? – sigma Jun 25 '14 at 20:08
• Does the output have to be exactly as given? Can we say 0 for letters that don't appear? Will every letter up to the highest letter appear at least once? – xnor Jun 25 '14 at 20:45
• Please clarify if the output has to be formatted exactly as exemplified in your question. At least 10 of the current 16 answers use a different format, three others present two different versions. – Dennis Jun 26 '14 at 2:17
• @Joey You probably should punish for golfing. By you condoning it, I'm going to end up seeing l:S_&{'=L{2$+_S\#)}g,(N}/ in production systems! And I will curse your name. – Cruncher Jun 27 '14 at 19:17 • Does this count? :) wolframalpha.com/input/?i=char+%22acbaabbbaaaaacc%22+frequency – dualed Jun 27 '14 at 21:41 ## 43 Answers # 8086 machine code, 82 80 Contents of the x.com file: B7 3D 89 DF B1 80 F3 AA 0D 0A 24 B4 01 CD 21 42 38 D8 74 F7 38 17 77 02 88 17 88 C3 31 D2 3C 0D 75 E9 BF 21 3D B1 5E 31 C0 F3 AE E3 EE 4F BB 04 01 8A 05 D4 0A 86 E0 0D 30 30 89 47 02 3C 30 77 04 88 67 03 43 89 3F 89 DA B4 09 CD 21 47 EB D7  It only supports repetitions of up to 99 characters. Source code (served as input for the debug.com assembler), with comments! a mov bh, 3d ; storage of 128 bytes at address 3d00 mov di, bx mov cl, 80 rep stosb ; zero the array db 0d 0a 24 ; 10b mov ah, 1 int 21 ; input a char inc dx ; calculate the run length cmp al, bl ; is it a repeated character? je 10b cmp [bx], dl ; is the new run length greater than previous? ja 11a mov [bx], dl ; store the new run length ; 11a mov bl, al ; remember current repeating character xor dx, dx ; initialize run length to 0 cmp al, d ; end of input? jne 10b ; no - repeat mov di, 3d21 ; start printing run lengths with char 21 mov cl, 5e ; num of iterations = num of printable characters ; 127 xor ax, ax repe scasb ; look for a nonzero run length jcxz 11b ; no nonzero length - exit dec di mov bx, 104 ; address of output string mov al, [di] ; read the run length aam ; convert to decimal xchg al, ah or ax, 3030 mov [bx+2], ax cmp al, 30 ; was it less than 10? ja 145 mov [bx+3], ah ; output only one digit inc bx ; adjust for shorter string ; 145 mov [bx], di ; store "x=" into output string mov dx, bx ; print it mov ah, 9 int 21 inc di jmp 127 ; repeat ; 150 rcx 50 n my.com w q  Here are some golfing techniques used here that I think were fun: • array's address is 3d00, where 3d is the ascii-code for =. This way, the address for array's entry for character x is 3d78. When interpreted as a 2-character string, it's x=. • Output buffer is at address 104; it overwrites initialization code that is no longer needed. End-of-line sequence 0D 0A 24 is executed as harmless code. • The aam instruction here doesn't provide any golfing, though it could... • Writing the number twice, first assuming it's greater than 10, and then correcting if it's smaller. • Exit instruction is at an obscure address 11b, which contains the needed machine code C3 by luck. • Interesting approach. However, with a limitation of 99 repetitions, it wouldn't handle cases where the input of 1024 aaaa's is supplied. – Homer6 Jun 28 '14 at 17:03 # CJam, 2726 25 bytes l:S_&{'=L{2$+_S\#)}g,(N}/


Try it online.

$cjam maxseq.cjam <<< "acbaabbbaaaaacc" a=5 c=2 b=3  ### How it works l:S " Read one line from STDIN and store the result in “S”. "; _& " Intersect the string with itself to remove duplicate characters. "; { " For each unique character “C” in “S”: "; '=L " Push '=' and ''. "; { " "; 2$+_  " Append “C” and duplicate.                                               ";
S\#)  " Get the index of the modified string in “S” and increment it.           ";
}g      " If the result is positive, there is a match; repeat the loop.           ";
,       " Retrieve the length of the string.                                      ";
(       " Decrement to obtain the highest value that did result in a match.       ";
N       " Push a linefeed.                                                        ";
}/        "                                                                         ";


## J - 52 bytes

Well, a simple approach again.

f=:([,'=',m=:":@<:@#@[(]m~[,{.@[)@.(+./@E.))"0 1~~.


Explanation:

f=:([,'=',m=:":@<:@#@[(]m~[,{.@[)@.(+./@E.))"0 1~~.
~~. Create a set of the input and apply it as the left argument to the following.
([,'=',m=:":@<:@#@[(]m~[,{.@[)@.(+./@E.))"0 1    The function that does the work
"0 1    Apply every element from the left argument (letters) with the whole right argument (text).
@.(+./@E.)         Check if the left string is in right string.
(]m~[,{.@[)                   If yes, add one letter to the left string and recurse.
":@<:@#@[                               If not, return (length of the left string - 1), stringified.
[,'=',                                           Append it to the letter + '='


Example:

   f 'acbaabbbaaaaacc'
a=5
c=2
b=3
f 'aaaabaa'
a=4
b=1


If free-form output is allowed (as in many other answers), I have a 45 bytes version too. These boxes represent a list of boxes (yes, they're printed like that, although SE's line-height breaks them).

   f=:([;m=:<:@#@[(]m~[,{.@[)@.(+./@E.))"0 1~~.
f 'acbaabbbaaaaacc'
┌─┬─┐
│a│5│
├─┼─┤
│c│2│
├─┼─┤
│b│3│
└─┴─┘
f 'aaaabaabba'
┌─┬─┐
│a│4│
├─┼─┤
│b│2│
└─┴─┘


(a=$*[0]).chars.uniq.map{|b|puts [b,a.scan(/#{b}+/).map(&:size).max]*?=}  This takes input from command line arguments and outputs to stdout. • chars is a bit shorter than split(""). – Ventero Jun 25 '14 at 19:44 • @Ventero I tried that, but chars gives an enumerator rather than an array. I am in 1.9.3, so is it a 2.0 thing? – afuous Jun 25 '14 at 19:50 • Yeah, in 2.0 chars returns an array. – Ventero Jun 25 '14 at 20:14 • It may be stretching the rules a bit, but perhaps use p instead of puts? – Shelvacu Jun 28 '14 at 10:37 • I see. Although that makes it less pretty, I can't see that it would break any rules tho. – daniero Jun 28 '14 at 19:44 # GolfScript, 26 bytes :s.&{61{2$=}s%1,/$-1=,n+}%  Try it online. Explanation: • :s saves the input string in the variable s for later use. • .& extracts the unique characters in the input, which the rest of the code in the { }% loop then iterates over. • 61 pushes the number 61 (ASCII code for an equals sign) on top of the current character on the stack, to act as an output delimiter. • {2$=}s% takes the string s and replaces its characters with a 1 if they equal the current character being iterated over, or 0 if they don't. (It also leaves the current character on the stack for output.)
• 1,/ takes this string of ones and zeros, and splits it at zeros.
$echo -n 'acbaabbbaaaaacc' | ./a.out c=2 b=3 a=5  • You could replace getchar()>0 by ~getchar() like in this answer – anatolyg Jun 27 '14 at 6:51 • @anatolyg Is EOF guaranteed to be exactly -1? I thought it was only specifically defined as being <0. – fluffy Jun 27 '14 at 7:30 • I think -1 is common enough (i.e. Windows and linux) so you can assume it for Code Golf. For production code, less than zero is perfectly OK, but == EOF is more clear. – anatolyg Jun 27 '14 at 7:36 • @anatolyg Sure, and actually I guess per the spec EOF apparently isn't even guaranteed to be <0 - it could also be, for example, 256. So I'll just save the single byte. :) – fluffy Jun 27 '14 at 7:39 • EOF is guaranteed to be negative, and -1 is used even if char is signed; see here – anatolyg Jun 27 '14 at 7:49 ## Mathematica, 7472 69 Print[#[[1,1]],"=",Max[Tr/@(#^0)]]&/@Split@Characters@#~GatherBy~Max& % @ "acbaabbbaaaaacc"  a=5 c=2 b=3  Not very good but strings are not Mathematica's best area. Getting better though. :-) • This is pretty impressive golfing (saying this after having tried it myself ...) – Szabolcs Jun 28 '14 at 2:38 • v10, not a full solution: First@*MaximalBy[Length] /@ GroupBy[First]@Split@Characters[#] & At least it's pretty straightforward and readable. – Szabolcs Jun 28 '14 at 2:40 • @Szabolcs Thanks! What's the difference between GroupBy and GatherBy? – Mr.Wizard Jun 28 '14 at 4:42 • The main difference is that GroupBy returns an Association. I haven't studied the other differences in detail yet. reference.wolfram.com/language/ref/GroupBy.html You can try it in the cloud with a free account (that's how I'm playing with these). – Szabolcs Jun 28 '14 at 4:44 # C# (LinQPad) ## 146 This is tsavino's answer but shorter. Here, I used Distinct() instead of GroupBy(c=>c). Also the curly braces from the foreach-loop are left out: void v(string i){foreach(var c in i.Distinct())Console.WriteLine(c+"="+(from Match m in Regex.Matches(i,"["+c+"]+")select m.Value.Length).Max());}  ## 136 I tried using a lambda expression instead of the normal query syntax but since I needed a Cast<Match> first, the code became 1 character longer... Anyhow, since it can be executed in LinQPad, you can use Dump() instead of Console.WriteLine(): void v(string i){foreach(var c in i.Distinct())(c+"="+(from Match m in Regex.Matches(i,"["+c+"]+")select m.Value.Length).Max()).Dump();}  Further study of the code got me thinking about the Max(). This function also accepts a Func. This way I could skip the Select part when using the lambda epxression: void v(string i){foreach(var c in i.Distinct())(c+"="+Regex.Matches(i,"["+c+"]+").Cast<Match>().Max(m=>m.Value.Length)).Dump();}  Thus, final result: # 128 Update: Thanks to the tip from Dan Puzey, I was able to save another 6 characters: void v(string i){i.Distinct().Select(c=>c+"="+Regex.Matches(i,"["+c+"]+").Cast<Match>().Max(m=>m‌​.Value.Length)).Dump();}  Length: # 122 • Thank you for your improvements, I didn't know about the trick with the .Dump() in LinqPad. To be honest, I developed the code in Visual Studio and copied it to LinqPad to save some characters because LinqPad doesn't need a main method. – tsavinho Jun 27 '14 at 12:59 • Thanks! I also just got to know the Dump() method recently, saves you 10+ chars every time :) The curly braces was easy and the rest was a bit of braincracking :D – Abbas Jun 27 '14 at 13:07 • If you're happy to use LinqPad's IEnumerable display style you can save another 8 chars, with this as your body: i.Distinct().Select(c=>c+"="+Regex.Matches(i,"["+c+"]+").Cast<Match>().Max(m=>m.Value.Length)).Dump(); – Dan Puzey Jun 27 '14 at 13:24 # Python 3 (70) s=input() for c in set(s): i=1 while c*i in s:i+=1 print(c,'=',i-1)  Even golfed Python can be very readable. I think this code is fully idiomatic except for single-letter variables and a one-line while loop. Example runs: >>> helloworld e = 1 d = 1 h = 1 l = 2 o = 1 r = 1 w = 1 >>> acbaabbbaaaaacc a = 5 c = 2 b = 3  • This is an interesting solution – Cruncher Jun 26 '14 at 14:26 • if you change set(s) to just s I think it still meets the requirements. Nowhere does it say each char must be printed only once. – Cruncher Jun 26 '14 at 14:30 • @Cruncher I agree the OP doesn't specify each letter once, but the other Python answers seem to assume it, so I'll stick with that to be comparable. Though output formats are still inconsistent. I do wish the OP had responded to the requests to clarify. – xnor Jun 26 '14 at 15:24 # Ruby, 58 h={} gets.scan(/(.)\1*/){h[$1]=[h[$1]||0,$&.size].max}
p h


Takes input from STDIN, outputs it to STDOUT in the form {"a"=>5, "c"=>2, "b"=>3}

# C# in LINQPad - 159 Bytes

Well, at least I beat T-SQL ;P Won't beat anyone else, but I thought I'd share it anyway.

void v(string i){foreach(var c in i.GroupBy(c=>c)){Console.WriteLine(c.Key+"="+(from Match m in Regex.Matches(i,"["+c.Key+"]+")select m.Value.Length).Max());}}


Usage:

v("acbaabbbaaaaacc");


Suggestions are always welcome!

• Great answer! I've got some suggestions but that was too long for a comment so click here for my answer. :) – Abbas Jun 27 '14 at 12:39

# Powershell 8077 72

$x=$args;[char[]]"$x"|sort -u|%{"$_="+($x-split"[^$_]"|sort)[-1].length}


You need to run it on console...

• $x is superfluous. You're three byte shorter not using it. Also sort -u suffices. There is rarely a need of spelling out the complete parameter names. This will, however, fail for certain characters due to the unescaped use in the regex. Depending on how »The string can contain any character« is to be understood, this could be a problem. – Joey Jun 27 '14 at 18:59 • @Joey thanks for the tip on sort -u, however regarding the$x I couldn't get it to work like [char[]]"$args"|sort -u|%{"$_="+($args-split"[^$_]"|sort)[-1].length}, it seems the second $args comes empty... – darkajax 17 mins ago – DarkAjax Jun 27 '14 at 21:17 • Eep, yes. Sorry. That's because it's in a script block, which has its own arguments (the $args there is no longer the one of the script). – Joey Jun 27 '14 at 22:48

# Perl - 65 7176 characters

My first code golf!

For each answer, copy to golf.pl and run as:

echo acbaabbbaaaaacc | perl golf.pl


My shortest solution prints each character as many times as it appears, since that is not prohibited by the rules.

$_=$i=<>;for(/./g){$l=length((sort$i=~/$_*/g)[-1]);print"$_=$l "}  My next-shortest solution (85 90 characters) only prints each character once: <>=~s/((.)\2*)(?{$l=length$1;$h{$2}=$l if$l>$h{$2}})//rg;print"$_=$h{$_}
"for keys %h


# F# - 106

let f s=
let m=ref(Map.ofList[for c in 'a'..'z'->c,0])


In FSI, calling

f "acbaabbbaaaaacc"


gives

val it : Map<char,int> ref =
{contents =
map
[('a', 8); ('b', 4); ('c', 3); ('d', 0); ('e', 0); ('f', 0); ('g', 0);
('h', 0); ('i', 0); ...];}


However, to print it without the extra information, call it like this:

f "acbaabbbaaaaacc" |> (!) |> Map.filter (fun _ n -> n > 0)


which gives

val it : Map<char,int> = map [('a', 8); ('b', 4); ('c', 3)]


# Javascript, 116 bytes

y=x=prompt();while(y)r=RegExp(y[0]+'+','g'),alert(y[0]+'='+x.match(r).sort().reverse()[0].length),y=y.replace(r,'')


Sample output:

lollolllollollllollolllooollo
l=4
o=3

acbaabbbaaaaacc
a=5
c=2
b=3

helloworld
h=1
e=1
l=2
o=1
w=1
r=1
d=1


## T-SQL (2012) 189 171

Edit: removed ORDER BY because rules allow any output order.

Takes input from a CHAR variable, @a, and uses a recursive CTE to create a row for each character in the string and figures out sequential occurrences.

After that, it's a simple SELECT and GROUP BY with consideration for the order of the output.

Try it out on SQL Fiddle.

WITH x AS(
SELECT @a i,''c,''d,0r,1n
UNION ALL
SELECT i,SUBSTRING(i,n,1),c,IIF(d=c,r+1,1),n+1
FROM x
WHERE n<LEN(i)+2
)
SELECT d+'='+LTRIM(MAX(r))
FROM x
WHERE n>2
GROUP BY d


Assigning the variable:

DECLARE @a CHAR(99) = 'acbaabbbaaaaacc';


Sample output:

a=5
c=2
b=3

• I don't think I've seen a SQL solution here before. Interesting. – Seiyria Jun 26 '14 at 14:46
• consider the str, function instead of ltrim. You can also name your variable @ to save a char. This allows you to lose the i variable in the rcte. I think you can shave quite a few chars that way. You might also be able to rewrite the query with using a windowing function like sum over rows preceding or lag. I haven't quite formed how yet mind you. – Michael B Jun 29 '14 at 15:11
• @MichaelB thanks for the advice. The trouble I have with str() is that it outputs a bunch of extra spaces. I will definitely start using @ as a variable! – comfortablydrei Jul 1 '14 at 21:32
• It's true that str always outputs 10 characters, but this is golfing :P – Michael B Jul 1 '14 at 21:44

# Haskell - 113 120 bytes

import Data.List
main=interact$show.map(\s@(c:_)->(c,length s)).sort.nubBy(\(a:_)(b:_)->a==b).reverse.sort.group  Tested with $ printf "acbaabbbaaaaacc" | ./sl
[('a',5),('b',3),('c',2)]

• You can use the . (compose) function to avoid creating a lambda where the parameter only appears after the end of a chain of $ connected functions. To do this, simply change all the $s to .s (example: (\i->reverse$sort$group i) turns into reverse.sort.group. – YawarRaza7349 Jun 27 '14 at 5:28

# JavaScript [83 bytes]

prompt().match(/(.)\1*/g).sort().reduce(function(a,b){return a[b[0]]=b.length,a},{})


Run this code in the browser console.

For input "acbaabbbaaaaacc" the console should output "Object {a: 5, b: 3, c: 2}".

# JavaScript - 91

for(i=0,s=(t=prompt()).match(/(.)\1*/g);c=s[i++];)t.match(c+c[0])||alert(c[0]+'='+c.length)


EDIT: My first solution obeys the rules, but it prints several times single char occurrences like abab => a=1,b=1,a=1,b=1 so I came out with this (101 chars), for those not satisfied with my first one:

for(i=0,s=(t=prompt()).match(/((.)\2*)(?!.*\1)/g);c=s[i++];)t.match(c+c[0])||alert(c[0]+'='+c.length)


# Julia, 85

f(s)=(l=0;n=1;a=Dict();[c==l?n+=1:(n>get(a,l,1)&&(a[l]=n);n=1;l=c) for c in s*" "];a)
julia> f("acbaabbbaaaaacc")
{'a'=>5,'c'=>2,'b'=>3}


# Python3 - 111, 126, 115114 111 bytes

Executable code that will read 1 line (only use lowercase letters a-z)

d={}.fromkeys(map(chr,range(97,123)),0)
for c in input():d[c]+=1
[print("%s=%d"%(p,d[p]))for p in d if d[p]>0]


Edit: Excluded unnecessary output on request from @Therare

The output looks nice

~/codegolf $python3 maxseq.py helloworld l=3 o=2 h=1 e=1 d=1 w=1 r=1  • You really should exclude the unnecessary output. (I think) – seequ Jun 25 '14 at 20:11 • "fixed" the output – Dog eat cat world Jun 25 '14 at 20:15 • You can remove spaces between braces, numbers and keywords, such as for or if. – seequ Jun 25 '14 at 20:21 • I think you've misread the questions. l=2 and o=1 for "helloworld" – gnibbler Jun 25 '14 at 21:53 • You're counting total appearances instead of maximum consecutive appearances. – xnor Jun 25 '14 at 22:53 # JavaScript - 141137 125 I don't like regex :) function g(a){i=o=[],a=a.split('');for(s=1;i<a.length;){l=a[i++];if(b=l==a[i])s++;if(!b|!i){o[l]=o[l]>s?o[l]:s;s=1}}return o}  Run console.log(g("acbaabbbaaaaacc"));  outputs [ c: 2, a: 5, b: 3 ]  # Javascript, 109104100 98 bytes function c(s){q=l={};s.split('').map(function(k){q[k]=Math.max(n=k==l?n+1:1,q[l=k]|0)});return q}  Example usage: console.log(c("aaaaaddfffabbbbdb"))  outputs: { a: 5, d: 2, f: 3, b: 4 }  # PHP, 104102 96 <?php function _($s){while($n=$s[$i++]){$a[$n]=max($a[$n],$n!=$s[$i-2]?$v=1:++$v);}print_r($a);}  usage _('asdaaaadddscc');  printed Array ( [a] => 4 [s] => 1 [d] => 3 [c] => 2 )  Java 247 import java.util.*;public class a{public static void main(String[]a){Map<Character, Integer> m = new HashMap<>();for(char c:a[0].toCharArray()){Integer v=m.get(c);m.put(c,v==null?1:v+1);}for(char c:m.keySet())System.out.println(c+"="+m.get(c));}}  • Does import java.util.*; work in Java? – seequ Jun 26 '14 at 13:29 • yes and i paste old code – user902383 Jun 26 '14 at 13:32 • The OP said it could just be a function/method so you can shorten this to simply the method. – Rudi Kershaw Jun 26 '14 at 17:08 • This outputs all occurrences of the character in the String, not the longest substrings consisting of the character. For example, acbaabbbaaaaacc outputs a=8; b=4; c=3 instead of a=5; b=3; c=2. – Kevin Cruijssen Nov 10 '17 at 13:21 ## C 169 Iterates each printable character in ASCII table and counts max from input string. #define N 128 int c,i,n; char Y[N],*p; int main(){gets(Y); for(c=33;c<127;c++){p=Y;n=0,i=0;while(*p){if(*p==c){i++;}else{n=(i>n)?i:n;i=0;}p++;} if(n>0) printf("%c=%d\n",c,n);} }  • Have you tested this? It doesn't look like it produces correct output on a lot of strings , and also doesn't meet the spec which says that input can be up to 1024 long... plus, there's a lot of easy golfing techniques that you've missed. :) – fluffy Jun 27 '14 at 8:11 # JavaScript 116 prompt(x={}).replace(/(.)\1*/g,function(m,l){n=m.length if(!x[l]||x[l]<n)x[l]=n}) for(k in x)console.log(k+'='+x[k])  ## Groovy - 80 chars Based on this clever answer by xnor : t=args[0];t.toSet().each{i=0; while(t.contains(it*++i)); println "${it}=${i-1}"}  Output: $ groovy Golf.groovy abbcccdddd
d=4
b=2
c=3
a=1


Ungolfed:

t=args[0]

t.toSet().each { c ->
i=0
s=c

// repeat the char c with length i
// e.g. "b", "bb", "bbb", etc
// stop when we find a length that is not in t:
// this is the max + 1
while (t.contains(s)) {
i++
s=c*i
}
println "${c}=${i-1}"
}
`
• Does that actually count the maximum sequence length? I don't see how that would work correctly for a string like "aabbbbaaaabbbbbba" although I don't know Groovy either. – fluffy Jun 27 '14 at 7:35
• It works for your example. I've updated the ungolfed version. Note that "a" * 4 == "aaaa" . – Michael Easter Jun 27 '14 at 11:22
• Ah, I see how it works now. Clever. – fluffy Jun 27 '14 at 21:48