They say that hate is a strong word. I wanted to find out why, so I had a good look at the word.

I noticed that every consonant had a vowel after it. That made it look quite strong to me, so I decided that that's what makes a word strong.

I want to find more strong words, so I'll need a program for it!

Finding strong words

Strong words are words where every consonant (letters in the set BCDFGHJKLMNPQRSTVWXZ) is followed by a vowel (letters in the set AEIOUY). That's it. Nothing else matters.

If the word starts with a vowel, you don't have to worry about any of the letters before the first consonant. If the word has no consonants in it at all, it's automatically a strong word!

Some examples of strong words are agate, hate and you. agate is still a strong word because although it starts with a vowel, every consonant is still followed by a vowel. you is a strong word because it has no consonants.

There is no restriction on length for strong words.

The challenge

Write a program or function that takes a non-empty string as input, and outputs a truthy value if it is a strong word or a falsy value if it is not.


  • You may decide to take the input in either lowercase or uppercase. Specify which in your answer.
  • Words will not contain punctuation of any kind. They will only contain plain letters in the set ABCDEFGHIJKLMNOPQRSTUVWXYZ.
  • Instead of truthy and falsy values, you may choose two distinct and consistent values to return for true and false. If you do this, specify the values you have picked in your answer.
    • You may alternatively output a falsy value for a strong word and a truthy one for a non-strong word.

Test cases

Input      -> Output
hate       -> true
love       -> true
popularize -> true
academy    -> true
you        -> true
mouse      -> true
acorn      -> false
nut        -> false
ah         -> false
strong     -> false
false      -> false
parakeet   -> false


Since this is , the answer with the least bytes wins!

  • \$\begingroup\$ Sandbox \$\endgroup\$
    – LyricLy
    Sep 9, 2017 at 21:49
  • 1
    \$\begingroup\$ Is the empty word "" a possible input? \$\endgroup\$ Sep 9, 2017 at 23:28
  • \$\begingroup\$ @SilvioMayolo It is not. \$\endgroup\$
    – LyricLy
    Sep 10, 2017 at 0:02
  • \$\begingroup\$ @LyricLy If input is "academy" then output should be false, the way I understand the problem. Because 'm' is a consonant. \$\endgroup\$
    – Truth-seek
    Sep 10, 2017 at 4:42
  • 1
    \$\begingroup\$ a "banana" is full of hate \$\endgroup\$
    – halfmang
    Sep 11, 2017 at 15:19

28 Answers 28


JavaScript (ES6), 36 28 27 bytes

Saved 1 byte by inverting the result, as suggested by LarsW

Takes input in lowercase. Returns false for a strong word and true for a non-strong word.



We append a 0 (non-vowel) at the end of the input string and look for two consecutive non-vowel characters. This allows us to cover both cases that make a word not strong:

  • it contains two consecutive consonants
  • or it ends with a consonant

Test cases

let f =


  "hate", "love", "popularize", "academy", "you", "mouse", "a", "euouae",
  "acorn", "nut", "ah", "strong", "false", "parakeet"
.forEach(s => console.log(s + ' --> ' + f(s)))

  • \$\begingroup\$ Why +0, though? It seems to work fine without it \$\endgroup\$ Sep 9, 2017 at 22:22
  • 1
    \$\begingroup\$ @MatheusAvellar Without the +0, it would return false positives on words ending with a consonant. \$\endgroup\$
    – Arnauld
    Sep 9, 2017 at 22:23
  • \$\begingroup\$ I see, without that it can't find 2 consecutive non-vowels if it's the last letter of the word. Smart! \$\endgroup\$ Sep 9, 2017 at 22:26
  • \$\begingroup\$ You should be able to omit the ! (two distinct values) \$\endgroup\$
    – LarsW
    Sep 10, 2017 at 7:59
  • \$\begingroup\$ @LarsW Thanks! I didn't notice this rule. \$\endgroup\$
    – Arnauld
    Sep 10, 2017 at 8:27

Python 2, 48 bytes

lambda s:'se, F'in`[v in'aeiouy'for v in s+'b']`

An unnamed function taking a (lowercase) string, s, and returning False if strong or True if not.

Try it online! (inverts the results to match the OP)


Non-strong words have either a consonant followed by a consonant or end in a consonant.

The code adds a consonant to the end (s+'b') to make the required test be just for two consonants in a row.

It finds out if each letter in the altered word is a vowel with the list comprehension [v in'aeiouy'for v in s+'b'].

It now needs to check for two False results in a row (signalling a non-strong word), it does so by getting a string representation (using `...`) of this list and looking for the existence of 'se, F'. This is the shortest string found in 'False, False' but none of: 'True, True'; 'False, True'; or 'True, False'.

