28
\$\begingroup\$

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.

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

69 Answers 69

1
\$\begingroup\$

Perl, 18/19 bytes

Includes +1 for -p

Give input on STDIN, prints 0 for even, 1 for odd

#!/usr/bin/perl -p
$_=1&lc=~y;aeiou;

Must be put in a file, but the file must not have a final newline giving 18 bytes. This is admittedly abusing the perl counting rules a bit since this actually doesn't work when run in a -e commandline which implicitely adds a final \n which makes the program not work. So more honest but 19 bytes is:

#!/usr/bin/perl -p
$_=1&lc=~y;aeiou;;
\$\endgroup\$
1
\$\begingroup\$

R, 164 bytes

I'm sure this can be done better, but it's still good practice.

f<-function(w){
l<-"aeiouAEIOU"
c<-0
for(i in 1:10){
for(j in 1:nchar(w)){
if(substr(l,i,i)==substr(w,j,j)){c<-c+1}}}
if(c%%2==0){print("F")}else{print("T")}}

input/output

> f("trees")
[1] "F"
> f("brush")
[1] "T"
> f("CAts")
[1] "T"
> f("Savoie")
[1] "F"
> f("rhythm")
[1] "F"

"F" for false and "T" for true.

\$\endgroup\$
  • \$\begingroup\$ Welcome to codegolf fellow R-user. May I recommend the following approach rather to reduce it to 117 bytes: function(w){a=substr;l="aeiouAEIOU";c=0;for(i in 1:10){for(j in 1:nchar(w))if(a(l,i,i)==a(w,j,j))c=c+1};cat(c%%2!=0)}. In other words, use = for assignment rather than <-, removed some unnessecary {...} as well, aliasing the substr() function to a since you use it twice. Finally instead of printing out a T or F string, just print the logical equivalents instead with the cat() function rather than print. \$\endgroup\$ – Billywob Sep 21 '16 at 8:26
  • \$\begingroup\$ Also, I would recommend to check out my vectorized solution here. There I also use readline() rather than defining a full function which is shorter when only one input is required. \$\endgroup\$ – Billywob Sep 21 '16 at 8:28
  • \$\begingroup\$ Thanks so much, I will look at all of your suggestions Billywob. \$\endgroup\$ – Arwalk Sep 22 '16 at 2:07
1
\$\begingroup\$

CJam, 18 17 bytes

0lel"aeiou"f{&,^}

Try it online!

Explanation

0                 e# Push 0
 l                e# Read line from input
  el              e# Convert to lowercase
   "aeiou"        e# Push this string
          f{   }  e# Map code block to each char of the input and the string "aeiou"
            &     e# Set intersection of each input char with the "aeiou". The result
                  e# is either that char or the empty string
             ,    e# Length. Gives 0 or 1
              ^   e# Binary XOR. Uses the initial 0 the first time
                  e# Implicitly display
\$\endgroup\$
  • \$\begingroup\$ lel_"aeiou"--,1& saves a byte. \$\endgroup\$ – Dennis Sep 21 '16 at 0:20
  • \$\begingroup\$ @Dennis Thanks! That's very clever. But it's a significantly different approach, you should post it yourself \$\endgroup\$ – Luis Mendo Sep 21 '16 at 7:18
1
\$\begingroup\$

Batch, 132 bytes

@echo off
set/ps=
set s=%s%%s:a=%%s:e=%%s:i=%%s:o=%%s:u=%
:l
if "%s%"=="" exit/b0
if "%s:~1%"=="" exit/b1
set s=%s:~2%
goto l

Takes input on STDIN, exits with ERRORLEVEL equal to 1 if the word is odd, 0 if it is even. Works by multiplying all the vowels by five and other letters by six, then calculating the parity of the resulting length.

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

Lua, 47 44 43 Bytes

