5
\$\begingroup\$

Challenge (Easy)

Write a function which takes an argument and returns the number of non-alphanumeric characters found.

Challenge (Hard)

Write a function which takes an argument and returns the number of bytes used to store the number of non-alphanumeric characters found. (ie: include calculation for multi-byte characters.)

Rules / Notes

  • Alphanumeric in this case is defined as:

    abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789

  • A null character should count as 0 characters, but as 1 byte when stored.

    NUL

  • Showing multi-byte support (if too complicated) only has to demonstrate one character set or language reference / codepage (if this actually matters. I don't know, so just putting it out there.)

Winner

Since this is code golf, the shortest code that correctly matches the challege wins.

\$\endgroup\$
  • \$\begingroup\$ Require to support multibyte char? Require UTF8? \$\endgroup\$ – l4m2 May 4 '18 at 2:06
  • \$\begingroup\$ For C non-unicode they are just same challenge? \$\endgroup\$ – l4m2 May 4 '18 at 2:07
  • \$\begingroup\$ @l4m2 "Showing multi-byte support (if too complicated) only has to demonstrate one character set or language reference / codepage" \$\endgroup\$ – mbomb007 May 4 '18 at 18:10

20 Answers 20

5
\$\begingroup\$

Perl, 14 characters

y/A-Za-z0-9//c
\$\endgroup\$
2
\$\begingroup\$

Stax, 3 bytes (Easy)

├Dr

Run and debug it

Explanation

VL-%        # Full program, unpacked
VL          # Push "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  -         # Remove all elements in b from a.
    %       # Length and implicitly print result
\$\endgroup\$
  • 1
    \$\begingroup\$ Dang, ninja'd me by a minute! My solution was identical. I'd describe VL as "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" rather than as many separate elements. \$\endgroup\$ – Khuldraeseth na'Barya May 4 '18 at 18:06
  • \$\begingroup\$ @Scrooble Yeah that is what I had it as originally, but I thought it looked too long, so I formatted it like that to be more concise. I see how they could be viewed at differently. I'll change it to be like you recommended though. \$\endgroup\$ – Multi May 4 '18 at 18:08
2
\$\begingroup\$

Jelly, 7 6 4 bytes

ḟØBL

Try it online!

ḟØBL
ḟ         reverse ḟilter: remove all of the input characters that are also in...
 ØB       alphanumeric characters...
   L      and get the Length of the resulting string!

6-byte solution:

ḟØWṖ¤L

Try it online!

ḟØWṖ¤L
ḟ         reverse ḟilter: remove all of the input characters that are also in...
 ØWṖ¤     the "word" character class with the underscore popped from it, taken as a nilad...
     L    ...and take the length of the resulting string
\$\endgroup\$
  • 2
    \$\begingroup\$ You can use (nilad) (links) ¤ as a new nilad, like so: ḟØWṖ¤L \$\endgroup\$ – Lynn May 4 '18 at 14:04
  • 1
    \$\begingroup\$ Alternatively, ØWṖ⁸ḟL works too, of course. (That ⁸ḟ is the fourth monad chain pattern.) \$\endgroup\$ – Lynn May 4 '18 at 15:00
  • \$\begingroup\$ @Lynn Thank you! I wasn't able to understand ¤ from the docs before but now I understand it! \$\endgroup\$ – Harry May 4 '18 at 15:35
  • 1
    \$\begingroup\$ You can use ØB (push '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz') instead of ØWṖ¤ to save 2 bytes. \$\endgroup\$ – Kevin Cruijssen May 4 '18 at 18:42
  • \$\begingroup\$ @KevinCruijssen, thanks! Don't know why I didn't catch that nilad when I was making this. \$\endgroup\$ – Harry May 4 '18 at 19:51
1
\$\begingroup\$

D

easy (29 chars)

count!"!isAlphaNum(b)&&b"(s);

hard (35 chars)

s needs to be a char[]

s.length-count!"!isAlphaNum(b)"(s);
\$\endgroup\$
1
\$\begingroup\$

Groovy

Easy: 26 25 30 characters

c={(it=~/[[^\00\w]_]/).size()}

assert c("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789")== 2
assert c("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")==0
assert c("a-b-7*NNuah ~#77%")==7
assert c('_|') == 2
assert c('\0') == 0

Hard: 47 characters

s={it.replaceAll(/[\w&&[^_]]/,'').bytes.size()}

assert s("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789")== 2
assert s("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")==0
assert s("a-b-7*NNuah ~#77%")==7
assert s('_') == 1
\$\endgroup\$
  • \$\begingroup\$ Is that | supposed to be in the first regex? \$\endgroup\$ – Peter Taylor Nov 17 '11 at 8:32
  • \$\begingroup\$ I thought it was... but looks unnecessary :) thanks \$\endgroup\$ – Armand Nov 17 '11 at 9:05
  • \$\begingroup\$ Looked to me like a bug, because I think it would have messed up the counts in strings with a |. \$\endgroup\$ – Peter Taylor Nov 17 '11 at 9:50
  • \$\begingroup\$ Waiting for some other entries, but nice go at it. Have you tried running some Chinese or Japanese characters into the hard function to see if it counts them properly? \$\endgroup\$ – cbroughton Nov 17 '11 at 21:18
  • \$\begingroup\$ I don't see you handling '\0' in easy (they should also be excluded) \$\endgroup\$ – ratchet freak Nov 18 '11 at 0:29
