Character Frequency in a String

23

4

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]]

bigyihsuan

Posted 6 years ago

Reputation: 1 483

Question was closed 6 years ago

Related and related. – bigyihsuan – 6 years ago

7Output the frequency of each character, in ASCII order. but e after v – Adám – 6 years ago

4May I output a,1b,2c,3? – tsh – 6 years ago

Could I use PETSCII instead? -> https://www.c64-wiki.com/wiki/PETSCII Also, do you mean true ASCII (7-bit), or simply ASCII-compatible, like extended ASCII or UTF-8?

– Shaun Bebbers – 6 years ago

I assume the output be for aAbBcCdD will it be A:1, B:1, C:1, D:1, a:1, b:1 c:1, d:1 - your examples of input/output has a type as Adam has mentioned above. – Shaun Bebbers – 6 years ago

You say there is a single character separator yet your first two examples use 2 and 3 character separators. Is the mistake in the spec or the examples? – Post Rock Garf Hunter – 6 years ago

@tsh No, but a,1 b,2 c,3 is a valid output – bigyihsuan – 6 years ago

1@ShaunBebbers ooo that's something. I'll allow it. ASCII-compatibles are also fine, provided you say what encoding it is. – bigyihsuan – 6 years ago

May we assume nonempty input? – Khuldraeseth na'Barya – 6 years ago

@Khuldraesethna'Barya Yes. – bigyihsuan – 6 years ago

Can there be any leading/trailing characters on the output? before the first line or after the last line? – Marie – 6 years ago

@KevinCruijssen Ah-ha, the very challenge I thought of but couldn't find when I saw this in the Sandbox so, in a rare occurrence for me, I'm gonna swing my hammer as I don't think the requirement that the output be sorted makes this significantly different. – Shaggy – 6 years ago

Answers

12

Python 3, 50, 43, 41 bytes

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

Try it online!

James

Posted 6 years ago

Reputation: 54 537

4

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!

– maxb – 6 years ago

7You 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))}) – Triggernometry – 6 years ago

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)} – spyr03 – 6 years ago

9

Ohm v2, 2 bytes

Try it online!

      implicit input
S     sort string
 Ö    run-length encoding
      implicitly print

Cinaski

Posted 6 years ago

Reputation: 1 588

8

Python 3, 41 bytes

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

Try it online!

U10-Forward

Posted 6 years ago

Reputation: 347

7

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 #

Jonah

Posted 6 years ago

Reputation: 8 729