print(#arg[2]:gsub('[^aeiouAEIOU]','')%2>0)

Takes the input via the command line, replaces all non-vowels with nothing, (removes them), prints true if the length of that is odd, false otherwise.

Old submission

_,n=arg[2]:gsub('[aeiouAEIOU]','')print(n%2~=0)
\$\endgroup\$
1
\$\begingroup\$

Bash + coreutils, 37 bytes

bc<<<!`sed s:[^aeiou]::ig\;q|wc -m`%2

The input word is taken from STDIN. Output is 1 if the word is odd, or 0 if it is even.

Explanation:

       sed s:[^aeiou]::ig\;q     # remove even letters from input and exit sed
       |wc -m                    # count remaining chars (odd letters + 1 for \n)
bc<<<!`                     `%2  # apply mod 2 and invert the boolean result

Run example:

me@LCARS:/PPCG$ ./odd_word.sh
trees
0
\$\endgroup\$
1
\$\begingroup\$

R, 78 bytes

Solution is based on counting the number of vowels:

s=strsplit;w=s(readline(),"")[[1]];v=s("aeiouAEIOU","")[[1]];sum(w%in%v)%%2!=0

Explanation

Unfortunately most functions in R relating to strings work on vectors of characters rather than full strings, thus the solution converts input into a vector using strsplit and checks whether this contains any vowels => sum the number of vowels and check if odd/even.

Also I found that using v=s("aeiouAEIOU","")[[1]] was shorter than manually inputting a vector of vowels which would have worked if only lower or upper case letters were used.

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

T-SQL (SQL Server 2014), 217 bytes

Golfed

declare @ table(a char)declare @i int=1while @i<=len(@a)begin insert into @ values(SUBSTRING(@a,@i,1))set @i=@i+1 end select count(*)%2from @ where a in('a','e','i','o','u')

Usage

First declare the variable @a as a char of some sort and assign the input like so

declare @a varchar(max) = 'CAts'

Output will either be 1 for odd, or 0 for even

Ungolfed

declare @input varchar(max) = 'rhythm'

declare @temp table ( letter char(1) ) -- table to hold each letter of the word

declare @i int = 1

while @i <= len(@input) -- split each letter, and each row in @temp will have one letter
begin
    insert into @temp values (SUBSTRING(@input, @i, 1))
    set @i = @i + 1
end

-- count the vowels and mod two to get if there's an even number of vowels or an odd number
select count(*) % 2
from @temp
where letter in ('a', 'e', 'i', 'o', 'u') -- use sql's case insensitive strings
\$\endgroup\$
1
\$\begingroup\$

Groovy (39 Bytes)

{s->s.collect{/aeiou/=~it?1:0}.sum()%2}

https://groovyconsole.appspot.com/script/5195711326978048

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

Actually, 17 bytes

Golfing suggestions welcome. Try it online!

ù╝"aeiou"`╛c`MΣ1&

Ungolfing

                    Implicit input s.
ù╝                  Add s.lower() to register 1.
  "aeiou"`  `M      Push the string "aeiou" and map the following function over it.
          ╛         Push register 1 to stack.
           c        Count the occurrences of "a", then "e", etc.
              Σ     Sum the counts of these occurrences.
               1&   x&1 == x%2.
                    Implicit return.
\$\endgroup\$
  • \$\begingroup\$ You don't have to output the actual words even and odd. Anything that is false and true in your language qualifies \$\endgroup\$ – Ton Hospel Sep 20 '16 at 19:12
  • \$\begingroup\$ Ah. Thanks @TonHospel. I had not reread the specification since I first saw in chat. Will edit my answer shortly \$\endgroup\$ – Sherlock9 Sep 20 '16 at 19:13
1
\$\begingroup\$

Julia, 53 Bytes

f(s)=sum(map(x->x in ["aeiouAEIOU"...]?1:2,[s...]))%2

replace odd characters with 1 and even characters with 2, then sum up. if the sum is even, then the word is even.

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

O, 27 bytes

Q_e\'a-'e-'i-'o-'u-e\;-e01?
\$\endgroup\$
1
\$\begingroup\$

Turtlèd, 91 65 64 52 47 67 bytes

More bytes because now takes case insensitive input

Changed approach again

does * for even, else o for odd

(trailing space)

!-u[*+.(a,)(e,)(i,)(o,)(u,)(A,)(E,)(I,)(O,)(U,)(*d(*'ou)(o'*u))_]' 

It goes through input, writing it down on one square, each time there is a vowel, it moves down, flips the state of a the output cell, continues until EOF of input, then removes the cell where it writes down all the characters.

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

PHP, 91 bytes

foreach(str_split($argv[1])as$c)$n+=substr_count("AEIOU",strtoupper($c));if($n%2==0)echo 1;

Outputs 1 for even word, empty for odd word.

Test online

Testing code:

$wa = array('trees','brush','CAts','Savoie','rhythm');
foreach ($wa as $w) {
    $n = 0;
    foreach(str_split($w) as $c) 
        $n+=substr_count("AEIOU",strtoupper($c));
    if ($n%2==0) echo 1;
}

Test online

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

Clojure, 38 bytes

#(rem(count(re-seq #"(?i)[aeiou]"%))2)

Try it online!

This anonymous function outputs 1 for odd and 0 for even.

Explanation

#"(?i)[aeiou]" ; This is a regular expression that matches a capital or lowercase vowel.
re-seq ; Returns a lazy sequence that contains all of the regex's matches from the input string.
count ; Returns the length of that sequence.
rem ; Returns the remainder when that length is divided by 2
\$\endgroup\$
1
\$\begingroup\$

Brachylog, 11 bytes

ḷ{∈Ṿ&}ˢl%₂1

Try it online!

The predicate succeeds if the input is odd and fails if it is even.

       l       The number of letters
ḷ              in the lowercased input
 {  &}ˢ        which are
  ∈            members of
   Ṿ           "aeiou"
        %₂     mod 2
          1    is equal to 1.
\$\endgroup\$
1
\$\begingroup\$

Java (JDK), 53 52 51 bytes

s->{return(s+"#").split("(?i)[AEIOU]").length%2<1;}

Try it online!

Edit: Saved a byte 2 bytes thanks to @JonathanFrech

\$\endgroup\$
  • 1
    \$\begingroup\$ return 1>(... to return(...<1 possibly? \$\endgroup\$ – Jonathan Frech Mar 3 '19 at 15:45
  • 1
    \$\begingroup\$ Also, could you not use (?i)[aeiou] instead of [aeiouAEIOU]? \$\endgroup\$ – Jonathan Frech Mar 3 '19 at 15:53
1
\$\begingroup\$

Bash, 36 bytes

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.

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

Java 143 bytes

Output is a boolean which is true if the word is odd.

public static boolean isOdd(char c){
return c=='a'||c=='e'||c=='i'||c=='o'||c=='u';
}


public static boolean isOdd(String k){
  boolean y=false;
  for(char x:k.toLowerCase().toCharArray())
    if(isOdd(x))
      y=(y?false:true);
  return y;
}

Golfed:

boolean i(String k){boolean y=false;for(char c:k.toLowerCase().toCharArray())if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u')y=!y;return y;}

Edit:

  • Fixed Case-sensitivity
\$\endgroup\$
  • \$\begingroup\$ Did you run this against the third test case? \$\endgroup\$ – user18932 Sep 20 '16 at 19:33
0
\$\begingroup\$

PHP, 43 Bytes

<?=preg_match_all("#[aeiou]#i",$argv[1])%2;
\$\endgroup\$
  • 1
    \$\begingroup\$ Following the rules directly, just preg_match_all("#[aeiou]#i",$argv[1])%2 qualifies. \$\endgroup\$ – alanaktion Sep 21 '16 at 5:43
0
\$\begingroup\$

Retina, 24 21 bytes

i`[aeiou]
1
T`Ll`
11

(there's a mandatory additional empty line, but formatting ignores it)

Returns 1 for odd words, and void for even ones.

Try it online!

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

Java, 59 bytes

s->s.chars().map(c->"aeiouAEIOU".indexOf(c)<0?0:1).sum()%2;

Ungolfed test program

public static void main( String[] args )
{
    Function<String, Integer> func = s -> s.chars().map( c -> "aeiouAEIOU".indexOf( c ) < 0 ? 0 : 1 ).sum() % 2;

    System.out.println( func.apply( "cat" ) );
}
\$\endgroup\$
0
\$\begingroup\$

Dyalog APL, 17 bytes

2|≢⍞∩'aeiouAEIOU'

TryAPL online!

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

R, 49 bytes

f=function(x)nchar(gsub("[^aeiou]","",x,i=T))%%2==0

Examples:

> f("cats")
[1] FALSE

> f("Savoie")
[1] TRUE

If it doesn't need a function and I can assume x is the input:

36 bytes:

!nchar(gsub("[^aeiou]","",x,i=T))%%2

If I can allow an output of 0 for even and 1 for odd:

35 bytes:

nchar(gsub("[^aeiou]","",x,i=T))%%2

Explanation

I'm substituting all vowels with blank character, ignoring case (i=T). This works because the i is enough to unambigiously identify the ignore.case argument and T is short for TRUE. Then count the odd characters and see if there's a remainder. If a number isn't a good response, I use ! (not) to coerce the 0/1 to TRUE/FALSE.

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

Go, 93 bytes

func(s string)int{n:=0;for _,c:=range s{for _,d:=range"aeiouAEIOU"{if c==d{n++}}};return n%2}
\$\endgroup\$
0
\$\begingroup\$

Lithp, 56 bytes, non-competing

#S::((& 1 (~ (length (split S (regex "[aeiou]" "i"))))))
  • Odd words: returns 1
  • Even words: returns 0

Non-competing because this was one of my test cases for developing my language. It was modified extensively after this challenge was posted to support running code such as this.


This is the same logic as the JavaScript response above. The language is a simplistic Lisp-like dialect with a fairly small interpreter.

Ungolfed:

(
    (var F #S::(
        (var L (split S (regex "[aeiou]" "i")))
        (& 1 (~ (length L)))
    ))
    (print (call F "brush"))
)

There is not currently an online repl to test this in, but there is a variation of this challenge in one of the provided examples that can be run with the interpreter.

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

Racket 127 bytes

(if(= 0(modulo(for/sum((i(map(λ(i)(ormap(λ(x)(equal? i x))(string->list"aieouAEIOU")))(string->list s))))(if i 1 0))2))#f #t)

Ungolfed:

(define(f s)
  (let* ((vl (string->list "aieouAEIOU"))
         (od (λ(i) (ormap (λ (x) (equal? i x)) vl)))
         (ol (map od (string->list s)))
         (s (count (λ(i) i) ol ))
         (m (modulo s 2)))
    (if (= m 0) "even" "odd")
  ))

A longer (240 bytes) but more direct version:

(let*((vl(string->list"aieouAEIOU"))(od(λ(i)(ormap(λ(x)(equal? i x))vl))))(let lp((l(string->list s))
(st #t)(d 0))(cond((null? l)(if d"odd""even"))(st(lp(cdr l)#f(if(od(car l))#t #f)))
(else(lp(cdr l)#f(if(equal? d(od(car l)))#f #t))))))

Ungolfed:

(define (f s)
  (let* ((vl (string->list "aieouAEIOU"))
         (od (λ (i) (ormap (λ (x) (equal? i x)) vl) )))
    (let loop ((l (string->list s))
               (starting #t)
               (odd 0))
      (cond
        ((null? l) 
         (if odd "odd" "even"))
        (starting
         (loop (rest l) #f
               (if(od (first l))
                  #t #f )))
        (else 
         (loop (rest l) #f 
               (if (equal? odd
                           (od (first l)))
                   #f #t)))))))

Testing:

(f "trees")
(f "brush")
(f "CAts")
(f "Savoie")
(f "rhythm")

Output:

"even"
"odd"
"odd"
"even"
"even"
\$\endgroup\$
0
\$\begingroup\$

Java, 128 bytes

boolean f(String k){return k.chars().flatMap(i->"aeiouAEIOU".contains(((char)i)+"")?IntStream.of(1):IntStream.of(0)).sum()%2>0;}

There's definitely a better way than using Instream.of(0) and Instream.of(1).

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

Ruby, 30 bytes

->w{w.count('aeiouAEIOU')%2>0}

Returns true for an odd word and false for an even word. The existing Ruby solution returns 0 for even words, which is a truthy value in Ruby.

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

Elixir, 45 bytes

&rem(length(Regex.scan(~r/[aeiou]/i,&1)),2)>0

Anonymous function defined using the capture operator. If the number of vowels is odd, the specified word is odd, so the function returns true.

Full program with test cases:

s=&rem(length(Regex.scan(~r/[aeiou]/i,&1)),2)>0
# test cases
IO.puts s.("trees") # false
IO.puts s.("brush") # true
IO.puts s.("CAts")  # true
IO.puts s.("Savoie")    # false
IO.puts s.("rhythm")    # false

Try it online on ElixirPlayground !

\$\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.