25
\$\begingroup\$

Given a string of printable ASCII, output the frequency of each character in that string.

The Challenge

  • Input is given as a string of printable ASCII characters (decimal [32-126] inclusive).
  • Output the frequency of each character, in ASCII order.
  • The output must have a format similar to [character][separator][count]. Provided that there is a single, non-newline separating string between the character and its frequency, it is a valid output.
  • Output can be a single string, multiple strings, list of 2-tuples, array of tuples, etc.
  • Input and output can be given using any convenient method.
  • Standard loopholes are forbidden.
  • This is , so shortest in bytes wins.

Sample I/O

abcd
//outputs
a: 1
b: 1
c: 1
d: 1
Over 9001!
//outputs
  [ 1
! [ 1
0 [ 2
1 [ 1
9 [ 1
O [ 1
e [ 1
r [ 1
v [ 1
--<-<<+[+[<+>--->->->-<<<]>]<<--.<++++++.<<-..<<.<+.>>.>>.<<<.+++.>>.>>-.<<<+.
//outputs (as 2-tuples)
(+,14),(-,13),(.,13),(<,21),(>,13),([,2),(],2)
Su3OH39IguWH
//outputs (as 2d array)
[[3,2],[9,1],[H,2],[I,1],[O,1],[S,1],[W,1],[g,1],[u,2]]
\$\endgroup\$
12
  • \$\begingroup\$ Related and related. \$\endgroup\$
    – bigyihsuan
    Commented Jul 24, 2019 at 5:00
  • 8
    \$\begingroup\$ Output the frequency of each character, in ASCII order. but e after v \$\endgroup\$
    – Adám
    Commented Jul 24, 2019 at 6:21
  • 4
    \$\begingroup\$ May I output a,1b,2c,3? \$\endgroup\$
    – tsh
    Commented Jul 24, 2019 at 7:40
  • \$\begingroup\$ Could I use PETSCII instead? -> c64-wiki.com/wiki/PETSCII Also, do you mean true ASCII (7-bit), or simply ASCII-compatible, like extended ASCII or UTF-8? \$\endgroup\$ Commented Jul 24, 2019 at 11:48
  • 1
    \$\begingroup\$ @ShaunBebbers ooo that's something. I'll allow it. ASCII-compatibles are also fine, provided you say what encoding it is. \$\endgroup\$
    – bigyihsuan
    Commented Jul 24, 2019 at 12:47

43 Answers 43

12
\$\begingroup\$

Python 3, 50, 43, 41 bytes

lambda s:{c:s.count(c)for c in sorted(s)}

Try it online!

\$\endgroup\$
3
  • 4
    \$\begingroup\$ You could save 7 bytes by switching to a list of 2-tuples (replace c+","+str(s.count(c)) with (c,s.count(c))), since python sorts tuples by their first elements. Try it online! \$\endgroup\$
    – maxb
    Commented Jul 24, 2019 at 6:52
  • 7
    \$\begingroup\$ You can save 2 bytes using zip() and map() (can't access TIO where I am, sorry): lambda s:sorted({*zip(s,map(s.count,s))}) \$\endgroup\$ Commented Jul 24, 2019 at 14:18
  • \$\begingroup\$ You can save two brackets (2 bytes) by using a dict and that more recent versions of Python 3 retain insertion order. lambda s:{c:s.count(c)for c in sorted(s)} \$\endgroup\$
    – spyr03
    Commented Jul 26, 2019 at 13:05
9
\$\begingroup\$

Ohm v2, 2 bytes

Try it online!

      implicit input
S     sort string
 Ö    run-length encoding
      implicitly print
\$\endgroup\$
8
\$\begingroup\$

Python 3, 41 bytes

lambda s:sorted({*zip(s,map(s.count,s))})

Try it online!

\$\endgroup\$
0
7
\$\begingroup\$

J, 13 bytes

({.;#)/.~@/:~

Try it online!

  • @/:~ sort the input and...
  • /.~ partition it into groups of like items. Apply the following to each group...
  • ({.;#) take the first element {. and link it ; to the number of items in the group #
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Nice! I forgot about /., my solution with = was significantly longer: (;/@~.,.1;/@:#.=)@/:~ \$\endgroup\$ Commented Jul 24, 2019 at 18:03
7
\$\begingroup\$

Brachylog, 2 bytes

ọo

Try it online!

ọ     Occurrences,
 o    sorted.

It's essentially the same as using an RLE builtin with the sorting requirement, but if the output could be in any order it would just be .

\$\endgroup\$
6
\$\begingroup\$

APL (Dyalog Extended), 5 bytesSBCS

Anonymous tacit prefix function, returning a two-column table, which by default prints with space as separator between character and count, and line break after each entry.

,∘≢⌸∧

Try it online!

, character followed

 by

 its tally

 for each unique character

 in ascending order

\$\endgroup\$
6
\$\begingroup\$

Haskell, 52 49 bytes

-3 bytes thanks to cole!

import Data.List
map((,).nub<*>length).group.sort

Try it online!

I know this is too long (especially that import), but I'm new at Haskell golfing and hoping to get better! Outputs as a list of tuples of (character, count) (note the character is String, not a Char).

\$\endgroup\$
2
  • \$\begingroup\$ Beat me by a few minutes. 49 bytes \$\endgroup\$
    – cole
    Commented Jul 24, 2019 at 6:41
  • 1
    \$\begingroup\$ I forgot to mention that the output type is [(String, Int)], but I think that's acceptable (not [(Char, Int)] like in your first answer). I don't know edit-quette very well here, so I hope my edit to clarify this was not in bad taste \$\endgroup\$
    – cole
    Commented Jul 24, 2019 at 6:51
5
\$\begingroup\$

Perl 6, 15 bytes

*.comb.Bag.sort

Try it online!

Anonymous code block that takes a string and returns a list of pairs, where the key is the character and the value is the number of occurrences.

Explanation:

*.comb           # Decompose into characters
      .Bag       # Group into unordered bag of character => occurrences
          .sort  # Sort by character
\$\endgroup\$
5
\$\begingroup\$

CJam, 8 4 bytes

$e`p

Try it online!

-3 bytes thanks to Jonah, and -1 byte from rule interpretation.

A perfect challenge for CJam. I had hoped that the RLE encode operator would output [char, count], but the order was reversed. Otherwise it would have been a 5-byter. After Jonah's comment, I switched the order of the output. I'm not sure if the first read should be counted, since the standard rules permit input to be on the stack at the start of the program. If that's the case, this answer is one byte shorter. From this meta discussion, I concluded that the read could be placed in the header. Otherwise I could modify the script to be a function without changing the byte count.

Explanation

 $       sort string
  e`     RLE-encode (transforms "aabc" to [[2, "a"], [1, "b"], [1, "c"]]
    p    print

Open question: would something like this be allowed if transforming the answer to a function, or should the brackets be included in the byte count?

\$\endgroup\$
1
  • \$\begingroup\$ "Provided that there is a single, non-newline separating character between the character and its frequency, it is a valid output." -- combined with the adjective "similar to," I read this as saying that the order doesn't matter. Which means you could drop the reversing. \$\endgroup\$
    – Jonah
    Commented Jul 24, 2019 at 7:31
4
\$\begingroup\$

Pyth, 3 bytes

r8S

Try it online!

Simply run-length encodes (r8) the sorted (S) input. Output is a list of tuples of [frequency, character].

\$\endgroup\$
4
\$\begingroup\$

Jelly, 6 3 bytes

ṢŒr

Try it online!

A monadic link taking the string as its argument. Returns a list of lists, each one containing the character and count. The footer formats this as a grid.

\$\endgroup\$
4
\$\begingroup\$

Bash, 27 22 20 bytes

fold -1|sort|uniq -c

Try it online!

-5 bytes thanks to Neil

-2 bytes thanks to Digital Trauma

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Why not take input on STDIN? \$\endgroup\$
    – Neil
    Commented Jul 24, 2019 at 9:15
  • \$\begingroup\$ Thanks @Neil, updated. \$\endgroup\$
    – Jonah
    Commented Jul 24, 2019 at 17:24
  • 2
    \$\begingroup\$ fold -1 instead of grep -o . saves 2 \$\endgroup\$ Commented Jul 24, 2019 at 22:51
  • \$\begingroup\$ @DigitalTrauma nice. updated. \$\endgroup\$
    – Jonah
    Commented Jul 24, 2019 at 23:04
4
\$\begingroup\$

PHP, 57 bytes

foreach(count_chars($argn,1)as$a=>$b)echo chr($a)," $b
";

Try it online!

Input via STDIN, run with php -F:

$ echo Su3OH39IguWH|php -F cc.php
3 2
9 1
H 2
I 1
O 1
S 1
W 1
g 1
u 2

Fun fact: this challenge is basically the Example 1 on the PHP docs for count_chars().

\$\endgroup\$
4
\$\begingroup\$

T-SQL 2008 query, 130 bytes

DECLARE @ varchar(2000)='kabcdda'

SELECT w,sum(1)FROM(SELECT
substring(@,number+1,1)FROM
spt_values WHERE type='P'and
number<len(@))x(w)GROUP BY w
ORDER BY ascii(w)

Try it online

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Your order by is alphabetical, but it should be in ascii order. it should be ORDER BY ascii(w) \$\endgroup\$
    – Einacio
    Commented Jul 25, 2019 at 14:12
  • \$\begingroup\$ @Einacio thanks, I had missed that part of the question. I corrected as you suggested \$\endgroup\$ Commented Jul 25, 2019 at 22:05
  • 1
    \$\begingroup\$ If your server is set to a binary collation like Latin1_General_BIN (which is not the default), sort order would be by ASCII code, without have to explicitly use the ASCII function. That does add an additional requirement to the answer (although you're already requiring this to be run in the master database, by your use of the master.dbo.spt_values system table). Good answer, though. SQL definitely needs a better built-in numbers table. \$\endgroup\$
    – BradC
    Commented Jul 26, 2019 at 13:57
  • \$\begingroup\$ @BradC interesting idea, using that collation, that would be kind of a big assumption. Using master database seems more legitimate though, best practice for me is not assigning users a default database. Last time I tried that, I was unable to log in with that user after the default database had been removed - I am not aware whether this issue has been fixed. I agree we need a better build in number table, this could easily be a calendar table as well. \$\endgroup\$ Commented Jul 29, 2019 at 8:19
  • \$\begingroup\$ @t-clausen.dk I've had answers where I had to specify "this only works with a case sensitive collation" or something, so it does narrow the scope, like when you have to specify the SQL version; in your case adding the extra bytes for the ASCII function is probably a better approach. Similarly, I try to specify when my code needs to be run in a particular database, so that it doesn't fail if someone tries it in a different context. \$\endgroup\$
    – BradC
    Commented Jul 29, 2019 at 16:14
3
\$\begingroup\$

C (gcc), 94 91 bytes

Thanks to Ourous and ceilingcat for their suggestions.

To get the non-newline separator, I'm making use of the fact that negative numbers get a "-" for free! :-)

f(char*s){char c[255]={},i=31;for(;*s;)c[*s++]--;for(;++i>0;)c[i]&&printf("%c%d ",i,c[i]);}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ 93 bytes by moving i=31 into the declaration: Try it online! \$\endgroup\$
    – Οurous
    Commented Jul 25, 2019 at 0:39
  • \$\begingroup\$ That's clever using negative counting like that. \$\endgroup\$ Commented Jul 25, 2019 at 17:38
3
\$\begingroup\$

PowerShell, 27 22 21 19 bytes

$args[0]|sort|group

Try it online!

Exactly what it says on the tin. Takes input $args[0] via splatting (manifests on TIO as a [char[]]), sorts it, then group-object it into a grouping.

-8 bytes thanks to mazzy

\$\endgroup\$
8
  • \$\begingroup\$ That output is perfectly fine. \$\endgroup\$
    – bigyihsuan
    Commented Jul 24, 2019 at 13:46
  • \$\begingroup\$ is a splatted string 'any convenient method'? Try it online! another word, is a char array a representation of a string? \$\endgroup\$
    – mazzy
    Commented Jul 25, 2019 at 13:34
  • \$\begingroup\$ @mazzy Splatting works, but then you need to count the name of the script block, so we only save a byte. Still, a byte is a byte! \$\endgroup\$ Commented Jul 25, 2019 at 17:34
  • \$\begingroup\$ why? you can save $args|sort|group to a file with .ps1 extension and call this script file as usually. The splatting works with a script file too. \$\endgroup\$
    – mazzy
    Commented Jul 25, 2019 at 17:49
  • 1
    \$\begingroup\$ @mazzy Yes, a [char[]] can be called a string per Meta consensus. Do you mean something like this? \$\endgroup\$ Commented Jul 26, 2019 at 18:05
3
\$\begingroup\$

JavaScript, 58 bytes

s=>[...s].sort().flatMap(c=>c>p?[p=[c,1]]:p[1]++&&[],p=[])

Try it online!

Thanks Shaggy, -1 byte.


Retina, 18 bytes

O`.
(.)\1*
$1,$.&¶

Try it online!

I don't speak Retina. I just translated above JavaScript answer to Retina with some searching.

Thanks to Cows quack, -3 bytes.

\$\endgroup\$
5
  • \$\begingroup\$ $.($&) can become $.& \$\endgroup\$
    – user41805
    Commented Jul 24, 2019 at 8:10
  • \$\begingroup\$ 64 bytes \$\endgroup\$
    – Shaggy
    Commented Jul 24, 2019 at 8:19
  • \$\begingroup\$ @Shaggy Nice idea. And I moved one more step based on that. \$\endgroup\$
    – tsh
    Commented Jul 24, 2019 at 8:37
  • \$\begingroup\$ Are there special requirements for the JS solution? Doesn't work on my latest Chrome (neither in TIO, nor dev tools) - I get an array of correct length, but filled with nulls. \$\endgroup\$
    – targumon
    Commented Jul 26, 2019 at 20:04
  • 1
    \$\begingroup\$ @targumon Just fixed it. Seems posted wrong version... It should work on TIO and most recent Chrome now ... \$\endgroup\$
    – tsh
    Commented Jul 27, 2019 at 6:03
2
\$\begingroup\$

Wolfram Language (Mathematica), 34 bytes

KeySortBy[ToCharacterCode]@*Counts

Try it online!

Returns an association.


SortBy[ToCharacterCode@@#&]@*Tally

Try it online!

Returns a list.

\$\endgroup\$
1
  • \$\begingroup\$ Are you sure it's within the rules to put Characters into the footer instead of into the code? I think it would be better to use CharacterCounts instead of Counts. \$\endgroup\$
    – Roman
    Commented Jul 24, 2019 at 19:35
2
\$\begingroup\$

C# (Visual C# Interactive Compiler), 63 61 bytes

s=>s.OrderBy(c=>c).GroupBy(c=>c).Select(g=>(g.Key,g.Count()))

Try it online!

Thanks to Expired Data for pointing me towards the C# Interactive Compiler and for showing me the power of dynamics.

\$\endgroup\$
2
  • \$\begingroup\$ 61 bytes \$\endgroup\$ Commented Jul 24, 2019 at 8:19
  • 1
    \$\begingroup\$ by the way it's not the fact that it's dynamic that it saves 2 bytes, you could make the return type the correct tuple type, I'm just lazy and like to return dynamic when golfing in case I change my mind about what type I want to return! \$\endgroup\$ Commented Jul 25, 2019 at 9:30
2
\$\begingroup\$

K4, 9 bytes

Solution:

#:'=x@<x:

Example:

q)k)#:'=x@<x:"Over 9001!"
 | 1
!| 1
0| 2
1| 1
9| 1
O| 1
e| 1
r| 1
v| 1

Explanation:

#:'=x@<x: / the solution
       x: / store input as x
      <   / indices to sort ascending
    x@    / apply (@) to x
   =      / group same values
#:'       / count (#:) each (')
\$\endgroup\$
2
\$\begingroup\$

APL(NARS), 26 chars, 52 bytes

{m,¨+/¨{w=⍵}¨m←k[⍋k←∪w←⍵]}

test:

  ⎕fmt{m,¨+/¨{w=⍵}¨m←k[⍋k←∪w←⍵]}'is, this good or not?'
┌12─────────────────────────────────────────────────────────────────────────────────┐
│┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐│
││   4│ │ , 1│ │ ? 1│ │ d 1│ │ g 1│ │ h 1│ │ i 2│ │ n 1│ │ o 4│ │ r 1│ │ s 2│ │ t 2││
│└+───┘ └+───┘ └+───┘ └+───┘ └+───┘ └+───┘ └+───┘ └+───┘ └+───┘ └+───┘ └+───┘ └+───┘2
└∊──────────────────────────────────────────────────────────────────────────────────┘

  {m,¨+/¨{w=⍵}¨m←k[⍋k←∪w←⍵]}
                     k←∪w←⍵     copy the argument in w, k is the argument that has unique elements
               m←k[⍋       ]    copy k order, in m, (so m is argument unique ordered)
         {w=⍵}¨m                see each element of m in w, so each element of m generate a len(w) bit list 
      +/¨                       sum each bit list above obtain the number of element of m in w
   m,¨                          make couples
\$\endgroup\$
6
  • \$\begingroup\$ What a programmer want is few primitive that combine well in resolve a problem, and a visual lay out and eventually comments, for explain better...so space and indentation should be good... \$\endgroup\$
    – user58988
    Commented Jul 25, 2019 at 8:05
  • \$\begingroup\$ I agree, so use those tools that APL gives you: {k,¨+/⍵∘.=⍨k←∪⍵[⍋⍵]} \$\endgroup\$
    – Adám
    Commented Jul 25, 2019 at 9:46
  • \$\begingroup\$ @Adám I prefer to order unique of the array on all the array... \$\endgroup\$
    – user58988
    Commented Jul 25, 2019 at 15:30
  • \$\begingroup\$ If you prefer a longer solution, then your solution is not a serious contender, and it becomes eligible for deletion! \$\endgroup\$
    – Adám
    Commented Jul 25, 2019 at 16:03
  • \$\begingroup\$ Why is this 52 bytes? Does APL/NARS not have SBCS? \$\endgroup\$ Commented Jul 25, 2019 at 17:37
2
\$\begingroup\$

brainfuck, 128 114 bytes

->>,[[-[>>+<<-]>>]>+<+[-<<+]->>,]+[+>[<--.++<<+++++++[>++++++++<-]>++.[-]++++++[>>++++++++<<-]>>.[-].]<[>>+<<-]>>]

Try it online!

How it works:

-                                          sets cell 0 to 255, which is used to move back to cell 2 later on
>>                                         moves to cell 2
,[                                         we load our first input and loop until there are no more characters to load
[-[>>+<<-]>>]                              keeps moving forward skipping every other cell until it has moved forward the ASCII value of the most recently loaded character  
>+<                                        adds one to the next cell for the purpose of later looking at to see how many of that character was entered
+[-<<+]->>                                 goes back to cell 2
,]                                         loads in next character and repeats process if there are remaining characters

+[+>[                                      checks IF the next cell has a value other than 0
<--.                                       then, if true, it prints the ASCII value of the previous cells contents
++<<+++++++[>++++++++<-]>++.               then print ":"
[-]++++++[>>++++++++<<-]>>.                then print the number value of the contents of the current cell
[-].]                                      then print a null character and leaves the if statement
<[>>+<<-]>>]                               continues the same process skipping every other cell, until it repeats 255 times

Thanks to Jo King, -14 bytes.

This is my second brainfuck program, first being hello world, and first time golfing, so please let me know what I can do to improve my program and answer!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You aren't printing a space, you're printing a nul byte. This also won't handle double digits, for example 10 of a character will print ; not 10. You can also shorten the : generation somewhat \$\endgroup\$
    – Jo King
    Commented Jul 25, 2019 at 5:45
  • \$\begingroup\$ Thanks! I shortened the ":" generation, and will try to allow it to print double digits. Are there any problems associated with printing a null byte? \$\endgroup\$ Commented Jul 25, 2019 at 15:12
1
\$\begingroup\$

Clean, 60 bytes

import StdEnv
$s=sort[(c,sum[1\\k<-s|k==c])\\c<-removeDup s]

Try it online!

Defines the function $ :: [Char] -> [(Char, Int)] giving the result as a list of 2-Tuples.
Uses the element-wise behavior of < and thus sort on Tuples to ensure codepoint ordering.

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

Charcoal, 13 bytes

EΦγ№θι⁺⁺ι №θι

Try it online! Link is to verbose version of code. Explanation:

  γ             Printable ASCII
 Φ              Filtered where non-zero
   №            Count of
     ι          Current character in
    θ           Input string
E               Map over filtered characters
        ι       Current character
       ⁺        Plus a space
      ⁺         Plus
          №     Count of
            ι   Current character in
           θ    Input string
                Implicitly output on separate lines
\$\endgroup\$
1
\$\begingroup\$

JavaScript, 57 bytes

Outputs a 2D-Array. Had to implement a quick & dirty fix for the sorting so I'll need to come back to try to golf that.

s=>[...s].map(o=x=>o[x]=-~o[x])&&Object.entries(o).sort()

Try It Online!

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

Kotlin, 75 bytes

fun String.c()=toCharArray().sorted().map{Pair(it,count{s->it==s})}.toSet()

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Replace Pair(it,count{s->it==s}) with it to count{s->it==s}. \$\endgroup\$
    – snail_
    Commented Jul 25, 2019 at 22:35
1
\$\begingroup\$

Japt, 7 bytes

¬ü ®âZl

Test it online!

\$\endgroup\$
1
  • \$\begingroup\$ You can drop the ¬ now. \$\endgroup\$
    – Shaggy
    Commented Jul 31, 2019 at 9:42
1
\$\begingroup\$

Haskell, 46 bytes

f x=[(c,sum[1|d<-x,d==c])|c<-[' '..],elem c x]

Try it online!

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

Ruby -n, 43 bytes

p$_.chars.uniq.sort.map{|c|[c,$_.count(c)]}

Try it online!

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

sfk, 124 87 84 bytes

xed -i
+chars
+count -same -case
+xed "_?????*x*[white]?_[parts 6,3,1]_"
+sort -case

Try it online!

Gives output in the form [character]x[count] with count padded to 5 digits.

\$\endgroup\$

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