31
\$\begingroup\$

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.

\$\endgroup\$
9
  • \$\begingroup\$ Is there a maximum to the length of the input string? \$\endgroup\$
    – sigma
    Jun 25, 2014 at 20:08
  • 2
    \$\begingroup\$ 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? \$\endgroup\$
    – xnor
    Jun 25, 2014 at 20:45
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – Dennis
    Jun 26, 2014 at 2:17
  • 2
    \$\begingroup\$ @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. \$\endgroup\$
    – Cruncher
    Jun 27, 2014 at 19:17
  • 1
    \$\begingroup\$ Does this count? :) wolframalpha.com/input/?i=char+%22acbaabbbaaaaacc%22+frequency \$\endgroup\$
    – dualed
    Jun 27, 2014 at 21:41

48 Answers 48

22
\$\begingroup\$

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.
\$\endgroup\$
1
  • \$\begingroup\$ Interesting approach. However, with a limitation of 99 repetitions, it wouldn't handle cases where the input of 1024 aaaa's is supplied. \$\endgroup\$
    – Homer6
    Jun 28, 2014 at 17:03
14
\$\begingroup\$

CJam, 27 26 25 bytes

l:S_&{'=L{2$+_S\#)}g,(N}/

Try it online.

Example

$ 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.                                                        ";
}/        "                                                                         ";
\$\endgroup\$
9
\$\begingroup\$

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│
└─┴─┘
\$\endgroup\$
8
\$\begingroup\$

Ruby, 72

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

\$\endgroup\$
7
  • \$\begingroup\$ chars is a bit shorter than split(""). \$\endgroup\$
    – Ventero
    Jun 25, 2014 at 19:44
  • \$\begingroup\$ @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? \$\endgroup\$
    – afuous
    Jun 25, 2014 at 19:50
  • \$\begingroup\$ Yeah, in 2.0 chars returns an array. \$\endgroup\$
    – Ventero
    Jun 25, 2014 at 20:14
  • \$\begingroup\$ It may be stretching the rules a bit, but perhaps use p instead of puts? \$\endgroup\$
    – Shelvacu
    Jun 28, 2014 at 10:37
  • 1
    \$\begingroup\$ I see. Although that makes it less pretty, I can't see that it would break any rules tho. \$\endgroup\$
    – daniero
    Jun 28, 2014 at 19:44
7
\$\begingroup\$

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

:s.&{{1$=}s%1,/$-1=,n+}%
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You can save the swap if you push the 61 first: :s.&{61{2$=}s%1,/$-1=,n+}%. \$\endgroup\$
    – Howard
    Jun 26, 2014 at 6:23
6
\$\begingroup\$

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

f("acbaabbbaaaaacc")

to get

c=2
a=5
b=3
\$\endgroup\$
3
  • \$\begingroup\$ This seems to generate incorrect results for input like aaaabaa. \$\endgroup\$
    – Ventero
    Jun 25, 2014 at 19:06
  • \$\begingroup\$ @Ventero you're right, there are two problems. one is easily fixed, but I need to think about the other. \$\endgroup\$ Jun 25, 2014 at 19:09
  • \$\begingroup\$ @Ventero fixed. \$\endgroup\$ Jun 25, 2014 at 19:37
6
\$\begingroup\$

Python 3, 69 bytes

s=input()
for c in set(s):
 i=0
 while-~i*c in s:i+=1
 print(c,'=',i)

Try it online!

Even golfed Python can be very readable. I think this code is fully idiomatic except for the -~i for i+1 and the single-letter variables. Thanks to pxeger for saving 1 byte.

Example runs:

>>> helloworld
e = 1
d = 1
h = 1
l = 2
o = 1
r = 1
w = 1
>>> acbaabbbaaaaacc
a = 5
c = 2
b = 3
\$\endgroup\$
6
  • \$\begingroup\$ This is an interesting solution \$\endgroup\$
    – Cruncher
    Jun 26, 2014 at 14:26
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – Cruncher
    Jun 26, 2014 at 14:30
  • \$\begingroup\$ @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. \$\endgroup\$
    – xnor
    Jun 26, 2014 at 15:24
  • 1
    \$\begingroup\$ You can change for c in set(s) to for c in{*s} for -2 bytes \$\endgroup\$ Feb 27, 2021 at 10:23
  • \$\begingroup\$ @cairdcoinheringaahing It looks like this answer actually predates the introduction of set unpacking in Python 3.5, so I'll keep it as is. \$\endgroup\$
    – xnor
    Feb 27, 2021 at 11:42
5
\$\begingroup\$

Pyth, 24 25 26 (or 29)

=ZwFY{Z=bkW'bZ~bY)p(Yltb

Test can be done here: link

Outputs in the format:

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

Explanation:

=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)