2Nice! I forgot about /., my solution with = was significantly longer: (;/@~.,.1;/@:#.=)@/:~ – Conor O'Brien – 6 years ago

7

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 .

Unrelated String

Posted 6 years ago

Reputation: 5 300

6

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

Adám

Posted 6 years ago

Reputation: 37 779

6

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

Jo King

Posted 6 years ago

Reputation: 38 234

Beat me by a few minutes. 49 bytes

– cole – 6 years ago

1I 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 – cole – 6 years ago

5

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

Jo King

Posted 6 years ago

Reputation: 38 234

5

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?

maxb

Posted 6 years ago

Reputation: 5 754

"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. – Jonah – 6 years ago

4

Bash, 27 22 20 bytes

fold -1|sort|uniq -c

Try it online!

-5 bytes thanks to Neil

-2 bytes thanks to Digital Trauma

Jonah

Posted 6 years ago

Reputation: 8 729

2Why not take input on STDIN? – Neil – 6 years ago

Thanks @Neil, updated. – Jonah – 6 years ago

2fold -1 instead of grep -o . saves 2 – Digital Trauma – 6 years ago

@DigitalTrauma nice. updated. – Jonah – 6 years ago

4

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.

Nick Kennedy

Posted 6 years ago

Reputation: 11 829

4

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

Sok

Posted 6 years ago

Reputation: 5 592

4

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

t-clausen.dk

Posted 6 years ago

Reputation: 2 874

1Your order by is alphabetical, but it should be in ascii order. it should be ORDER BY ascii(w) – Einacio – 6 years ago

@Einacio thanks, I had missed that part of the question. I corrected as you suggested – t-clausen.dk – 6 years ago

1If 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. – BradC – 6 years ago

@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. – t-clausen.dk – 6 years ago

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

– BradC – 6 years ago

4

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

640KB

Posted 6 years ago

Reputation: 7 149

3

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.

tsh

Posted 6 years ago

Reputation: 13 072

$.($&) can become $.& – user41805 – 6 years ago

64 bytes – Shaggy – 6 years ago

@Shaggy Nice idea. And I moved one more step based on that. – tsh – 6 years ago

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. – targumon – 6 years ago

1@targumon Just fixed it. Seems posted wrong version... It should work on TIO and most recent Chrome now ... – tsh – 6 years ago

3

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

AdmBorkBork

Posted 6 years ago

Reputation: 41 581

That output is perfectly fine. – bigyihsuan – 6 years ago

is a splatted string 'any convenient method'? Try it online! another word, is a char array a representation of a string?

– mazzy – 6 years ago

@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! – AdmBorkBork – 6 years ago

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. – mazzy – 6 years ago

@mazzy I didn't know that. How would that work on TIO? You can't use @' because that's a here-string. – AdmBorkBork – 6 years ago

@AdmBorkBork I think TIO does not have splatting functionality. Powershell have. That's why we have to use a footer section on TIO instead an argument section. My question is whether the character array (args after splatting) can be treated as a string in this task? – mazzy – 6 years ago

1

@mazzy Yes, a [char[]] can be called a string per Meta consensus. Do you mean something like this?

– AdmBorkBork – 6 years ago

yes. thanks. it would be nice if TIO could use splatting. – mazzy – 6 years ago

3

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!

ErikF

Posted 6 years ago

Reputation: 2 149

93 bytes by moving i=31 into the declaration: Try it online!

– Οurous – 6 years ago

That's clever using negative counting like that. – AdmBorkBork – 6 years ago

2

Wolfram Language (Mathematica), 34 bytes

KeySortBy[ToCharacterCode]@*Counts

Try it online!

Returns an association.


SortBy[ToCharacterCode@@#&]@*Tally

Try it online!

Returns a list.

attinat

Posted 6 years ago

Reputation: 3 495

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. – Roman – 6 years ago

2

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.

Charlie

Posted 6 years ago

Reputation: 11 448

61 bytes – Expired Data – 6 years ago

1by 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! – Expired Data – 6 years ago

2

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 (')

streetster

Posted 6 years ago

Reputation: 3 635

2

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!

Nicholas Kopiwoda

Posted 6 years ago

Reputation: 21

1You 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 – Jo King – 6 years ago

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? – Nicholas Kopiwoda – 6 years ago

2

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

RosLuP

Posted 6 years ago

Reputation: 3 036

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... – RosLuP – 6 years ago

I agree, so use those tools that APL gives you: {k,¨+/⍵∘.=⍨k←∪⍵[⍋⍵]} – Adám – 6 years ago

@Adám I prefer to order unique of the array on all the array... – RosLuP – 6 years ago

If you prefer a longer solution, then your solution is not a serious contender, and it becomes eligible for deletion! – Adám – 6 years ago

Why is this 52 bytes? Does APL/NARS not have SBCS?

– AdmBorkBork – 6 years ago

@AdmBorkBork I do not know... They say Nars use 16bit character set – RosLuP – 6 years ago

1

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.

Οurous

Posted 6 years ago

Reputation: 7 916

1

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.

Οurous

Posted 6 years ago

Reputation: 7 916

1

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!

Shaggy

Posted 6 years ago

Reputation: 24 623

1

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

Neil

Posted 6 years ago

Reputation: 95 035

1

Japt, 10 8 bytes

ü
mÎíUmÊ

Try it

ü\nmÎíUmÊ     :Implicit input of string U
ü             :Split, sort and partition by value
 \n           :Reassign to U
   m          :Map
    Î         :  First element
     í        :Interleave with
      UmÊ     :  Map lengths of U

Shaggy

Posted 6 years ago

Reputation: 24 623

1

Kotlin, 75 bytes

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

Try it online!

Quinn

Posted 6 years ago

Reputation: 1 153

Replace Pair(it,count{s->it==s}) with it to count{s->it==s}. – snail_ – 6 years ago

1

Java (JDK), 82 bytes

s->s.stream().sorted().distinct().map(c->c+" "+s.stream().filter(x->c==x).count())

Try it online!

Olivier Grégoire

Posted 6 years ago

Reputation: 10 647

1

Japt, 7 bytes

¬ü ®âZl

Test it online!

Oliver

Posted 6 years ago

Reputation: 7 160

You can drop the ¬ now. – Shaggy – 6 years ago

1

Haskell, 46 bytes

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

Try it online!

nimi

Posted 6 years ago

Reputation: 34 639

1

Ruby -n, 43 bytes

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

Try it online!

Value Ink

Posted 6 years ago

Reputation: 10 608

1

Kotlin, 53 bytes

Returns a Map<Char, Int> associating characters to frequencies. The map keys are sorted in ASCII order (it's a java.util.SortedMap underneath.)

{s->s.associateWith{c->s.count{it==c}}.toSortedMap()}

Try it online!

snail_

Posted 6 years ago

Reputation: 1 982

Is this legal? I once got called out for defining my function in the header like you did here... Is that a legal code golf move because I'm genuinely not sure -> I can drop quite a few bytes on my Kotlin answer if so – Quinn – 6 years ago

I'm not entirely sure what the consensus is but I recall it being legal for lambdas specifically. I've never been called out for it. – snail_ – 6 years ago

This meta post states that for lambdas/anonymous functions only the function body is required. Since Kotlin can use type inference and you can indicate the function signature in the declaration, it seems to me like that counts as part of the assignment as well. – snail_ – 6 years ago

1

05AB1E, 8 6 bytes

SêDŠ¢ø

Try it online!

Expired Data

Posted 6 years ago

Reputation: 3 129

6 bytes – Kevin Cruijssen – 6 years ago

1

R (in C locale), 32 bytes

function(s)table(strsplit(s,''))

Try it online!

strsplit the input character string by the empty string to separate its characters then table builds a contingency table of the unique character counts.

Rui Barradas

Posted 6 years ago

Reputation: 131

identical(names(f("Over 9001!")), sort(names(f("Over 9001!")))) returns TRUE. – Rui Barradas – 6 years ago

@Giuseppe Right. Besides, my example is meaningless, if table sorts according to the locale in effect, so will sort. – Rui Barradas – 6 years ago

@Giuseppe Yes, like this users will have a bad surprise. – Rui Barradas – 6 years ago

Something like this should be fine, just put a note saying "R (in C locale), 32 bytes" as the title, or something similar

– Giuseppe – 6 years ago

@Giuseppe Thanks, it's my first post and I really needed assistance. – Rui Barradas – 6 years ago

No problem! There's a chatroom for R golfing; feel free to ping me (or any of the other R golfers) there and we'll be happy to answer.

– Giuseppe – 6 years ago

1

JavaScript, 55  48  62 57 bytes

a=>[...a].sort().map(c=>o.set(c,-~o.get(c)),o=new Map)&&o

output is a Map

contrary to Objects, Map remember the order in which values where sets

let input = document.getElementById("input")
let run = document.getElementById("run")
let output = document.getElementById("output")

run.onclick = () => {
  output.innerHTML = ""
  func(input.value).forEach((val, key) => output.innerHTML += `'${key}' => ${val}<br>`)
}

let func = a=>[...a].sort().map(c=>o.set(c,-~o.get(c)),o=new Map)&&o
<input id="input"/>
<button id="run">run</button>
<p id="output"></p>

Thanks to Shaggy and Einacio for pointing my flaws

-5 bytes thanks to Shaggy

jonatjano

Posted 6 years ago

Reputation: 331

Unfortunately, this doesn't seem to sort the output correctly. – Shaggy – 6 years ago

I didn't see that I was confident object kept entries in the same order as they were added to it, I'll try to correct it later – jonatjano – 6 years ago

i'm not sure about the input. it's defined in the question that it's a string, so splitting it should be part of your function as well – Einacio – 6 years ago

seems like i misinterpreted the Input and output can be given using any convenient method. part :/ – jonatjano – 6 years ago

+1 for Map; don't think I've seen it used here before. But you have a lot more parentheses than you actually need and you can ditch the get: https://tio.run/##BcExDoMwDADAr1AGZEtg0bFD@AHiAYjBMqZqBXGURLDx9XD355OTxF/InbdVy@YKu2EmIl4oWcyAdHAAcYNR0gzSdrfNsmBrzutVjRywaayI@WS70m5f2KCeTo3Vp@/frxqxPA – Shaggy – 6 years ago

@Shaggy actually I can't ditch the get look again your TIO, it doesn't count repeated characters. Still could remove some parentheses thank to you. – jonatjano – 6 years ago

1

Forth (gforth), 134 bytes

: f here 128 allot dup 128 erase -rot 0 do 2dup i + c@ + 1 swap +! loop drop
128 0 do dup i + c@ ?dup if i emit ." : ". cr then loop ;

Try it online!

Limitation: won't work if any character occurs more than 256 times in a single string (to fix this requires an extra ~25 bytes)

Explanation

  • Allocate an area of memory 128 bytes (cells if needed) wide to use as an array/dictionary
  • Zero out all bytes/cells in that area
  • Loop through string, for each character
    • Add ascii value to array starting address, then increment value at that address by 1
  • When finished, loop through array/dictionary and output all chars/values that have a value other than 0

Code Explanation

: f                     \ start new word definition
  here 128 allot        \ allocate 128 bytes to use as an array
  dup 128 erase         \ fill array with zeros
  -rot                  \ stick array address behind string address
  0 do                  \ start counted loop from 0 to string-length - 1
    2dup                \ duplicate array and string address
    i + c@              \ get ascii value of next character in string
    + 1 swap +1         \ add to array address, then add 1 to the value in that array position
  loop                  \ end the loop
  drop                  \ drop the string address [no longer needed]
  128 0 do              \ start a counted loop from 0 to 127
    dup i + c@          \ get value at next array position
    ?dup                \ duplicate if >0
    if                  \ start an if block (if >0)
      i emit            \ output the character
      ." : ".           \ output ": " followed by the number of that char in the string
      cr                \ output a newline
    then                \ end the if block
  loop                  \ end the loop
;                       \ end the word definition

reffu

Posted 6 years ago

Reputation: 1 361

0

Red, 92 bytes

func[s][parse/case sort/case s[any[copy k[copy t skip thru any t](print[t length? to""k])]]]

Try it online!

Galen Ivanov

Posted 6 years ago

Reputation: 13 815

0

Perl 5 (-nF -M5.01 -MList::Util=uniq), 49 41 bytes

41 bytes : for$a(uniq sort@F){say"$a ",eval"y/$a//"} doesn't work if input contains a slash. Otherwise, 36 bytes : for$a(uniq sort@F){say"$a "./\Q$a/g} doesn't work because of //g in scalar context.

for$a(uniq sort@F){say"$a ".(()=/\Q$a/g)}

TIO

first answer

Nahuel Fouilleul

Posted 6 years ago

Reputation: 5 582

44 bytes (and fewer commandline options, even though we don't count those now) – Xcali – 6 years ago

41 bytes (with some extra cli options) – Xcali – 6 years ago

9 characters longer but without the List::Util requirement: @a{@F}=1;for$a(sort keys%a){say"$a ".(()=/\Q$a/g)} – msh210 – 6 years ago

@msh210, thanks for the trick @a{@F}=1 however first answer link is shorter also without List::Util, and options doesn't count now – Nahuel Fouilleul – 6 years ago

0

Scala, 64 62 bytes

(x:String)=>x.groupBy(identity).mapValues(_.size).toSeq.sorted

Soapy

Posted 6 years ago

Reputation: 251

0

C++ (gcc), 85 bytes

#include<map>
auto f(std::string s){std::map<char,int>m;for(int c:s)m[c]++;return m;}

Try it online!

This solution makes use of several nice features of std::map:

  1. It has a sorted iterator, with default lexicographic ordering.
  2. The []-operator default initializes members, in case of int it zeroes it.

Also, C++17 allows for golfing using auto and range-for loop.

movatica

Posted 6 years ago

Reputation: 635

0

SNOBOL4 (CSNOBOL4), 120 bytes

	A =&ALPHABET
	I =INPUT
S	O =0
	A LEN(1) . X REM . A	:F(END)
R	I X =	:F(O)
	O =O + 1	:(R)
O	OUTPUT =GT(O) X 0 O	:(S)
END

Try it online!

	A =&ALPHABET			;* alias for &ALPHABET (256 characters in ascending order)
	I =INPUT			;* read input
S	O =0				;* set counter to 0
	A LEN(1) . X REM . A	:F(END)	;* set X to first letter of A
					;* setting the REMainder to A
					;* and going to END if no letters remain
R	I X =	:F(O)			;* remove the first occurrence of X from I
					;* and output if none are left
	O =O + 1	:(R)		;* increment the counter, going to R
O	OUTPUT =GT(O) X 0 O	:(S)	;* if O > 0,
					;* output X 0 and O in that order
					;* then GOTO S
END

Giuseppe

Posted 6 years ago

Reputation: 21 077

0

JavaScript (Node.js), 56 bytes

s=>[...s].sort().reduce((a,b)=>(a[b]=(a[b]||0)+1)&&a,{})

Try it online!

2oppin

Posted 6 years ago

Reputation: 101

1Your output is incorrect. It is not in ASCII order, as can be seen with the input Over 9001!, where v is before e and r, which is not the case in ASCII order. Adding a .sort() would make it correct, at 56 bytes: s=>[...s].sort().reduce((a,b)=>(a[b]=(a[b]||0)+1)&&a,{}) – bigyihsuan – 6 years ago

@bigyihsuan, thanks, indeed missed the ordering – 2oppin – 6 years ago