8
\$\begingroup\$

GOAL : To Implement a character counting program

This is how this counting system works :

input of the program is a set of printable ASCII characters . the program counts each type of character , and outputs the number of each character , starting from first mentioned character to last mentioned character .

Example :

input : aaaabbbbbcccc    123445b
output : 4 6 4 4 1 1 1 2 1

Which 4 is number of as , 6 is number of bs , 4 is number of cs , 4 is number of spaces () and so on . Also you can split answers with space (like example) , EOL , or anything other than numerals .

Rules

Your program must log to STDOUT or an acceptable alternative, if STDOUT is not available.

Your program must be a full, runnable program, and not a function or snippet

It's optional to mention the ungolfed version of program and/or a short explanation .

Test input : ThIs Is ThE iNPUT , WITH 72/2 CHARS!

Test output : 4 2 3 2 7 1 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1

\$\endgroup\$
5

20 Answers 20

7
\$\begingroup\$

MATL, 3 bytes

8#u

Input is a string enclosed with quotation marks (which is allowed by default)

Try it online!

Explanation

u is the unique function, which essentially removes duplicates. It can produce up to four outputs. The fourth output is the count of unique characters, identified in order of appearance.

8# specifies that the fourth output of u should be produced. In general, 2# means "produce two outputs", 3# means "produce three outputs" etc. When the maximum number of function outputs is reached, larger numbers mean "take the first output only", or "the second only" etc. Thus, since u has four possible outputs, 4# would produce all four outputs; 5# produces the first, 6# the second, etc.

\$\endgroup\$
3
  • \$\begingroup\$ well , it doesn't work with ' at first and end , which is not allowed , can you edit it in a way that it doesn't need ' ? or is this an implemented feathure in the language ? \$\endgroup\$
    – user55673
    Jun 23, 2016 at 9:41
  • \$\begingroup\$ I'm not sure what you mean. About strings using quotes, see here \$\endgroup\$
    – Luis Mendo
    Jun 23, 2016 at 9:43
  • \$\begingroup\$ Ok , i didn't know that \$\endgroup\$
    – user55673
    Jun 23, 2016 at 9:45
4
\$\begingroup\$

05AB1E, 6 bytes

Ùv¹y¢,

Explained

Ùv      # for each unique char in original order
  ¹y¢   # count number of occurances in input string
     ,  # print on newline

Try it online