As an example consider 'nut', the list comprehension evaluates each letter, v, of 'nutb' for existence in 'aeiouy' yielding the list [False, True, False, False], the string representation of this list is '[False, True, False, False]' which contains 'e, F' here: '[False, True, Fals>>e, F<<alse]' hence the function returns True meaning that nut is not a strong word.


Jelly,  10  9 bytes


A monadic link taking a list of characters and returning:

  • 0 if strong
  • 1 if not

Try it online! or see the test-suite.


e€ØY;Ạ11ẇ - Link: list of characters, s      e.g. "hate"  or  "you"  or  "not"
  ØY      - consonant yield                   "BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz"
e€        - exists in? for €ach letter            [1,0,1,0]   [0,0,0]    [1,0,1]
     Ạ    - all truthy? (1 for any valid input)   1           1          1
    ;     - concatenate                           [1,0,1,0,1] [0,0,0,1]  [1,0,1,1]
      11  - literal eleven
        ẇ - sublist exists?                       0           0          1
          -  N.B.: left of ẇ implicitly makes digits so it looks for the sublist [1,1]

Note: The reason for using is just to save a byte over using 1 (since we then want to use 11 straight away).

  • \$\begingroup\$ hmm, consistent values... \$\endgroup\$ Sep 10, 2017 at 8:17
  • \$\begingroup\$ what do you mean? \$\endgroup\$ Sep 10, 2017 at 8:54
  • \$\begingroup\$ the hacky thing in your code...otherwise you could've done e€ØY;1w11 or something \$\endgroup\$ Sep 10, 2017 at 9:04
  • \$\begingroup\$ Why eleven? String words didn't seem to be tied to the number eleven in any way \$\endgroup\$
    – hyiltiz
    Sep 12, 2017 at 0:26
  • \$\begingroup\$ @hyiltiz when the dyad has a left argument that is a number it gets implicitly converted to a decimal list of digits, so the eleven becomes [1,1]. \$\endgroup\$ Sep 12, 2017 at 0:46

05AB1E, 8 bytes



Uses the 05AB1E encoding. Try it online!


žPS¡         # Split the string on consonants (bcdfghjklmnpqrstvwxz)
    ¦        # Remove the first element of the array to handle cases when the
               string starts with a consonant
     õÊP     # Check if the empty string is not in the array


             # "popularize"
žPS¡         # ['', 'o', 'u', 'a', 'i', 'e']
    ¦        # ['o', 'u', 'a', 'i', 'e']
     õÊ      # [1, 1, 1, 1, 1]
       P     # 1
  • \$\begingroup\$ Maybe I'm missing something, but this seems to always return 1? It returns 1 for both the truthy cases I tried and the falsey testcases. \$\endgroup\$
    – Sundar R
    Aug 10, 2018 at 18:51
  • \$\begingroup\$ (Oh, I just noticed how old this answer (and question) is. I guess something in the language has changed in the meantime?) \$\endgroup\$
    – Sundar R
    Aug 10, 2018 at 19:43
  • \$\begingroup\$ @sundar Yes nice catch! It seems that I broke the split function at some point. I will fix this as soon as possible. \$\endgroup\$
    – Adnan
    Aug 11, 2018 at 12:22

R, 43 bytes


Try it online!

A port of Arnauld's JavaScript answer; returns 1 for weak words and integer(0) for strong ones; it appends a (space) to the end of the string.

This is actually vectorized; with a vector of strings, it returns the indices (1-based) of the weak words.

  • \$\begingroup\$ Same comment here, can't you use $ in the regex instead of adding a space? \$\endgroup\$
    – Charlie
    Sep 13, 2017 at 21:12
  • \$\begingroup\$ @Charlie I'm not sure how you intend on using $, care to explain that further? \$\endgroup\$
    – Giuseppe
    Sep 13, 2017 at 21:33
  • \$\begingroup\$ Like this solution a lot. I think the logic is clearer (and bytes the same) with paste0(s,0), but that is just quibbling. I think @Charlie is referencing something like this: grep("[^aeiouy]([^aeiouy]|$)",s) \$\endgroup\$ Aug 10, 2018 at 20:40

Dyalog APL, 20 bytes


Try it online!

  • 3
    \$\begingroup\$ I don't think you need ⎕←. \$\endgroup\$
    – Adalynn
    Sep 10, 2017 at 16:08
  • \$\begingroup\$ @Zacharý I used not to put it, but I was later told (by Dennis, I believe) that a program should not assume to be run in a REPL. \$\endgroup\$
    – Oberon
    Sep 13, 2017 at 15:00
  • \$\begingroup\$ What language did he tell you that about? Was it for Dyalog APL? I know that policy definitely applies for Python/JavaScript/etc. \$\endgroup\$
    – Adalynn
    Sep 13, 2017 at 20:44