1
\$\begingroup\$

Husk, 4 bytes (easy)

#(¬□

Try it online!

Explanation

Pretty simple usage of isanum ():

#(¬□)  -- example: "Input!"
#(  )  -- count number of
 ( □)  -- | is alphanumeric: [73,110,112,117,116,0]
 (¬ )  -- | not: [0,0,0,0,0,1]
       -- : 1
\$\endgroup\$
1
\$\begingroup\$

R, 68 42 bytes

-26 bytes thanks to Giuseppe.

function(x)nchar(gsub('[[:alnum:]]',"",x))

Try it online!

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

05AB1E, 4 bytes (easy)

žKмg

Try it online.

Explanation:

žK      # Push "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  м     # Remove all occurrences of this second string from the input string
   g    # Push and implicitly output the length of the result

05AB1E, 19 bytes (hard)

žKмÇεDžy‹i1ë.²<5÷>н]O

Thanks to @Mr.Xcoder for helping me put two sub-solutions together with D, and explaining how ] closes both the if-statement and foreach-loop. (I accidentally placed the D before the ε and used one } instead of two..)

Try it online.

Explanation:

žK                     # "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  м                    # Remove all occurrences of this second string from the input string
   Ç                   # Convert each character to its unicode value
    εD                 # Foreach over this list
         i             #  If the current item
        ‹              #  is maller than
      žy               #  128
          1            #   Use 1
           ë           #  Else
            .²         #   Use log_2
              <        #   minus 1
               5÷      #   integer-divided by 5
                 >     #   plus 1
                  н    #  Take the head of the sublists
                   ]   # Close both the if-else and for-each (shorter version of `}}`)
                    O  # Sum everything together

05AB1E doesn't have any builtins for knowing the amount of bytes a character costs, so I'm converting them to unicode values with Ç and use the following pseudo-code to determine their bytes:

if(unicodeValue < 128)
  return 1
else
  return log_2(unicodeValue-1)//5+1    # (where // is integer-division)

Pseudo-code inspired by @TheBikingViking's Python 3 answer for the Bytes/Characters challenge.

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

MS-SQL, 85 bytes (easy)

SELECT SUM(1)FROM spt_values,t
WHERE type='P'AND SUBSTRING(v,number,1)LIKE'[^a-z0-9]'

Handles strings up to 2047 characters. Per our IO standards, input is taken via a pre-existing table t with varchar field v.

This must be run in the master database (which exists on every SQL server). This database has a system table dbo.spt_values, which, if we filter by type='P', contains counting numbers from 0 to 2047. Join that to our input table to split each character into its own row, then count up those that match the LIKE filter (which supports character ranges).

MS-SQL, 85 bytes (hard)

SELECT SUM(2)FROM spt_values,t
WHERE type='P'AND SUBSTRING(v,number,1)LIKE'[^a-z0-9]'

You also need to change the input table to an nvarchar field v instead of varchar.

So yeah, this is kind of cheaty, because the nvarchar data type uses 2 bytes for every character, even for normal ASCII characters. That means I don't have to distinguish between characters that could be stuffed into a single byte and those that can't. But it does strictly satisfy the challenge, since it reflects the number of bytes that SQL is actually using to store nvarchar strings.

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