\$\endgroup\$
2
  • \$\begingroup\$ you have forgot to delete """ (quation marks) in try it online , which produced extra 2 at the first of output \$\endgroup\$
    – user55673
    Jun 23, 2016 at 9:30
  • \$\begingroup\$ @GLASSIC: Yeah, I just noticed. Thanks! \$\endgroup\$
    – Emigna
    Jun 23, 2016 at 9:31
4
\$\begingroup\$

Pyth, 4 bytes

/LQ{

Test suite.

Explanation

/LQ{    Input: Q
/LQ{Q   Implicitly fill arguments

   {Q   Yield the unique elements of Q.
 L      For each unique element:
/       Yield its number of occurrences
  Q     in Q.
\$\endgroup\$
3
\$\begingroup\$

J, 18 15 bytes

echo#/.~stdin''

Following the challenge spec to write a program, the above is a one-line script in J that reads a line from stdin, computes the result, and prints it to stdout.

If using an online interpreter, it would require 4 bytes since without stdio, only function arguments could be used.

#/.~

Straight-forward application of adverbs /. and ~ to the tally # verb.

Usage

As a script,

$ echo -n 'aaaabbbbbcccc    123445b' | jconsole golf.j 
4 6 4 4 1 1 1 2 1

As a function,

   (#/.~) 'aaaabbbbbcccc    123445b'
4 6 4 4 1 1 1 2 1

Explanation

#/.~  Input: s
   ~  Reflects the input
 /.   An adverb that executes a verb on each set of identical items in s
      Operates in the order of first-seen distinct items in s
#     Get the size of each set of identical items
      Returns a list of the sizes of identical items
\$\endgroup\$
2
\$\begingroup\$

CJam, 9 bytes

l__&\fe=p

Test it here.

Explanation

l    e# Read input.
__   e# Make two copies.
&    e# Set intersection - removes duplicates.
\    e# Swap with input.
fe=  e# For each (unique) character, count its occurrences.
p    e# Print as array literal.
\$\endgroup\$
2
\$\begingroup\$

Dyalog APL, 10 bytes

Shortest by byte count

+⌿t∘.=∪t←⍞

t←⍞ get character input and store as t

`∪' unique elements of

t∘.= table of which elements of t are equal to (the unique elements of t)

+⌿ sum the columns

5 character solution which unfortunately is 15 bytes:

⊢∘≢⌸⍞

get character input

make a table of contents containing...

⊢∘≢ the tally () of the indices while the entries are ignored ()

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

Jelly, 4 bytes

Qċ@€

Try it online

Explanation

Qċ@€   Main link. Argument: S

Q      Remove duplicate characters from S.
       Current value v contains each character of S once sorted by first appearance.
  @€   For each character in v.
 ċ       count its occurrence in S.
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 56 bytes

Print@StringRiffle[Last/@Tally@Characters@InputString[]]

Essentially, Tally does exactly what the challenge asks for (although it gives pairs of {element, count}). The rest is just for working with strings and proper I/O for a full program.

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

Retina, 30 28 bytes

2 bytes thanks to Martin Ender.

+`((.).+)\2
$2$1
(.)\1*
$.&¶

Try it online!

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

Brachylog, 32 bytes

:efd:?:{tL,?he:L:{t:.m~h?}fl.}f.

Awfully long but there's no simple way of counting elements of something yet…

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

Java 7, 246 235 231 213 bytes

Loads of bytes removed thanks to cliffroot.

import java.util.*;class M{public static void main(String[]a){Map<Long,Long>m=new LinkedHashMap();for(long c:a[0].toCharArray())m.put(c,m.get(c)!=null?m.get(c)+1:1);for(Long e:m.values())System.out.print(e+" ");}}

Ungolfed & test code:

Try it here.

import java.util.*;

class Main{
  public static void main(String[] a){
    // Test code:
    a = new String[]{ "ThIs Is ThE iNPUT , WITH 72/2 CHARS!" };

    Map<Long, Long> m = new LinkedHashMap();
    for(long c : a[0].toCharArray()){
      m.put(c, m.get(c) != null ? m.get(c) + 1 : 1);
    }
    for(Long e : m.values()){
      System.out.print(e + " ");
    }
  }
}

Output:

4 2 3 2 7 1 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 
\$\endgroup\$
4
  • 1
    \$\begingroup\$ You can use Map m=new LinkedHashMap which saves some bytes. Also in your first loop you can use int instead of char \$\endgroup\$
    – cliffroot
    Jun 23, 2016 at 11:03
  • \$\begingroup\$ @cliffroot Ah of course, edited. Thanks! \$\endgroup\$ Jun 23, 2016 at 11:06
  • 1
    \$\begingroup\$ Map<Long,Long>m=new LinkedHashMap<>(); saves 2 more bytes because it allows to remove cast to int (though you'll have to use long in the first cycle) and to use Map.Entry in your second for-each loop. \$\endgroup\$
    – cliffroot
    Jun 23, 2016 at 11:09
  • 1
    \$\begingroup\$ The last for loop is basically just for(Long e:m.values())System.out.print(e+" "); \$\endgroup\$
    – cliffroot
    Jun 23, 2016 at 12:15
1
\$\begingroup\$

Python 3, 134 81 bytes

s,r=input(),[]
for c in s:
 k,s=s.count(c),s.replace(c,'')
 if k:r+=[k]
print(*r)

Output:

4 2 3 2 7 1 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1

Not that short :(


Another approach: 109 bytes

Not shorter than the others but the counting happens in a one-liner.

s=input()
k=[i[1]for i in sorted({i:str(s.count(i))for i in s}.items(),key=lambda v:s.index(v[0]))]
print(*k)

Edit: Golfed 53 bytes thanks to @Dr Green Eggs and Iron Man Edit 2: Added one-liner method

\$\endgroup\$
1
  • \$\begingroup\$ You could make this a lot shorter by deleting the first and last lines, and putting s=input();r=[] \$\endgroup\$
    – DJMcMayhem
    Jun 23, 2016 at 13:41
1
\$\begingroup\$

Java 7, 172 168 bytes

class M{public static void main(String[]a){int[]m=new int[256];byte[]b=a[0].getBytes();for(int z:b)m[z]++;for(int z:b){System.out.print(m[z]>0?(m[z]+" "):"");m[z]=0;}}}

Stores number of occurrences in an int array, then for each char print number of occurrences and replace this value with zero so it won't be printed again.

Whitespaces and comments added:

class M{
    public static void main(String[]a){
        int[]m=new int[256]; // map, ascii value to number of occurrences
        byte[b]=a[0].getBytes();
        for(int z:b)m[z]++; // count number of occurrences
        for(int z:b){
            System.out.print(m[z]>0?(m[z]+" "):""); // print result 
            m[z]=0; // make it not be printed again
        }
    }
}

See it online: https://ideone.com/7X58F9

\$\endgroup\$
2
  • 1
    \$\begingroup\$ +1 and since you've helped me out in my Java 7 answer I'll help you as well. :) You can add byte[]b=a[0].getBytes(); and replace both a[0].getBytes() with b to save 4 bytes. \$\endgroup\$ Jun 24, 2016 at 7:40
  • \$\begingroup\$ @Kevin Cruijssen oh right, thank you. We can arguably do byte[]m=new byte[256],b=a[0].getBytes();, but then number of symbols occurrences will be limited to 256 \$\endgroup\$
    – cliffroot
    Jun 24, 2016 at 8:18
0
\$\begingroup\$

C#

public static void Main(string[] args)
    {
        string str = "aaaabbbbbcccc    123445b";
        Dictionary<char, int> counts = new Dictionary<char, int>();

        for (int i = 0; i < str.Length; i++)
           if (counts.ContainsKey(str[i]))
               counts[str[i]]++;
           else
              counts.Add(str[i], 1);

        foreach (var count in counts)
         Console.WriteLine("{0} = {1}", count.Key, count.Value.ToString());
    }
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Hi, and welcome to the site! This is a code-golf challenge, meaning all answers must at least make an attempt to shorten their code as much as possible. For example, you can remove your whitespace, and use one letter variable names. You can also look through our list of tips for golfing in C#. If you don't try to shorten this code, the answer is invalid, and it will probably need to be deleted. \$\endgroup\$
    – DJMcMayhem
    Jun 23, 2016 at 13:33
0
\$\begingroup\$

ES6, 90 bytes

a=prompt();b=new Map();for(c of a)b.set(c,(b.get(c)|0)+1);alert([...b.values()].join(' '))

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

Python 3, 76 73 bytes

3 bytes shorter:

s,a=input(),[]
for y in s:a+=(y,'')[y in a]
print([s.count(x)for x in a])

Old version:

s=input();print([s.count(x)for x in sorted(set(s),key=lambda i:s.index(i))])

Iterates over a sorted set of unique characters from the input, counts the occurrences, and outputs a list of the counts.

\$\endgroup\$
7
  • \$\begingroup\$ @LeakyNun That returns the generator object for me. \$\endgroup\$ Jun 23, 2016 at 12:29
  • \$\begingroup\$ I don't understand. Doesn't sorted(s) have the same number of elements? \$\endgroup\$
    – Leaky Nun
    Jun 23, 2016 at 12:30
  • \$\begingroup\$ sorted(s) has the same number of elements as the input, but I'm sorting a set of the input that has only unique elements (using the indexes of the original as the key, to preserve the order). \$\endgroup\$ Jun 23, 2016 at 12:37
  • \$\begingroup\$ Does set preserve input order? \$\endgroup\$
    – Leaky Nun
    Jun 23, 2016 at 12:38
  • \$\begingroup\$ No, it's unordered. docs.python.org/3/tutorial/datastructures.html#sets A set is an unordered collection with no duplicate elements. \$\endgroup\$ Jun 23, 2016 at 12:41
0
\$\begingroup\$

Python 3, 93 bytes

s=input();c,o=[],""
for i in s:
 if i not in c:c+=i
for i in c:o+=str(s.count(i))+" "
print o
\$\endgroup\$
0
\$\begingroup\$

Matlab, 47 chars

@(y)arrayfun(@(x)sum(y==x),unique(y,'stable'))

Reasonably straightforward, though the default behavior of Matlab's unique function to sort the values makes the function rather longer.

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

Pyke, 3 bytes

}F/

Try it here!

for i in uniquify(input): print input.count(i)
\$\endgroup\$
0
\$\begingroup\$

Python 2.7 - 103 Bytes (Ungolfed)

i=list(raw_input())
print ''.join([str(e) for e in map(lambda x,y:x!=y and i.count(x)or' ',i,['']+i) ])

edit: Thanks to Dr Green Eggs and Iron Man for helping to reduce 47 Bytes!

\$\endgroup\$
2
  • \$\begingroup\$ You can shorten it by 36 bytes by changing the first three lines to i=input() I don't think stripping whitespace or printing the original string is necessary. \$\endgroup\$
    – DJMcMayhem
    Jun 23, 2016 at 13:45
  • \$\begingroup\$ You could also just do print s on the last line. (Although I haven't tested that) you might need print list(s) or print[s] \$\endgroup\$
    – DJMcMayhem
    Jun 23, 2016 at 13:50