Haskell, 61 54 bytes


Try it online!

I had to add a z at the end of the string to handle the case of a trailing consonant.


Husk, 12 bytes


Try it online!

Thanks to H.PWiz for help with -4. Returns inconsistent but appropriately truthy or falsy values.
Thanks to Leo for -1, now returns consistent truthy/falsy value.

  • \$\begingroup\$ Shorter compressed string. String compression is still way too slow, I need to work on it some more \$\endgroup\$
    – Leo
    Sep 12, 2017 at 0:52
  • \$\begingroup\$ @Leo I think that's an NP problem unfortunately. \$\endgroup\$ Sep 12, 2017 at 9:45

Java (OpenJDK 8), 93 81 bytes

s->{int w=0,p=w,l;for(char c:s)w|=p&(p=l="aeiouy".indexOf(c)>>31);return w+p>=0;}

Try it online!

  • \$\begingroup\$ I'm afraid booleans are not the answer: s->{int w=0,p=w,l;for(char c:s){l="aeiouy".indexOf(c)>>31;w|=p&l;p=l;}return w+p>=0;}. \$\endgroup\$
    – Jakob
    Sep 10, 2017 at 3:26
  • 1
    \$\begingroup\$ Or you can even do this: s->{int w=0,p=w,l;for(char c:s)w|=p&(p=l="aeiouy".indexOf(c)>>31);return w+p>=0;} \$\endgroup\$
    – Jakob
    Sep 10, 2017 at 3:34
  • \$\begingroup\$ Nice answer, but with this challenge a simple regex-matching is actually quite a bit shorter. Still, +1 from me. \$\endgroup\$ Sep 11, 2017 at 12:19
  • 1
    \$\begingroup\$ @KevinCruijssen My regex is awful, couldn't get it to work :D. I will pretend that I wanted to be original \$\endgroup\$ Sep 11, 2017 at 12:21
  • \$\begingroup\$ @RobertoGraham "I will pretend that I wanted to be original" Well, it certainly is. :) And I used to be pretty bad at regex as well, but after quite a few other answers here on PPCG using regex I'm getting more used to it. And I had already figured out how to match consonants using [a-z&&[^aeiouy]] in a previous answer of mine. ;) \$\endgroup\$ Sep 11, 2017 at 12:34

Pyth, 18 bytes


Verify all the test cases.

"Borrowed" the regex from the JS answer. This returns False for strong words, True otherwise

  • \$\begingroup\$ @KevinCruijssen In fact, Pyth uses ISO-8859-1. That's why I am not convinced. \$\endgroup\$
    – Mr. Xcoder
    Sep 11, 2017 at 12:44
  • 1
    \$\begingroup\$ @KevinCruijssen Downgoat's userscript tells me it is 13 bytes: 13 ISO-8859-1 bytes, 13 chars. I think that should be fine \$\endgroup\$
    – Mr. Xcoder
    Sep 11, 2017 at 12:46
  • \$\begingroup\$ @KevinCruijssen Should be fixed now. \$\endgroup\$
    – Mr. Xcoder
    Sep 11, 2017 at 12:56
  • \$\begingroup\$ @KevinCruijssen I don't see any difference. What is code do you see in my answer and what code do you see in my testing link? \$\endgroup\$
    – Mr. Xcoder
    Sep 11, 2017 at 13:10
  • \$\begingroup\$ @KevinCruijssen Lol, it's your browser's font. \$\endgroup\$
    – Mr. Xcoder
    Sep 11, 2017 at 13:20

Brachylog, 18 11 10 bytes


Try it online!

Neat and simple (except maybe for the 2 extra initial bytes to handle the final consonant case, like "parakeet").

Is falsey for strong words and truthy for non-strong words.

,Ḷ               % append a newline (non-vowel) at the end of input, 
                 %   to catch final consonants
     s₂          % the result has some substring of length 2
       {¬∈Ẉ}ᵐ    % where neither of its elements belong to  
                 %   the set of alternate vowels (with "y")

Perl 5, 31 bytes (30 + 1)


