Is it an Odd Word?

Challenge

Given a single word as input, determine if the word is odd or even.

Odd and Even words

Assume the general rules:

odd + odd = even
even + odd = odd
odd + even = odd
even + even = even


In the alphabet, the odd letters are:

aeiou


And the even letters are:

bcdfghjklmnpqrstvwxyz


The same applies to capital letters (AEIOU are odd and BCDFGHJKLMNPQRSTVWXYZ are even).

You then 'add' each of the letters in the word together. For example, the word cats is equivalent to:

even + odd + even + even


Which simplifies to:

odd + even


Which simplifies further to:

odd


So the word cats is odd.

Examples

Input:  trees
Output: even


Input:  brush
Output: odd


Input:  CAts
Output: odd


Input:  Savoie
Output: even


Input:  rhythm
Output: even


Rules

All input will be a single word which will only contain alphabetical characters.

If the word is odd, output a truthy value. If the word is even, output a falsey value.

Winning

The shortest code in bytes wins.

• Could you add an example of a word without any odd letters.
– Hedi
Sep 20, 2016 at 18:50
• @Hedi I've added one, rhythm Sep 20, 2016 at 19:37
• Excuse you. Odd Word™ has been trademarked already by JLee. This is an unauthorized use of the term. :P Sep 20, 2016 at 20:58
• This is begging for a pure regex submission Sep 20, 2016 at 21:19
• Is the input guaranteed to only contain alphabetical characters? Sep 20, 2016 at 23:07

EXCEL, 79 bytes:

=MOD(SUMPRODUCT(LEN(A1)-LEN(SUBSTITUTE(LOWER(A1),{"a","e","i","o","u"},""))),2)


input:
This function can be placed anywhere EXCEPT A1
Put your word in question into A1.

Output: 0 if even, 1 if odd.

JavaScript (ES6), 344133 32 bytes

Saved 1 bytes thanks to Arnauld:

s=>~s.split(/[aeiou]/i).length&1

• Odd word : returns 1
• Even words : returns 0

Previous solutions:

33 bytes thanks to Arnauld:

s=>s.split(/[aeiou]/i).length&1^1

• Odd word : returns 1
• Even words : returns 0

Another way without bitwise operators:

s=>++s.split(/[aeiou]/i).length%2


41 bytes:

(s,a=s.match(/[aeiou]/ig))=>a&&a.length%2

• Odd word : returns 1
• Even words with odd letters : returns 0
• Even words with no odd letters : returns null

42 bytes to return 0 instead of null:

(s,a=s.match(/[aeiou]/ig))=>a?a.length%2:0


34 bytes, breaks on words with no odd letters:

f=s=>s.match(/[aeiou]/ig).length%2


Saved 2 bytes thanks to Shaun H

s=>s.match(/[aeiou]/ig).length%2

• This method breaks when word has no vowels. That said: f= isn't needed, and calling exec on the regex object is shorter. s=>/[aeiou]/ig.exec(s).length%2 Sep 20, 2016 at 18:27
• I don't have the same result with exec with the g flag.
– Hedi
Sep 20, 2016 at 18:53
• dammit brain yeah ignore that, f= still isn't needed though Sep 20, 2016 at 18:58
• Could you do s=>s.split(/[aeiou]/i).length&1^1? Sep 20, 2016 at 19:44
• s=>~s.split(/[aeiou]/i).length&1 is actually one byte shorter. Sep 20, 2016 at 20:51

C, 42 bytes

f(char*s){return*s&&2130466>>*s&1^f(s+1);}


This works with GCC 4.x on a x86-64 CPU. Results may vary with different setups.

Test it on repl.it.

At the cost of 5 more bytes, undefined behavior can be avoided, so the code should work as long as ints are at least 32 bits wide.

f(char*s){return*s&&2130466>>(*s&31)&1^f(s+1);}


How it works

Modulo 32, the character codes of all odd letters are 1, 5, 9, 15, and 21. 2130466 is the 32-bit integer that has set bits at these positions and unset bits at all others.

When f is called on a string, it first checks if the first character of the string is a null byte (string terminator). If it is, *s yields 0 and f returns 0. Otherwise, *s yield the character code of a letter and the right argument of the logical AND (&&) is executed.

For >>, GCC generates a shift instruction. On a x86-64 CPU, the corresponding instruction for a 32-bit integer ignores all but the lower 5 bits of the right argument, which avoids reducing *s modulo 32. The right shift and the following bitwise AND with 1 extracts the bit of 2130466 that corresponds to the letter, which will be 1 if and only if the letter is odd.