Javascript 1.8

easy (48 chars)

function f(s)(s.match(/[^a-z0-9]/gi)||[]).length

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

PowerShell, easy, 44

filter e{($args-replace"[a-z0-9]").Length}

If we stretch the definition of »arguments«, we can shorten it a bit more (41):

filter e{($_-replace"[`0a-z0-9]").Length}

but it then requires input to be sent via the pipeline.

PowerShell, hard, 71

function x{[text.encoding]::utf8.GetByteCount($args-replace'[a-z0-9]')}

Again, if we allow the pipeline we get it to 68:

function x{[text.encoding]::utf8.GetByteCount($_-replace'[a-z0-9]')}
\$\endgroup\$
0
\$\begingroup\$

Scala

Easy (43 chars)

def c(s:String)=s.count(!_.isLetterOrDigit)

Hard (58 chars)

def c(s:String)=s.filter(!_.isLetterOrDigit).getBytes.size
\$\endgroup\$
0
\$\begingroup\$

Python

easy (39 chars)

f=lambda s:sum(1-i.isalpha()for i in s)
\$\endgroup\$
  • \$\begingroup\$ You can remove the f= to save 2 bytes \$\endgroup\$ – caird coinheringaahing Apr 2 '17 at 23:18
0
\$\begingroup\$

Brainfuck

Easy (1397 chars)

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

All hand coded. It takes input until it gets a 0xA character signifying end of input (not counted). Only handles up to 255 nonalphanumeric input characters.

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

Perl (easy) 27 characters

sub _{$_=shift;(s/\W|_//g)}

usage:

say _('@abc_123ABC -("~ abc')   
---> 8
\$\endgroup\$
0
\$\begingroup\$

Ruby, easy, 32

f=->s{s.scan(/[^a-z0-9]/i).size}
\$\endgroup\$
0
\$\begingroup\$

Gol><>, Easy, 26 bytes

iEh$"0:A[a{"{16F@2k)S^|}~+

Try it online!

How it works

iEh$"0:A[a{"{16F@2k)S^|}~+

iEh                         Take input as char; if EOF, print the top as int and halt
   $                        Move the input under the char counter
    "0:A[a{"                Push six boundary chars
            {1              Pull the input to the top, and push 1 (XOR counter)
                            (Stack: [char counter, ...boundary, input, XOR counter])
              6F      |     Repeat 6 times...
                @             Pull a boundary char to the top
                 2k)          Copy the input char and compare (boundary > input)
                    S^        XOR with the XOR counter
                            (Stack: [char counter, input, XOR counter])
                       }~+  Move XOR counter to bottom, discard input, and
                              add to the char counter
                            Repeat indefinitely
\$\endgroup\$
0
\$\begingroup\$

Pyth

Easy, 17 bytes

l:z"[a-zA-Z0-9]"k

Try it online!

Hard, 30 bytes

/lsm.[\08.BCd:z"[a-zA-Z0-9]"k8

Try it online!

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

Java 10, 42 bytes (easy)

s->s.replaceAll("[A-Za-z0-9]","").length()

Try it online.

Explanation:

s->                               // Method with String parameter and integer return-type
  s.replaceAll("[A-Za-z0-9]","")  //  Remove all digits and letters
   .length()                      //  And return the length

Java 10, 102 bytes (hard)

s->{int r=0;for(var c:s.replaceAll("[A-Za-z0-9]","").split(""))r+=c.getBytes("utf8").length;return r;}

Try it online.

Explanation:

s->{                              // Method with String parameter and integer return-type
  int r=0;                        //  Result-integer, starting at 0
  for(var c:s.replaceAll("[A-Za-z0-9]","")
                                  //  Remove all digits and letters
             .split(""))          //  And loop over the remaining characters
    r+=                           //   Add to the result-sum:
      c.getBytes("utf8").length;  //    The UTF-8 bytes of the current character
  return r;}                      //  Return the result-sum
\$\endgroup\$
0
\$\begingroup\$

Haskell, 58 52 bytes (easy)

-6 bytes, thanks to Laikoni (inverting the test, using elem instead)!

f s=sum[1|c<-s,elem c":;<=>?@[\\]^_`"||c>'z'||c<'0']

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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