+1 byte for -p command line flag. Prints the word if it's a strong word, or the empty string if it is not.

  • \$\begingroup\$ "two distinct and consistent values" \$\endgroup\$
    – L3viathan
    Sep 10, 2017 at 0:12
  • \$\begingroup\$ @L3viathan Empty strings are falsy and non-empty strings are truthy. This is valid. \$\endgroup\$
    – LyricLy
    Sep 10, 2017 at 0:26
  • \$\begingroup\$ @L3viathan Perl's truthiness rules are actually very conducive to challenges like this. It's not the first time I've exploited that exact fact. \$\endgroup\$ Sep 10, 2017 at 3:36
  • \$\begingroup\$ With newline terminated words, this can be shortened to $_=$/if/[^aeiouy]{2}/. \$\endgroup\$
    – nwellnhof
    Sep 11, 2017 at 13:14

Jelly, 11 bytes


Try it online!

e€ØY;1a2\¬Ȧ  Main link
 €           For each letter
e            Is it an element of
  ØY         The consonants (excluding Yy)?
    ;1       Append 1 (true) (consonant) to make sure last letter isn't consonant
       2\    For all (overlapping) slices of length 2 (the <link><nilad>\ functionality)
      a      Logical AND of the two values; is it a consonant pair?
         ¬   Logical NOT vectorizing; for each (overlapping) pair, is it not a consonant pair?
          Ȧ  Any and all; make sure all pairs are not consonant pairs

Yes I know I've been beaten a lot by Jonathan Allan but I wanted to share my approach anyway :P

-4 bytes by stealing a little bit of Jonathan Allan's answer (instead of appending a consonant to check for last-letter edge case, just append 1)
-1 byte thanks to miles

  • \$\begingroup\$ You can save a byte using either a2\ or Ȧ2Ƥ instead of ṡ2Ȧ€ \$\endgroup\$
    – miles
    Sep 9, 2017 at 23:07
  • \$\begingroup\$ @JonathanAllan facepalm I deliberately made sure to use ØC to make sure Yy was counted as a consonant because somehow I remembered backwards. Thanks! \$\endgroup\$
    – hyper-neutrino
    Sep 10, 2017 at 1:08

Awk, 39 bytes

/([^aeiouy]{2}|[^aeiouy]$)/{print "n"}

prints n for non-strongword, nothing (or, just a newline) for strongword

following the pack and searching for two consecutive non-vowels on lowercase input


$ awk -f strongwork.awk

Kotlin, 49 bytes


True and false are swapped




var s:(String)->Boolean =
data class TestData(val input: String, val output: Boolean)

