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 2019-07-24T04:59:57.320

Reputation: 1 483

Question was closed 2019-07-26T22:40:03.753

Related and related. – bigyihsuan – 2019-07-24T05:00:28.330

7Output the frequency of each character, in ASCII order. but e after v – Adám – 2019-07-24T06:21:17.943

4May I output a,1b,2c,3? – tsh – 2019-07-24T07:40:31.237

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 – 2019-07-24T11:48:07.860

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 – 2019-07-24T11:54:37.213

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 – 2019-07-24T12:05:18.857

@tsh No, but a,1 b,2 c,3 is a valid output – bigyihsuan – 2019-07-24T12:43:25.163

1@ShaunBebbers ooo that's something. I'll allow it. ASCII-compatibles are also fine, provided you say what encoding it is. – bigyihsuan – 2019-07-24T12:47:51.703

May we assume nonempty input? – Khuldraeseth na'Barya – 2019-07-25T21:18:21.897

@Khuldraesethna'Barya Yes. – bigyihsuan – 2019-07-25T21:20:32.903

Can there be any leading/trailing characters on the output? before the first line or after the last line? – Marie – 2019-07-26T20:18:04.767

@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 – 2019-07-26T22:39:45.330

Answers

12

Python 3, 50, 43, 41 bytes

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

Try it online!

James

Posted 2019-07-24T04:59:57.320

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 – 2019-07-24T06:52:40.993

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 – 2019-07-24T14:18:52.240

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 – 2019-07-26T13:05:14.020

9

Ohm v2, 2 bytes

Try it online!

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

Cinaski

Posted 2019-07-24T04:59:57.320

Reputation: 1 588

8

Python 3, 41 bytes

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

Try it online!

U10-Forward

Posted 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

Reputation: 8 729

