Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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

For example, given the sample input:


Output for the sample input can be:



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

share|improve this question
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? :) – dualed Jun 27 '14 at 21:41

41 Answers 41

8086 machine code, 82 80

Contents of the 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 assembler), with comments!

    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

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.
share|improve this answer
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, 27 26 25 bytes


Try it online.


$ cjam maxseq.cjam <<< "acbaabbbaaaaacc"

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.                                                        ";
}/        "                                                                         ";
share|improve this answer

J - 52 bytes

Well, a simple approach again.

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


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 + '='


   f 'acbaabbbaaaaacc'
   f 'aaaabaa'

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'
   f 'aaaabaabba'
share|improve this answer

Ruby, 72

(a=$*[0]){|b|puts [b,a.scan(/#{b}+/).map(&:size).max]*?=}

This takes input from command line arguments and outputs to stdout.

share|improve this answer
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

bash + utils 41, or 62

Edit2: Well, losing compatibility can save another 10 bytes by dropping the #!/bin/sh line. This will probably work for most shells, and I believe the current shell will assume a script of the same type. See comments here.

Edit: thanks to Dennis for some improvements.

Save the following to file then $ chmod +x

fold -1|uniq -c|sort -rk2|awk '!a[$2]++'

Description: Replace each character with character and newline, count the number of times consecutive lines appears, sort by the count in reverse order (most-seen first), send to awk which outputs each line that hasn't been seen before based on the character column.


/codegolf/substring_count$ ./ <<< "aabbccbbbbccca"
      3 c
      4 b
      2 a

And, for output as specified in the challenge for a total of 62 bytes, use

fold -1|uniq -c|sort -rk2|awk '!a[$2]++'|awk '{print$2"="$1}'

Which gives:

codegolf/substring_count$ ./ <<< "aabbccbbbbccca"
share|improve this answer
fold -1 does the same as your sed command. You don't need printf if you just read from STDIN. – Dennis Jun 26 '14 at 1:26
Thanks for the tips. – tolos Jun 26 '14 at 3:36
Even if required, shebangs are usually not included in the byte count, since you could always invoke the script as bash Your script doesn't use any bashisms; any POSIX compatible shell will be able to execute it. In any case, the proper shebang for a Bash script would be #!/bin/bash, since sh might be a different shell. – Dennis Jun 26 '14 at 4:02

GolfScript, 26 bytes


Try it online.


  • :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.
  • $ sorts the resulting substrings, -1= extracts the last substring (which, since they all consist of repetitions of the same character, is the longest), and , returns the length of this substring.
  • n+ stringifies the length and appends a newline to it.

Ps. If the equals signs in the output are optional, the 61 can be omitted (and the 2$ replaced by 1$), for a total length of 24 bytes:

share|improve this answer
You can save the swap if you push the 61 first: :s.&{61{2$=}s%1,/$-1=,n+}%. – Howard Jun 26 '14 at 6:23
@Howard: Thanks! – Ilmari Karonen Jun 26 '14 at 12:34

CoffeeScript, 109 bytes

I like regex.

f=(s)->a={};a[t[0]]=t.length for t in s.match(/((.)\2*)(?!.*\1)/g).reverse();(k+'='+v for k,v of a).join '\n'

Here is the compiled JavaScript you can try in your browser's console

f = function(s) {
  var a, t, _i, _len, _ref;
  a = {};
  _ref = s.match(/((.)\2*)(?!.*\1)/g).reverse();
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    t = _ref[_i];
    a[t[0]] = t.length;
  return a;

Then you can call


to get

share|improve this answer
This seems to generate incorrect results for input like aaaabaa. – Ventero Jun 25 '14 at 19:06
@Ventero you're right, there are two problems. one is easily fixed, but I need to think about the other. – Martin Ender Jun 25 '14 at 19:09
@Ventero fixed. – Martin Ender Jun 25 '14 at 19:37

Mathematica, 74 72 69


% @ "acbaabbbaaaaacc"

Not very good but strings are not Mathematica's best area. Getting better though. :-)

share|improve this answer
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. 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

Pyth, 24 25 26 (or 29)


Test can be done here: link

Outputs in the format:

('a', 5)
('c', 2)
('b', 3)


=Zw              Store one line of stdin in Z
FY{Z             For Y in set(Z):
=bk              b=''
W'bZ             while b in Z:
~bY              b+=Y
)                end while
p(Yltb           print (Y, len(b)-1)


for Y in set(Z):
 while (b in Z):

For proper (a=5) output, use:


29 characters

share|improve this answer
Seems like you had the exact same idea. Have a +1 for that. – Seeq Jun 25 '14 at 21:57
@TheRare yeah, it seems like a very good way to do it. – isaacg Jun 25 '14 at 21:59
Not really related to your algorithm, but the python output is confusing, because k='' is defined elsewhere. – gggg Jun 25 '14 at 22:58
Yeah, sorry about that. I'll work on improving it. I'll edit it too. – isaacg Jun 25 '14 at 23:24

C, 126 125 119 bytes



$ gcc seq.c 2>& /dev/null
$ echo -n 'acbaabbbaaaaacc' | ./a.out
share|improve this answer
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

C# (LinQPad)


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


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:



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



share|improve this answer
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)

for c in set(s):
 while c*i in s: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
share|improve this answer
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

p h

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

share|improve this answer

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



Suggestions are always welcome!

share|improve this answer
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

Perl - 65 71 76 characters

My first code golf!

For each answer, copy to and run as:

echo acbaabbbaaaaacc | perl

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


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
share|improve this answer

F# - 106

let f s=
 let m=ref(Map.ofList[for c in 'a'..'z'->c,0])
 String.iter(fun c->m:=(!m).Add(c,(!m).[c]+1))s;m

In FSI, calling

f "acbaabbbaaaaacc"


val it : Map<char,int> ref =
  {contents =
      [('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)]
share|improve this answer

Javascript, 116 bytes


Sample output:



share|improve this answer

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.

    SELECT @a i,''c,''d,0r,1n
    SELECT i,SUBSTRING(i,n,1),c,IIF(d=c,r+1,1),n+1
    FROM x
    WHERE n<LEN(i)+2

Assigning the variable:

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

Sample output:

share|improve this answer
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$\s@(c:_)->(c,length s)).sort.nubBy(\(a:_)(b:_)->a==b)

Tested with

$ printf "acbaabbbaaaaacc" | ./sl
share|improve this answer
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 – YawarRaza7349 Jun 27 '14 at 5:28
Thanks, I had not noticed. – gxtaillon Jun 27 '14 at 10: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}".

share|improve this answer

JavaScript - 91


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:

share|improve this answer

Powershell 80 77 72

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

You need to run it on console...

share|improve this answer
$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

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")
share|improve this answer

Python3 - 111, 126, 115 114 111 bytes

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

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 
share|improve this answer
You really should exclude the unnecessary output. (I think) – Seeq 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. – Seeq 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 - 141 137 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}




[ c: 2, a: 5, b: 3 ]
share|improve this answer

Javascript, 109 104 100 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:



{ a: 5, d: 2, f: 3, b: 4 }
share|improve this answer

PHP, 104 102 96

<?php function _($s){while($n=$s[$i++]){$a[$n]=max($a[$n],$n!=$s[$i-2]?$v=1:++$v);}print_r($a);}




Array ( [a] => 4 [s] => 1 [d] => 3 [c] => 2 )
share|improve this answer

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));}}
share|improve this answer
Does import java.util.*; work in Java? – Seeq 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

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);
if(n>0) printf("%c=%d\n",c,n);}
share|improve this answer
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

for(k in x)console.log(k+'='+x[k])
share|improve this answer

protected by Community Jun 28 '14 at 17:38

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.