# Counter counter

In typography, a counter is the area of a letter that is entirely or partially enclosed by a letter form or a symbol. A closed counter is a counter that is entirely enclosed by a letter form or symbol. You must write a program takes a string as input and prints the total number of closed counters in the text.

• May be a command line input, or from STDIN, but you must specify which.

• Will consist entirely of the printable ASCII characters, meaning all ASCII values between 32 and 126 inclusive. This does include spaces. More information.

Now, this does vary slightly between fonts. For example, the font you're reading this in considers 'g' to have one closed counter, whereas the google font has 'g' with two closed counters. So that this is not an issue, here are the official number of closed counters per character.

All the symbols with no closed counters:

 !"'()*+,-./12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\]^_cfhijklmnrstuvwxyz{|}~


Note that this includes space.

Here are all the symbols with one closed counter:

#0469@ADOPQRabdegopq


And here are all the symbols with 2 closed counters:

$%&8B  And last but not least, here are some sample inputs and outputs. Programming Puzzles and Code-Golf should print 13 4 8 15 16 23 42 should print 5 All your base are belong to us should print 12 Standard loopholes apply should print 12 Shortest answer in bytes is the winner! should print 8 • Two answers have submitted functions instead of full programs. While that is allowed by default, your wording suggests otherwise. Could you clarify? – Dennis Jun 19 '15 at 22:07 • Would you mind disclosing which going you used to count the counters? – Martin Ender Jun 20 '15 at 13:06 • None of the fonts I'm viewing the question in corresponds to the counts you have given. E.g. in the browser, the zero has a diagonal slash through it, giving two counters. The font in the android app doesn't, but here the g has two closed counters. Did you determine the counters based on any particular font? – Martin Ender Jun 20 '15 at 14:10 • @DJMcMayhem 'g' has 1; though where listed in code, g has 2. Slightly confusing to read, but I don't think it's different by location. – OJFord Jun 21 '15 at 21:45 • Doesn't 0 have 2 closed counters in certain fonts, especially many monospace fonts? – vsz Jun 22 '15 at 6:17 ## 24 Answers # Pyth, 31 bytes sm@tjC"cúÁ-ÈN%³rØ|­"3Cdz  Demonstration. Note that the code may not be displayed properly due to the use of non-ASCII characters. The correct code is at the link. I made a lookup table of the output desired for each input character, rotated it by 32 to make use of Pyth's modular indexing, stuck a 1 at the beginning, and interpreted it as a base 3 number, giving the number 2229617581140564569750295263480330834137283757. I then converted this number to base 256 and converted it to a string, which is the string used in the answer. ## Python 3, 63 print(sum(map(input().count,"#0469@ADOPQRabdegopq$%&8B$%&8B")))  A straightforward approach. Iterates over each character with a closed counter, summing the number of occurrences, doing so twice for characters with two closed counters. It would be the same length to instead write "#0469@ADOPQRabdegopq"+"$%&8B"*2


Python 3 is needed to avoid raw_input.

# CJam, 413937 34 bytes

"$%&8Badopq#0469@Rbeg"_A<eu+qfe=1b  Thanks to @jimmy23013 for golfing off 3 bytes! Try it online. ### How it works "$%&8Badopq#0469@Rbeg"             e# Push that string.
_A<          e# Retrieve the first 10 characters.
eu+       e# Convert to uppercase and append.
e# This pushes "$%&8Badopq#0469@Rbeg$%&8BADOPQ".
q      e# Read from STDIN.
fe=   e# Count the occurrences of each character.
1b e# Base 1 conversion (sum).

• "$%&8Badopq#0469@Rbeg"_A<eu+. – jimmy23013 Jun 20 '15 at 6:11 • @jimmy23013: I had tried a few variations of eu and el, but I never found that. Thanks! – Dennis Jun 20 '15 at 6:17 # sed, 51 With golfing help from @manatwork and @TobySpeight: s/[$%&8B]/oo/g
s/./1/g


Input from STDIN. With this meta-question in mind, the output is in unary:

$echo 'Programming Puzzles and Code-Golf 4 8 15 16 23 42 All your base are belong to us Standard loopholes apply Shortest answer in bytes is the winner!' | sed -f countercounter.sed 1111111111111 11111 111111111111 111111111111 11111111$


# Perl, 41

$_=y/#0469@ADOPQRabdegopq//+y/$%&8B//*2