2Nice! I forgot about /., my solution with = was significantly longer: (;/@~.,.1;/@:#.=)@/:~ – Conor O'Brien – 2019-07-24T18:03:34.923

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

Reputation: 38 234

Beat me by a few minutes. 49 bytes

– cole – 2019-07-24T06:41:51.720

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 – 2019-07-24T06:51:09.243

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 – 2019-07-24T07:31:14.887

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 2019-07-24T04:59:57.320

Reputation: 8 729

2Why not take input on STDIN? – Neil – 2019-07-24T09:15:52.363

Thanks @Neil, updated. – Jonah – 2019-07-24T17:24:47.267

2fold -1 instead of grep -o . saves 2 – Digital Trauma – 2019-07-24T22:51:47.717

@DigitalTrauma nice. updated. – Jonah – 2019-07-24T23:04:32.483

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

Reputation: 2 874

1Your order by is alphabetical, but it should be in ascii order. it should be ORDER BY ascii(w) – Einacio – 2019-07-25T14:12:47.530

@Einacio thanks, I had missed that part of the question. I corrected as you suggested – t-clausen.dk – 2019-07-25T22:05:18.530

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 – 2019-07-26T13:57:14.040

@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 – 2019-07-29T08:19:09.920

@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 – 2019-07-29T16:14:22.143

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

Reputation: 13 072

$.($&) can become $.& – user41805 – 2019-07-24T08:10:22.743

64 bytes – Shaggy – 2019-07-24T08:19:48.870

@Shaggy Nice idea. And I moved one more step based on that. – tsh – 2019-07-24T08:37:37.543

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 – 2019-07-26T20:04:54.170

1@targumon Just fixed it. Seems posted wrong version... It should work on TIO and most recent Chrome now ... – tsh – 2019-07-27T06:03:10.840

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 2019-07-24T04:59:57.320

Reputation: 41 581

That output is perfectly fine. – bigyihsuan – 2019-07-24T13:46:38.117

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

– mazzy – 2019-07-25T13:34:36.760

@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 – 2019-07-25T17:34:11.923

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 – 2019-07-25T17:49:46.360

@mazzy I didn't know that. How would that work on TIO? You can't use @' because that's a here-string. – AdmBorkBork – 2019-07-25T18:57:36.157

@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 – 2019-07-26T03:57:58.420

1

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

– AdmBorkBork – 2019-07-26T18:05:01.693

yes. thanks. it would be nice if TIO could use splatting. – mazzy – 2019-07-26T18:12:08.847

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 2019-07-24T04:59:57.320

Reputation: 2 149

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

– Οurous – 2019-07-25T00:39:30.743

That's clever using negative counting like that. – AdmBorkBork – 2019-07-25T17:38:42.607

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 2019-07-24T04:59:57.320

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 – 2019-07-24T19:35:25.543

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 2019-07-24T04:59:57.320

Reputation: 11 448

61 bytes – Expired Data – 2019-07-24T08:19:11.280

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 – 2019-07-25T09:30:33.420

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 – 2019-07-25T05:45:33.660

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 – 2019-07-25T15:12:53.767

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 2019-07-24T04:59:57.320

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 – 2019-07-25T08:05:47.783

I agree, so use those tools that APL gives you: {k,¨+/⍵∘.=⍨k←∪⍵[⍋⍵]} – Adám – 2019-07-25T09:46:31.913

@Adám I prefer to order unique of the array on all the array... – RosLuP – 2019-07-25T15:30:45.560

If you prefer a longer solution, then your solution is not a serious contender, and it becomes eligible for deletion! – Adám – 2019-07-25T16:03:44.980

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

– AdmBorkBork – 2019-07-25T17:37:10.180

@AdmBorkBork I do not know... They say Nars use 16bit character set – RosLuP – 2019-07-25T19:38:36.337

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

Reputation: 1 153

Replace Pair(it,count{s->it==s}) with it to count{s->it==s}. – snail_ – 2019-07-25T22:35:17.873

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 2019-07-24T04:59:57.320

Reputation: 10 647

1

Japt, 7 bytes

¬ü ®âZl

Test it online!

Oliver

Posted 2019-07-24T04:59:57.320

Reputation: 7 160

You can drop the ¬ now. – Shaggy – 2019-07-31T09:42:40.037

1

Haskell, 46 bytes

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

Try it online!

nimi

Posted 2019-07-24T04:59:57.320

Reputation: 34 639

1

Ruby -n, 43 bytes

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

Try it online!

Value Ink

Posted 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 – 2019-07-25T16:37:00.937

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_ – 2019-07-25T21:45:10.593

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_ – 2019-07-25T22:28:02.847

1

05AB1E, 8 6 bytes

SêDŠ¢ø

Try it online!

Expired Data

Posted 2019-07-24T04:59:57.320

Reputation: 3 129

6 bytes – Kevin Cruijssen – 2019-07-26T08:11:37.770

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 2019-07-24T04:59:57.320

Reputation: 131

identical(names(f("Over 9001!")), sort(names(f("Over 9001!")))) returns TRUE. – Rui Barradas – 2019-07-25T15:49:38.947

@Giuseppe Right. Besides, my example is meaningless, if table sorts according to the locale in effect, so will sort. – Rui Barradas – 2019-07-25T16:00:41.040

@Giuseppe Yes, like this users will have a bad surprise. – Rui Barradas – 2019-07-25T16:25:31.447

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

– Giuseppe – 2019-07-25T18:05:14.183

@Giuseppe Thanks, it's my first post and I really needed assistance. – Rui Barradas – 2019-07-25T18:48:15.477

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 – 2019-07-25T18:57:07.857

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 2019-07-24T04:59:57.320

Reputation: 331

Unfortunately, this doesn't seem to sort the output correctly. – Shaggy – 2019-07-25T23:32:00.643

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 – 2019-07-26T07:14:54.847

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 – 2019-07-26T07:18:24.790

seems like i misinterpreted the Input and output can be given using any convenient method. part :/ – jonatjano – 2019-07-26T07:20:38.490

+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 – 2019-07-26T22:04:08.577

@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 – 2019-07-28T11:32:16.547

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

Reputation: 5 582

44 bytes (and fewer commandline options, even though we don't count those now) – Xcali – 2019-07-24T17:07:27.697

41 bytes (with some extra cli options) – Xcali – 2019-07-25T04:32:49.943

9 characters longer but without the List::Util requirement: @a{@F}=1;for$a(sort keys%a){say"$a ".(()=/\Q$a/g)} – msh210 – 2019-07-25T23:17:25.933

@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 – 2019-07-26T07:52:21.890

0

Scala, 64 62 bytes

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

Soapy

Posted 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 2019-07-24T04:59:57.320

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 – 2019-07-26T19:41:19.473

@bigyihsuan, thanks, indeed missed the ordering – 2oppin – 2019-07-26T20:17:30.803