Python:

k=""
Z=copy(input())
for Y in set(Z):
 b=copy(k)
 while (b in Z):
  b+=Y
 print(_tuple(Y,len(tail(b))))

For proper (a=5) output, use:

=ZwFY{Z=bkW'bZ~bY)p++Y"="`ltb

29 characters

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

C, 126 125 119 bytes

l,n,c[256];main(p){while(~(p=getchar()))n*=p==l,c[l=p]=c[p]>++n?c[p]:n;for(l=256;--l;)c[l]&&printf("%c=%d\n",l,c[l]);}

Running:

$ gcc seq.c 2>& /dev/null
$ echo -n 'acbaabbbaaaaacc' | ./a.out
c=2
b=3
a=5
\$\endgroup\$
6
  • \$\begingroup\$ You could replace getchar()>0 by ~getchar() like in this answer \$\endgroup\$
    – anatolyg
    Jun 27, 2014 at 6:51
  • \$\begingroup\$ @anatolyg Is EOF guaranteed to be exactly -1? I thought it was only specifically defined as being <0. \$\endgroup\$
    – fluffy
    Jun 27, 2014 at 7:30
  • \$\begingroup\$ 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. \$\endgroup\$
    – anatolyg
    Jun 27, 2014 at 7:36
  • \$\begingroup\$ @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. :) \$\endgroup\$
    – fluffy
    Jun 27, 2014 at 7:39
  • 2
    \$\begingroup\$ EOF is guaranteed to be negative, and -1 is used even if char is signed; see here \$\endgroup\$
    – anatolyg
    Jun 27, 2014 at 7:49
4
\$\begingroup\$

Mathematica, 74 72 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. :-)

\$\endgroup\$
4
  • \$\begingroup\$ This is pretty impressive golfing (saying this after having tried it myself ...) \$\endgroup\$
    – Szabolcs
    Jun 28, 2014 at 2:38
  • \$\begingroup\$ v10, not a full solution: First@*MaximalBy[Length] /@ GroupBy[First]@Split@Characters[#] & At least it's pretty straightforward and readable. \$\endgroup\$
    – Szabolcs
    Jun 28, 2014 at 2:40
  • \$\begingroup\$ @Szabolcs Thanks! What's the difference between GroupBy and GatherBy? \$\endgroup\$
    – Mr.Wizard
    Jun 28, 2014 at 4:42
  • \$\begingroup\$ 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). \$\endgroup\$
    – Szabolcs
    Jun 28, 2014 at 4:44
3
\$\begingroup\$

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

\$\endgroup\$
3
  • \$\begingroup\$ 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. \$\endgroup\$
    – tsavinho
    Jun 27, 2014 at 12:59
  • \$\begingroup\$ 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 \$\endgroup\$
    – Abbas
    Jun 27, 2014 at 13:07
  • 1
    \$\begingroup\$ 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(); \$\endgroup\$
    – Dan Puzey
    Jun 27, 2014 at 13:24
2
\$\begingroup\$

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}

\$\endgroup\$
2
\$\begingroup\$

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!

\$\endgroup\$
1
  • \$\begingroup\$ Great answer! I've got some suggestions but that was too long for a comment so click here for my answer. :) \$\endgroup\$
    – Abbas
    Jun 27, 2014 at 12:39
2
\$\begingroup\$

Powershell 80 77 72

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

You need to run it on console...

\$\endgroup\$
3
  • 1
    \$\begingroup\$ $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. \$\endgroup\$
    – Joey
    Jun 27, 2014 at 18:59
  • \$\begingroup\$ @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 \$\endgroup\$
    – DarkAjax
    Jun 27, 2014 at 21:17
  • \$\begingroup\$ 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). \$\endgroup\$
    – Joey
    Jun 27, 2014 at 22:48
2
\$\begingroup\$

Perl - 65 71 76 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
\$\endgroup\$
1
\$\begingroup\$

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"

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)]
\$\endgroup\$
1
\$\begingroup\$

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 
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
4
  • \$\begingroup\$ I don't think I've seen a SQL solution here before. Interesting. \$\endgroup\$
    – Seiyria
    Jun 26, 2014 at 14:46
  • \$\begingroup\$ 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. \$\endgroup\$
    – Michael B
    Jun 29, 2014 at 15:11
  • \$\begingroup\$ @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! \$\endgroup\$ Jul 1, 2014 at 21:32
  • \$\begingroup\$ It's true that str always outputs 10 characters, but this is golfing :P \$\endgroup\$
    – Michael B
    Jul 1, 2014 at 21:44
1
\$\begingroup\$

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)]
\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$ Jun 27, 2014 at 5:28
1
\$\begingroup\$

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}".