41 characters +1 for the -p flag.

This uses y/// to count the characters.

echo 'Programming Puzzles and Code-Golf' | perl -pe'$_=y/#0469@ADOPQRabdegopq//+y/$%&8B//*2'


# GNU APL, 39 bytes

+/⌈20÷⍨26-'$%&8B#0469@ADOPQRabdegopq'⍳⍞  Try it online in GNU APL.js. ### How it works  ⍞ Read input. '$%&8B#0469@ADOPQRabdegopq'⍳  Compute the indexes of the input characters
in this string. Indexes are 1-based.
26-                              Subtract each index from 26.
20÷⍨                                 Divide those differences by 20.
⌈                                     Round up to the nearest integer.
+/                                      Add the results.


# JavaScript, 86

I/O via popup. Run the snippet in any drecent browser to test.

for(c of prompt(t=0))c='$%&8B#0469@ADOPQRabdegopq'.indexOf(c),~c?t+=1+(c<5):0;alert(t) # K, 544342 37 bytes +//(30#"$%&8B#0469@ADOPQRabdegopq"=)'


Cut off 5 bytes thanks to @JohnE!

## Older version:

f:+/(#&"#0469@ADOPQRabdegopq$%&8B$%&8B"=)'


## Original:

f:+/{2-(5="$%&8B"?x;20="#0469@ADOPQRabdegopq"?x;0)?0}'  • The #& inside the parens could just as easily be +/, which means you could go further with +//"#0469@ADOPQRabdegopq$%&8B$%&8B"=\:. Finally, it's not necessary to have the f: since the function can be used in tacit form. That would bring you down to 38! – JohnE Jun 20 '15 at 0:19 • Unfortunately the trick a few other solutions have employed to compact the lookup table comes out dead even with the current 38 byte solution: +//(30#"$%&8B#0469@ADOPQRabdegopq")=\:. This may be the best we can do. – JohnE Jun 20 '15 at 2:46
• haha, no sooner did I post that than I saved a character: +//(30#"$%&8B#0469@ADOPQRabdegopq"=)' – JohnE Jun 20 '15 at 2:51 # C, 127 bytes n;f(char*i){char*o="#0469@ADOPQRabdegopq",*t="$%&8B";for(;*i;i++)if(strchr(o,*i))n++;else if(strchr(t,*i))n+=2;printf("%d",n);}


Pretty straightforward. Ungolfed version:

int num = 0;
void f(char* input)
{
char *two="$%&8B"; for(;*input;input++) if(strchr(one, *input)) //If current character is found in first array num ++; else if(strchr(two, *input))//If cuurent character is found in second array num += 2; printf("%d", num); }  Test it here If function arguments are not allowed, then the stdin version takes up to 141 bytes: n;f(){char*o="#0469@ADOPQRabdegopq",*t="$%&8B",i[99],*p;gets(i);for(p=i;*p;p++)if(strchr(o,*p))n++;else if(strchr(t,*p))n+=2;printf("%d",n);}


Note that the above version assumes that the input is atmost 98 characters long.

Test it here

Command-line arguments version (143 bytes):

n;main(c,v)char**v;{char*o="#0469@ADOPQRabdegopq",*t="$%&8B",*p=v[1];for(;*p;p++)if(strchr(o,*p))n++;else if(strchr(t,*p))n+=2;printf("%d",n);}  Test it here • @DJMcMayhem C is really not that bad. Try golfing in Fortran 77. ;) – Alex A. Jun 22 '15 at 13:11 # Python 2, 969075 67+2 = 69 Bytes Can't think of any other way to do this... is what I would have thought until I saw xnor's solution. I'll post what I had anyways. Thanks to FryAmTheEggman for saving 6 bytes Alright, now I'm happy with this. Thanks to xnor for the find trick, saving 4 bytes. Added two bytes since input needs to be enclosed in quotes. print sum('#0469@ADOPQRabdegopq$%&8B'.find(x)/20+1for x in input())

• I like the clever use of indexes! Also, python 3's a bit shorter because it uses input instead of raw_input. – DJMcMayhem Jun 19 '15 at 19:25
• – Kade Jun 22 '15 at 14:30
• Oh, I see. Sorry, I combined it with @DJMcMayhem's Python 3 comment. – manatwork Jun 22 '15 at 14:31

# Java, 162

class C{public static void main(String[]a){System.out.print(-a[0].length()+a[0].replaceAll("[#0469@ADOPQRabdegopq]","..").replaceAll("[$%&8B]","...").length());}}  Well if it has to be a full program... It's just a one-liner that matches characters and replaces them with a longer string. Then, returns the difference in length from the original. Unfortunately, java doesn't really have anything to just count the number of matches. Here it is with line breaks: class C{ public static void main(String[]a){ System.out.print( -a[0].length() + a[0].replaceAll("[#0469@ADOPQRabdegopq]","..") .replaceAll("[$%&8B]","...")
.length()
);
}
}


# Pyth - 35 bytes

Uses the obvious method of in first + *2 in second. Thanks @FryTheEggman.

s/Lz+"#0469@ADOPQRabdegopq"*2"$%&8B  # Javascript, 114 95 bytes alert(prompt().replace(/[#046@ADOPQRabdegopq]/g,9).replace(/[$%&8B]/g,99).match‌​(/9/g).length)


Thanks to Ismael Miguel for helping me golf this.

• 93 bytes: alert(prompt().replace(/[#046@ADOPQRabdegopq]/g,9).replace(/[$%&8B]/g,99).match(/9/g).length) – Ismael Miguel Jun 19 '15 at 23:59 • Sorry for counting badly. Yes, its 95. – Ismael Miguel Jun 20 '15 at 0:34 # Ruby, 59 bytes a=gets;p a.count('#0469@ADOPQRabdegopq')+2*a.count('$%&8B')


Input from command line or stdin. Shortest so far using a non-esoteric language.

Update: chilemagic beat me

# Retina, 44 bytes

1

1
[$%&8B] 11 [^1] <empty line>  Gives output in unary. Each line should go to its own file or you can use the -s flag. E.g.: > echo "pp&cg"|retina -s counter 11111  The pairs of lines (pattern - substitute pairs) do the following substitution steps: • Remove 1's • Substitute 1-counter letters with 1 • Substitute 2-counter letters with 11 • Remove everything but the 1's # J, 43 As a function:  f=:[:+/[:,30$'$%&8B#0469@ADOPQRabdegopq'=/] f 'text goes here' 6  # 46 bytes (command line) As a standalone command-line program: echo+/,30$'$%&8B#0469@ADOPQRabdegopq'=/>{:ARGV  Save the above line as counter2.ijs and call from the command line: $ jconsole counter2.ijs 'Programming Puzzles and Code Golf'
13

• Copy-pasting the input into the code isn't allowed but a function which can take the input as an argument is ok. E.g. f=:your_function_code. – randomra Jun 20 '15 at 7:57

# Julia, 77 74 bytes

t=readline();length(join(t∩"#0469@ADOPQRabdegopq")*join(t∩"$%&8B")^2)  This reads text from STDIN and prints the result to STDOUT. Ungolfed + explanation: # Read text from STDIN t = readline() # Print (implied) to STDOUT the length of the intersection of t with the # 1-closed counter list joined with the duplicated intersection of t with # the 2-closed counter list length(join(t ∩ "#0469@ADOPQRabdegopq") * join(t ∩ "$%&8B")^2)


Example:

julia> t=readline();length(join(t∩"#0469@ADOPQRabdegopq")*join(t∩"\$%&8B")^2) Programming Puzzles and Code Golf 13  # rs, 56 bytes _/ [#0469@ADOPQRabdegopq]/_ [$%&8B]/__
[^_]/
(_+)/(^^\1)


Live demo.

• Just an fyi: I created a stub esolangs page for rs. You may wish to add to it: esolangs.org/wiki/Rs – mbomb007 Sep 21 '15 at 20:01
• @mbomb007 WOW!! That just made my day. :D – kirbyfan64sos Sep 21 '15 at 20:10
• Well, "rs" doesn't come up in Google or anything since it's only two letters. This way, people can find it. :) – mbomb007 Sep 21 '15 at 20:12

GNU APL, 37 characters

+/,⍞∘.=30⍴'$%&8B#0469@ADOPQRabdegopq'  construct a character vector which contains 2-counter characters twice (30⍴) compare each input char with every character in the vector (∘.=) sum up ravelled matches (+/,) # Javascript 159, 130 Bytes function c(b){return b.split("").map(function(a){return-1!="$%&8B".indexOf(a)?2:-1!="#0469@ADOPQRabdegopq".indexOf(a)?1:0}).reduce(function(a,b){return a+b})};


unminified:

function c(b) {
return b.split("").map(function(a) {
return -1 != "$%&8B".indexOf(a) ? 2 : -1 != "#0469@ADOPQRabdegopq".indexOf(a) ? 1 : 0 }).reduce(function(a, b) { return a + b }) };  With the help of @edc65: function c(b){return b.split('').reduce(function(t,a){return t+(~"$%&8B".indexOf(a)?2:~"#0469@ADOPQRabdegopq".indexOf(a)?1:0)},0)}

• As ~ -1 == 0, you can write ~x? instead of -1 != x?. See me answer for an example of use. – edc65 Jun 20 '15 at 0:09
• function c(b){return b.split('').reduce(function(t,a){return t+(~"$%&8B".indexOf(a)?2:~"#0469@ADOPQRabdegopq".indexOf(a)?1:0)},0)} No need to have map then reduce – edc65 Jun 20 '15 at 0:18 # Haskell, 117 a="#0469@ADOPQRabdegopq" b="$%&8B"
c n[]=n
c n(x:s)
|e a=f 1
|e b=f 2
|True=f 0
where
e y=xelemy
f y=c(n+y)s


c is a function c :: Int -> String -> Int which takes a counter and a string and goes through the string one letter at a time checking if the current letter is a member of the 1 point array or the 2 point array and calls itself for the rest of the string after incrementing the counter the appropriate amount.

Call with counter = 0 in ghci:

ghci> c 0 "All your base are belong to us"
12


# C#, 157

void Main(string s){int v=0;v=s.ToCharArray().Count(c=>{return "#0469@ADOPQRabdegopq".Contains(c)||"$%&8B".Contains(c)?++v is int:false;});Console.Write(v);}  Ungolfed: void Main(string s) { int v = 0; v = s.ToCharArray() .Count(c => { return "#0469@ADOPQRabdegopq".Contains(c) || "$%&8B".Contains(c) ? ++v is int:false;
});

Console.Write(v);
}


Converting the string into a char array, then seeing if each char is in either counter. If it is in the second one, I just have it incrementing the counter again.

# Erlang, 103 bytes

This is a complete program that runs using escript. The first line of the file must be blank (adding 1 byte).

main([L])->io:write(c(L,"#0469@ADOPQRabdegopq")+2*c(L,"$%&8B")). c(L,S)->length([X||X<-L,S--[X]/=S]).  Sample run: $ escript closed.erl 'Shortest answer in bytes is the winner!'
8$ • Welcome to PPCG, c(L,"#0469@ADOPQRabdegopq")+2*c(L,"$%&8B") is longer than c(L,"#0469@ADOPQRabdegopq$%&8B$%&8B") by 5 bytes :). – Katenkyo Jun 22 '15 at 8:24
• @Katyenko, thanks for the suggestion. Regrettably it doesn't work correctly for certain inputs. "$%&8B" counts for 5, but should be 10. The c/2 function works by filtering out the chars of the string that do not belong to a set of chars, such as "$%&8B". It checks for set inclusion by deleting the char to be tested from the set, then comparing the result with the original set. If they are not equal, then the char was in the set, and it is included. Multiple copies of chars in the set don't have any effect. – Edwin Fine Jun 22 '15 at 15:40
• Ho, I see, I don't know erlang, was thinking you were using a string to count the counter :3. Anyway, nevermind, and well done :) – Katenkyo Jun 22 '15 at 17:53

char *two = strchr(one, '$'); while (*input) { num += 2 - !strchr(one, *input) - !strchr(two, *input)); ++input; } }  Output is in num, which must be cleared before each call. # Test program and results #include <stdio.h> int main() { const char* a[] = { "Programming Puzzles and Code-Golf", "4 8 15 16 23 42", "All your base are belong to us", "Standard loopholes apply", "Shortest answer in bytes is the winner!", NULL }; for (const char** p = a; *p; ++p) { n=0;f(*p); printf("%3d: %s\n", n, *p); } return 0; }   13: Programming Puzzles and Code-Golf 5: 4 8 15 16 23 42 12: All your base are belong to us 12: Standard loopholes apply 8: Shortest answer in bytes is the winner! 37: n;f(char*i){for(char*o="#0469@ADOPQRabdegopq$%&8B",*t=o+20;*i;)n+=2-!strchr(o,*i)-!strchr(t,*i++);}
`

The code itself contains 37 counters by its own metric.