Afterwards, we increment the pointer s (effectively discarding the first letter), call f recursively on the beheaded string, and take the bitwise XOR of the result from above and the result of the recursive call.

• Great bit wise work! Sep 21, 2016 at 17:42
• erees Return 0 in Ideone, is it right?
– user58988
Sep 21, 2016 at 18:40
• @RosLuP No, that's not correct. It works on my computer and on repl.it though (possibly because the version of GCC is quite different). Sep 21, 2016 at 18:49
• Yeah, it's definitely the compiler. With clang 3.7, it works on Ideone as well. Sep 21, 2016 at 18:57

Python, 41 bytes

lambda s:sum(map(s.count,"aeiouAEIOU"))%2


Brain-Flak206196192 178 + 3 = 181 bytes

Try it Online!

([]<{({}[((((((()()())){}){}){}){}){}()]){({}[({}())]){({}[({})]){({}[({}()())]){({}[({})]){({}<>)(<>)}}}}}{}{}}><>[[]]<>()()){(({}[<>(())<>()()])){{}({}())((<>)<>)}{}}{}<>({}<>)


This requires the -c flag to run in ASCII mode adding an extra 3 bytes to the length of the program.

Ungolfed

([]<
{({}[(((((()()()){}){}){}){}){}()])
{
({}[()()()()])
{
({}[()()()()])
{
({}[(()()()){}])
{
({}[(()()()){}])
{
({}<>)
(<>)
}
}
}
}
}
{}
}
><>[[]]<>)
(<(()()<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>({}<{}><>)


Explanation

First store the stack height for future purposes

([]<...>


Then while the stack is not empty (assumes that none of the characters is zero)

{...}


Subtract ninety seven (and store 3 for later optimizations)

({}[((((((()()())){}){}){}){}){}()])


If it is not zero (i.e. not a)

{...}


Subtract 4 (and store 4 for later optimizations)

({}[({}())])


If it is not zero (i.e. not e)

{...}


Subtract 4 (and store 4 for later optimizations)

({}[({})])


If it is not zero (i.e. not i)

{...}


Subtract 6 (and store 6 for later optimizations)

({}[({}()())])


If it is not zero (i.e. not o)

{...}


Subtract 6 (store 6 because the program expects one later)

({}[({})])


If it is not zero (i.e. not u)

{...}


Move the remainder to the other stack and put a zero on the active stack to escape all of the ifs

({}<>)(<>)


Once all of the ifs have been escaped remove the zero and the six

{}{}


Once all the characters have been processed subtract the height of the offset from the originally stored height.

...<>[[]]<>)


Mod by two

{(({}[<>(())<>()()])){{}({}())((<>)<>)}{}}{}<>({}<>)

• I think -c is only +1 byte since ever Perl answer also only adds 1 byte / flag. Sep 21, 2016 at 6:10
• @ThreeFx That's because perl -pe'code' is only one byte longer than perl -e'code'. Sep 21, 2016 at 7:07

05AB1E, 6 bytes

lžMÃgÉ


Explanation

l       # convert to lower case
žMÃg   # count odd letters
É  # true if odd else false


Try it online!

sed 44 (42 + 1 for -n) 43

-1 thanks to Neil

s/[aeiou][^aeiou]*[aeiou]//gi
/[aeiou]/Ico


Prints o for odd and nothing for even

• s/[aeiou][^aeiou]*[aeiou]//gi might save you a byte, if I've counted correctly.
– Neil
Sep 20, 2016 at 21:23
• @Neil Yep! I wish sed could do non-greedy search. Sep 20, 2016 at 21:44

Brain-Flak, 524, 446, 422 bytes

{(<((((()()()()){}){}){}<>)>)<>{({}[()])<>(({}[({})]())){{}(<({}({}))>)}{}<>}{}<>([(((({}<{}<>>))))]()){(<{}>)<>({}[()])<>}<>({}())<>{}([{}]()()()()()){(<{}>)<>({}[()])<>}<>({}())<>{}(((()()())){}{}[{}]){(<{}>)<>({}[()])<>}<>({}())<>{}(((()()()()())){}{}[{}]){(<{}>)<>({}[()])<>}<>({}())<>{}((((()()()){}())){}{}[{}]){(<{}>)<>({}[()])<>}<>({}())<>{}}(<(()())>)<>{({}[()])<>(({}[({})]())){{}(<({}({}))>)}{}<>}{}<>({}<{}<>>)


Try it online!

{((((()()()()){}){}){})(<({}<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>({}<{}><>)((((({})))))
(())
({}[{}]){(<{}>)<>({}[()])<>}<>({}())<>{}
(()()()()())
({}[{}]){(<{}>)<>({}[()])<>}<>({}())<>{}
(()()()()()()()()())
({}[{}]){(<{}>)<>({}[()])<>}<>({}())<>{}
(()()()()()()()()()()()()()()())
({}[{}]){(<{}>)<>({}[()])<>}<>({}())<>{}
(()()()()()()()()()()()()()()()()()()()()())
({}[{}])
{(<{}>)<>({}[()])<>}<>({}())<>{}}<>(()())(<({}<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>({}<{}><>){{}([()])
(<><>)}({}{}())

• The Ungolfed version doesn't seem to work (can't fit TIO link in comment ;_;) Sep 21, 2016 at 0:49
• "more readable" 'nough said Sep 21, 2016 at 0:52

Jelly, 13 12 11 bytes

-1 byte thanks to @Luis Mendo (use Ḃ to replace %2)
-1 byte thanks to @Dennis (use a string compression)

Œlf“¡ẎṢɱ»LḂ


All test cases are at TryItOnline

How?

Œlf“¡ẎṢɱ»LḂ - Main link takes an argument - s
Œl          - lowercase(s)
“¡ẎṢɱ»   - string of lowercase vowels (compression using the words a and eoui)
f         - filter - keep only the vowels
L  - length - the number of vowels
Ḃ - Bit (modulo 2)


Non-competing, 5 bytes (since I just added the function Øc)

fØcLḂ


Test cases also at TryItOnline

Same as above, but Øc yields the Latin alphabet's vowels, 'AEIOUaeiou'

• I think you can replace %2 by Ḃ  Sep 20, 2016 at 21:11
• euoi is a cry of impassioned rapture in ancient Bacchic revels, so you can use the dictionary and get the vowels as “¡ẎṢɱ». Sep 20, 2016 at 21:53
• @Dennis - LOL of course! Sep 20, 2016 at 21:59
• @Dennis How exactly does that work? Is it just base-compression to get the index of a word in a giant dictionary? Where does the 'a' come from? Sep 21, 2016 at 0:32
• @DJMcMayhem it's a base 250 compression using a dictionary (which I believe was just taken from Dennis's computer) with separation between short (less than 6 char) and long words. Some code to automate the process of making compressed strings was written by Lynn. The unused 6 bytes are Jelly's string identifying characters “”«»‘’ (there is also ⁾ which is for a two-char string, but that is used within compressed strings). Sep 21, 2016 at 1:04

Python, 42 bytes

lambda s:sum(c in"aeiouAEIOU"for c in s)%2


Not a whole lot to explain here. An unnamed function that returns 0 or 1.

odd.length.filter(elem"aeiouAEIOU")


Thanks to Angs for one byte!

• Truthy for odd, so you have to use odd instead of even. Saves one byte!
– Angs
Oct 12, 2016 at 8:55
• @Angs clever :) Oct 13, 2016 at 7:16

Python 3, 53 Bytes

This can probably be golfed further:

lambda n:[x in 'aeiou' for x in n.lower()].count(1)&1

• Remove spaces between in and 'aeiou' and for, and use sum to save 8 bytes: lambda n:sum(x in'aeiou'for x in n.lower())&1 (although as you can see from DJMcMayhem's post using all ten vowels is also shorter) Sep 20, 2016 at 20:41
• Thanks for the tips! I noticed the extra spaces a little bit after posting, but in all honesty, @DJMcMayhem and I had identical approaches with his being the best version I can imagine for a Python solution. I didn't know about the sum() command before this golf so once again I learned something! Have a nice day :) Sep 21, 2016 at 2:48

C 52 bytes

h(o){o=strpbrk(o,"aeiouAEIOU");return o?1^h(o+1):0;}


the main and the result:

main()
{int   k;
char *a[]={"trees","brush","CAts","Savoie","rhythm", 0};

for(k=0;a[k];++k)
printf("[%s]=%s\n", a[k], h(a[k])?"odd":"even");
}

/*
91
[trees]=even
[brush]=odd
[CAts]=odd
[Savoie]=even
[rhythm]=even

*/

• i try to use int as pointers but it not compile where the use of inirection *... the solution printed first here was wrong...
– user58988
Sep 21, 2016 at 15:28
• h(o){return~-o?1^h(1+strpbrk(o,"aeiouAEIOU")):1;} saves 3 bytes. Sep 21, 2016 at 16:52
• s;h(o){s=~-o?1^h(1+strpbrk(o,"aeiouAEIOU")):1;} the result is in the global variable s...
– user58988
Sep 21, 2016 at 18:56
• Unfortunately, that's not allowed. Functions have to be reusable, and this will break if you use it more than once. Also, saving the output in a variable is not allowed, unless you take the location as user input. Sep 21, 2016 at 19:11
• I think in this case reuse is possible becausr the start value of s now is not important...ok ok now i think something can go wrong... Thanks
– user58988
Sep 21, 2016 at 19:19

Pyth, 14 bytes

%l@"aeiou"rQ02


Try it Online!

Explanation:

  @"aeiou"       Grab only the vowels
rQ0      From lowercased input
l                 Get the length of this
%            2     And mod 2 to check for oddness


Ruby, 30 bytes

->w{w.scan(/[aeiou]/i).size%2}


Vim, 32, 31, 29 keystrokes

:s/[^aeiou]//gi
C<C-r>=len(@")%2<cr>


Since the V interpreter is backwards compatible, you can try it online! right here.

One Three bytes saved thanks to m-chrzan!

• Can you do s/.../gi instead of s/\c.../g? Sep 20, 2016 at 18:46
• @m-chrzan Woah, awesome tip. Thanks! Sep 20, 2016 at 18:48
• Also, '<C-r>"' -> @". Sep 20, 2016 at 18:57
• I found out about @" 15 minutes ago. The best vim tip I have is to use :help foo and / the documentation :P. Sep 20, 2016 at 19:10
• Well, since we're talking about golf, :h foo is shorter. :P Sep 20, 2016 at 19:11

Java, 73

boolean f(String s){return s.replaceAll("(?i)[^aeiou]","").length()%2>0;}


saw a couple other java answers, otherwise wouldn't have shared. Thanks to Phaeze for saving a byte.

• I think you can save a byte with %2>0
– user19547
Sep 20, 2016 at 22:41

dimwit, 14 bytes (non-competing)

ar[aeiou]}et}T


I thought this would be a fun, simple challenge to start with for a new language.

Explanation

• a - push a new array to the matrix
• r[aeiou]} - count occurrences of all values matching the regex "[aeiou]" in the first array (since the first array contains the input), ignoring case, and push that value to the end of the last array.
• e - if the last number in the last array is even (which we set to the number of occurrences), perform the next operations up until a closing bracket ("}")
• t - stop execution, clear the matrix, and set the first value to be false
• } - end of e code block
• T - stop execution, clear the matrix, and set the first value to be true

Try it online!

Use the Input field to enter the word.

K (ngn/k), 13 bytes

=/^"aeiou"?_:


Try it online!

Returns 1 for "even" inputs and 0 for "odd" ones.

• _: lowercase the (implicit) input
• ^"aeiou"? generate a bitmask indicating which characters in the (lowercased) input are not vowels
• =/ do an equals-reduce; if there are an even number of 0s (i.e. vowels), this returns 1. if there are an odd number, it returns 0
• By the default site I/O rules, 1 for even and 0 for odd should be allowed. Jun 22 at 22:58
• Great, thanks! Updated the answer to trim those notes out. Jun 22 at 23:00

Retina, 19 bytes

Mi[aeiou]
[13579]$ Try it online! (The first line enables a linefeed-separated test suite.) The first line counts the vowels in the input. The second line checks that the result is odd. Java 7, 88 boolean f(char[]s){int x=0;for(char c:s)if("aeiouAEIOU".indexOf(c)>=0)++x;return x%2>0;}  Ungolfed:  boolean f(char[] s) { int x = 0; for (char c : s) { if ("aeiouAEIOU".indexOf(c) >= 0) { ++x; } } return x % 2 > 0; }  PowerShell v2+, 45 42 bytes ($args[0]-replace'[^aeiouAEIOU]').Length%2


Takes input $args[0], sends it through -replace to remove all non-vowel characters, takes the resulting .length, and %2 to check whether it's odd/even. Examples PS C:\Tools\Scripts\golfing> 'trees','brush','CAts','Savoie','rhythm'|%{"$_ --> "+(.\is-it-an-odd-word.ps1 $_)} trees --> 0 brush --> 1 CAts --> 1 Savoie --> 0 rhythm --> 0  • You can just use [^aeiou] for 37 bytes, as -replace is by default case insensitive. You'd have to use (?-i)[^aeiou] to make it case sensitive. Jun 22 at 16:12 J, 20 bytes 2|+/@e.&'aeiouAEOIU'  Straight-forward approach Explanation 2|+/@e.&'aeiouAEOIU' Input: string S e.&'aeiouAEOIU' Test each char in S for membership in 'aeiouAEOIU' +/@ Sum those values 2| Take it modulo 2 and return  • Haha, I just posted a J answer (now deleted) 1 byte longer than this. Nice job! Sep 21, 2016 at 1:01 • Where is the command for "take input"? – user58988 Sep 22, 2016 at 5:51 • @RosLuP This is a verb (function) that takes a single argument as input. J uses tacit programming so commands are chained together and pass values implicitly Sep 22, 2016 at 6:12 Japt, 7 bytes 1&Uè"%v  Test it online! Outputs 1 for odd, 0 for even. How it works  // Implicit: U = input string Uè // Count the number of matches of the following regex in the input: "%v // /[AEIOUaeiou]/g 1& // Take only the first bit (convert 1, 3, 5, etc. to 1, and others to 0) // Implicit output  Octave, 34 bytes @(s)mod(nnz(~(s'-'aeiouAEIOU')),2) s'-'aeiouAEIOU' % Creates a 2D-matrix where each of the odd letters are % subtracted from the string s ~(s'-'aeiouAEIOU') % Negates that array, so the all zero elements become 1 nnz( .... ) % Counts all the non-zero elements (the odd letters) mod(nnz( ....),2 % Takes this sum modulus 2  This is 6 bytes shorter than the traditional approach using ismember, @(s)mod(sum(ismember(s,'aeiouAEIOU')),2), and two bytes shorter than the regex approach: @(s)mod(nnz(regexpi(s,'[aeiou]')),2). PHP, 41 bytes <?=count(spliti("[aeiou]",$argv[1]))%2-1;


This outputs -1 for truthy and 0 for falsey.

• spliti was deprecated in PHP 5.3.0 (30 June 2009), and removed in PHP 7.0.0 (03 Dec 2015), so this submission should have specified a version for the language, e.g. "PHP 5.6.26". This submission would not have even worked in "PHP 5.2.17", the last version that didn't print a deprecation warning, because the <?= shorthand for <?php echo  was only introduced in PHP 5.4.0. Jun 22 at 17:44

Mathematica, 44 bytes

OddQ@StringCount[#,Characters@"aeiouAEIOU"]&


Gives True for an odd string and False for an even one.

• +1 to any man or woman learning mathematica Sep 21, 2016 at 21:01

q, 29 bytes

{mod[sum x in "aeiouAEIOU";2]}


C# 646256 50 Bytes

s=>1>s.Split("aeiouAEIOU".ToCharArray()).Length%2;

• We are already using linq, so Contains saves 2 bytes over IndexOf
• Using the method overload of Count saves 6 bytes
• Thanks to @Milk for suggesting a neat method and saving 6 more bytes

An anonymous function that takes a string and counts the odd letters then returns true if there is an odd number of them or false if there is not.

This new solution splits the string on any of the characters in the given char array. The mechanics of this flip the meaning of the %2 result; 0 is now odd and 1 even hence the 1>.

Try it online here!

• It's only 50 bytes to use string.Split() to count the vowels and you don't need LINQ. s=>1>s.Split("aeiouAEIOU".ToCharArray()).Length%2;
– milk
Sep 21, 2016 at 0:11
• @milk Thanks for that, very neat solution.
– user19547
Sep 22, 2016 at 16:12

x=${1,,//[aeiou]/} ((1&${#1}&${#x}))  Try it online! Zsh, 30 bytes ((1&$#1&${#${1:l}//[aeiou]/}))


Try it online!

Accepts input as its first argument. Exits with nonzero if even, exits zero if odd.

We barely beat out the bash+coreutils solution!

x=${1,,//[aeiou]/} # lowercase first argument, then remove all [aeiou] ((1&${#1}&${#x})) 1& & # bitwise-and 1 with${#1} \${#x}     # length of first parameter and length of stripped parameter
((             ))   # if nonzero, exit 0 (truthy in shell)
`

The Zsh solution is very similar, but uses the ability to nest parameter expansions to save an assignment.