\$\endgroup\$
1
\$\begingroup\$

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)
\$\endgroup\$
1
\$\begingroup\$

Husk, 18 bytes

mȯJ'=§eo;←osL►Lk←g

Try it online!

11 bytes if we ignore the exact input format and display as a list of pairs instead.

\$\endgroup\$
1
1
\$\begingroup\$

Husk, 16 bytes

mS:(:'=s▲`mg¹#)U

Try it online!

Explanation:

m              U    # for each of the unique elements of the input
 S:                 # prepend the element to
   (:'=       )     # '=' prepended to
        ▲           # the maximum of
             #      # the number of times it occurs in 
         `mg¹       # each group of identical items in the input,
       s            # converted into a string

I saw that Razetime had answered this in Husk, so I had to have a go too...

\$\endgroup\$
2
  • \$\begingroup\$ I'm surprised Husk doesn't have any form of run-length encoding \$\endgroup\$ Feb 27, 2021 at 16:55
  • \$\begingroup\$ @cairdcoinheringaahing - it doesn't have it as a single builtin command, so g = group on equal adjacent values is the closest we can get... \$\endgroup\$ Feb 27, 2021 at 17:30
1
\$\begingroup\$

Jelly, 12 bytes

ŒriƇṀj”=ʋⱮQY

Try it online!

-2 bytes thanks to Unrelated String!

8 bytes to output as a list of pairs

How it works

ŒriƇṀj”=ʋⱮQY - Main link. Takes a string S on the left
        ʋ    - Group the previous 4 links into a dyad f(S, C):
Œr           -   Run-length encode S
   Ƈ         -   For each sublist in rle(S), keep it if:
  i          -     It contains C
    Ṁ        -   Maximum
                 As all elements are in the form [C, n] for integers n,
                 Python considers the maximum as the greatest n
     j”=     -   Join with "="; Yields [C, "=", n]
          Q  - Get the unique characters of S
         Ɱ   - For each unique character C in S, yield f(C, S)
           Y - Join by newlines and output
\$\endgroup\$
2
  • \$\begingroup\$ I think the Ṫṭ can be removed: Try it online! \$\endgroup\$ Feb 27, 2021 at 3:42
  • 1
    \$\begingroup\$ @UnrelatedString Of course! The dangers of golfing at 1 in the morning :) \$\endgroup\$ Feb 27, 2021 at 16:18
1
\$\begingroup\$

Bash / GNU core utils (40)

fold -1|uniq -c|sort -k2 -k1r|uniq -f1

Try it online!

Output when input is "acbaabbbaaaaacc":

      5 a
      3 b
      2 c

Explanation:

  • fold -1 adds a newline after each character
  • uniq -c counts the number of consecutive identical lines
  • sort -k2 -k1r sorts the result so as the maximum count for each character comes first
  • uniq -f1 keeps only the first line for each character
\$\endgroup\$
2
  • \$\begingroup\$ Welcome to Code Golf! Nice first answer. \$\endgroup\$ Feb 27, 2021 at 20:09
  • \$\begingroup\$ Thank you @RedwolfPrograms :-) \$\endgroup\$
    – xhienne
    Feb 27, 2021 at 20:11
0
\$\begingroup\$

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}
\$\endgroup\$
0
\$\begingroup\$

Python3 - 111, 126, 115 114 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
\$\endgroup\$
6
  • \$\begingroup\$ You really should exclude the unnecessary output. (I think) \$\endgroup\$
    – seequ
    Jun 25, 2014 at 20:11
  • \$\begingroup\$ "fixed" the output \$\endgroup\$ Jun 25, 2014 at 20:15
  • \$\begingroup\$ You can remove spaces between braces, numbers and keywords, such as for or if. \$\endgroup\$
    – seequ
    Jun 25, 2014 at 20:21
  • 3
    \$\begingroup\$ I think you've misread the questions. l=2 and o=1 for "helloworld" \$\endgroup\$
    – gnibbler
    Jun 25, 2014 at 21:53
  • 4
    \$\begingroup\$ You're counting total appearances instead of maximum consecutive appearances. \$\endgroup\$
    – xnor
    Jun 25, 2014 at 22:53
0
\$\begingroup\$

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}

Run

console.log(g("acbaabbbaaaaacc"));

outputs

[ c: 2, a: 5, b: 3 ]
\$\endgroup\$
0
\$\begingroup\$

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:

console.log(c("aaaaaddfffabbbbdb"))

outputs:

{ a: 5, d: 2, f: 3, b: 4 }
\$\endgroup\$
0
\$\begingroup\$

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

usage

_('asdaaaadddscc');

printed

Array ( [a] => 4 [s] => 1 [d] => 3 [c] => 2 )
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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