fun main(args: Array<String>) {
    val items = listOf(
            TestData("hate", true),
            TestData("love", true),
            TestData("popularize", true),
            TestData("academy", true),
            TestData("you", true),
            TestData("mouse", true),
            TestData("acorn", false),
            TestData("nut", false),
            TestData("ah", false),
            TestData("strong", false),
            TestData("false", false),
            TestData("parakeet", false)

            .filter { s(it.input) == it.output }
            .forEach { throw AssertionError(it.toString()) }

    println("Test Passed")


Based on @Arnauld's Answer


Retina, 23 18 bytes


Try it online! Outputs 0 for strong, 1 if not. Add 1 byte to support mixed case. Edit: Saved 5 bytes thanks to @ovs.

  • \$\begingroup\$ 18 bytes by appending a consonant to the end. \$\endgroup\$
    – ovs
    Sep 10, 2017 at 11:52

Java 8, 53 42 bytes


-11 bytes by using the same regex as in @jrtapsell's Kotlin answer instead.

Try it here. (false if strong; true if not)


s->               // Method with String parameter and boolean return-type
  s.matches(      //  Checks if the String matches the following regex:
    ".*           //   One or more characters
     [^aeiouy]    //   Followed by a consonant
     ([^aeiouy].* //   Followed by another consonant (+ any more characters)
      |$)")       //   Or the end of the String
                  // End of method (implicit / single-line return statement)

So it basically checks if we can find two adjacent consonants, or if the String ends with a consonant.

Old answer (53 bytes):


Try it here. (true if strong; false if not)

Uses regex to see if the input-String matches the 'strong'-regex. Note that String#matches in Java automatically adds ^...$ to check if the String entirely matches the given regex.


 s->                   // Method with String parameter and boolean return-type
  s.matches(           //  Checks if the String matches the following regex:
    "[aeiouy]*         //   0 or more vowels
    ([a-z&&[^aeiouy]]  //     { A consonant,
     [aeiouy]+)        //       plus one or more vowels }
    *")                //    Repeated 0 or more times
                       // End of method (implicit / single-line return statement)

A search instead of matches (like a lot of other answers use) is actually longer in Java:
70 bytes:


Try it here. (false if strong; true if not)


Ruby, 25 bytes


Try it online!

Everybody else is doing it, so why can't Ruby?


Python 2, 58 bytes

-30 bytes by realizing it can be as simple as Arnauld's JS answer.

lambda s:re.search('[^aeiouy]([^aeiouy]|$)',s)<1
import re

Try it online!

  • \$\begingroup\$ Save 6 bytes by really doing the same as Arnauld \$\endgroup\$
    – L3viathan
    Sep 9, 2017 at 23:02
  • \$\begingroup\$ Don't you need to assign the lambda to somthing? i.e. f=lambda s... \$\endgroup\$
    – AAM111
    Sep 9, 2017 at 23:41
  • \$\begingroup\$ @OldBunny2800 not unless you are using the reference within your code (it is acceptable to create an unnamed function one could access for reuse with header or footer code - here with f=\ in a header). \$\endgroup\$ Sep 9, 2017 at 23:50
  • \$\begingroup\$ I think you might be able to replace your pattern string '[^aeiouy]([^aeiouy]|$)' (24 bytes) with "[^aeiouy]("*2+")|$)" (21 bytes) to save 3 bytes, as the empty group, (), does not change the search behavior (TIO). \$\endgroup\$ Sep 10, 2017 at 3:03
  • \$\begingroup\$ @JonathanFrech It can get even better \$\endgroup\$
    – Mr. Xcoder
    Sep 10, 2017 at 7:15

SOGL V0.12, 19 18 bytes


Try it Here!


æ                   push "aeiou"
 "[^ŗy]”            push "[^ŗy]" with ŗ replaced with pop
        ŗ(ŗ|$)”     push `ŗ(ŗ|$)` with ŗ replaced with pop
               øβ   replace in the input that regex with nothing
                 =  check for equality with the original input

05AB1E, 11 bytes


Try it online!

Uses Jonathan's algorithm, returns 0 for true and 1 for false.


Swift 3.1, 85 bytes

import Foundation

Try it here!

This borrows Arnauld's regex.


Lua, 41 bytes


Reads from standard input

Lua (loadstring'ed), 37 bytes


Reads from function parameter(s)

Input is lowercase

Sees if there is a string of length 2 or more, consisting only of not vowels (consonants) or if the string ends with a non-vowel

Returns true/false


C++, 195 194 bytes

-1 bytes thanks to Zacharý

Uppercase, return true if input is a strong word, false otherwise ( C++ have simple int to bool implicit cast rules, 0 => false, true otherwise )

#define C(p)(v.find(e[p])==size_t(-1))
std::string v="AEIOUY";int s(std::string e){for(int i=0;i<e.size()-1;++i)if(e[i]>64&&e[i]<91&&C(i)&&C(i+1))return 0;return!C(e.size()-1);}

Code to test :

auto t = {

for (auto&a : t) {
    std::cout << (s(a) ? "true" : "false") << '\n';
  • 1
    \$\begingroup\$ You can remove the space between return and !. \$\endgroup\$
    – Adalynn
    Sep 10, 2017 at 15:53

C, 107 Bytes

i,v,w,r,t;a(char*s){w=0;for(r=1;*s;s++){v=1;for(i=6;v&&i;)v=*s^" aeiouy"[i--];r=w&&v?0:r;w=v;}return r&~v;}

Returns 1 for strong word and 0 for weak word. Tested with the words given in the main post.


C (gcc), 59 bytes


Try it online!


PHP, 69 bytes


Returns 1 is the word is not strong.

  • \$\begingroup\$ Welcome to PPCG! I believe you can remove spaces to cut some bytes, specifically /", str -> /",str and [1]))) return -> [1])))return but I don't know PHP too well so I can't be sure. \$\endgroup\$
    – Stephen
    Sep 12, 2017 at 14:34
  • \$\begingroup\$ Yes, good idea! Also it is possible to reduce bytes by assuming that input is always in uppercase. \$\endgroup\$ Sep 12, 2017 at 14:41
  • \$\begingroup\$ Oh, and if the regex is a standard regex engine, can't you do [B-Z]? \$\endgroup\$
    – Stephen
    Sep 12, 2017 at 14:42
  • \$\begingroup\$ @Stephen [B-Z] includes vowels. [^AEIOUY] works, though. \$\endgroup\$
    – LyricLy
    Sep 12, 2017 at 20:18
  • \$\begingroup\$ I don't know PHP either, but you could probably save more bytes by returning the result from the regex match directly, instead of wrapping it in an if statement. \$\endgroup\$
    – LyricLy
    Sep 12, 2017 at 20:20

CJam, 57 bytes


Try it online!

Reads input, converts to 1s for consonants, 0s for vowels. For every consonant, AND predefined variable X (predefined to 1) with next character's value. Output X


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.