38
\$\begingroup\$

Your task is to write a program that will output a readable list of every five letter words with the structure:

consonant - vowel - consonant - vowel - consonant

The output should be sorted alphabetically with one word per line and no words repeated twice. It can be lowercase or uppercase but not mixed. So the list could start and end like this:

babab  
babac  
babad  
...  
zyzyw  
zyzyx  
zyzyz 

Vowels are a-e-i-o-u-y, the other 20 English-alphabet letters are consonants.
Words don't have to be actual dictionary words.
Shortest code wins.

Note: A few years ago I stumbled upon a program on a university website that did exactly that. Turns out my first and last name fit the c-v-c-v-c constraint, and i'd been googling myself.

\$\endgroup\$
  • 7
    \$\begingroup\$ I see two things here. First, there are a ridiculous amount of words like this. How do you expect to test the entries? Also, there are many names that fit that constraint. The first that comes to mind is Jacob, although others like Lucas also fit \$\endgroup\$ – TrojanByAccident Jan 12 '17 at 12:10
  • 9
    \$\begingroup\$ @TrojanByAccident I believe the challenge requires all possible matching letter combinations, regardless of whether they are names/English words. "Words don't have to be actual dictionary words." \$\endgroup\$ – trichoplax Jan 12 '17 at 12:22
  • 3
    \$\begingroup\$ @wilks Relevant meta post -- Strict i/o formats aren't appreciated in this SE community. This challenge is focusing on generating c-v-c-v-c words, not inserting newlines between words, no? \$\endgroup\$ – JungHwan Min Jan 12 '17 at 14:41
  • 1
    \$\begingroup\$ @JungHwanMin Thanks for the link, first time here and I didn't know about this. I saw it as a readable and alphabetical list of all the c-v-c-v-c words. So I agree that upper or lowercase really doesn't matter, but I also think that one very long string or, say some nested arrays, whilst technically valid wouldn't be a great answer. \$\endgroup\$ – wilks Jan 12 '17 at 15:30
  • 2
    \$\begingroup\$ Having run a few of the upvoted answers to this question, they obviously do not comply with "The output should be incremental with each word on its own line". Has this requirement been relaxed and if so can you edit the question to reflect this? I reckon I could lose quite a few bytes if my answer wasn't restricted by the format. \$\endgroup\$ – ElPedro Jan 12 '17 at 18:33

45 Answers 45

28
\$\begingroup\$

Mathematica, 72 65 61 bytes

Print@@@Tuples@{a=##/(b=#5#9#15#21#25#)&@@Alphabet[],b,a,b,a}

For testing, I recommend replacing Print@@@ with ""<>#&/@. Mathematica will then display a truncated form showing the first few and last few words, instead of taking forever to print 288,000 lines.

Explanation

I finally found a use for dividing strings. :)

I've been intrigued by the possibility of adding or multiplying strings for a while, but the actual use cases are fairly limited. The main point is that something like "foo"+"bar" or "foo"*"bar" (and consequently, the short form "foo""bar") is completely valid in Mathematica. However, it doesn't really know what to do with the strings in arithmetic expressions, so these things remain unevaluated. Mathematica does apply generally applicable simplifications though. In particular, the strings will be sorted into canonical order (which is fairly messed up in Mathematica, once you start sorting strings containing letters of various cases, digits and non-letters), which is often a dealbreaker, but doesn't matter here. Furthermore, "abc""abc" will be simplified to "abc"^2 (which is a problem when you have repeated strings, but we don't have that either), and something like "abc"/"abc" will actually cancel (which we'll be even making use of).

So what are we trying to golf here. We need a list of vowels and a list of consonants, so we can feed them to Tuples to generate all possible combinations. My first approach was the naive solution:

Characters@{a="bcdfghjklmnpqrstvwxz",b="aeiouy",a,b,a}

That hardcoded list of consonants does hurt a bit. Mathematica does have an Alphabet built-in which would allow me to avoid it, if I were able to remove the vowels in a cheap way. This is where it gets tricky though. The simplest way to remove elements is Complement, but that ends up being longer, using one of the following options:

{a=Complement[Alphabet[],b=Characters@"aeiouy"],b,a,b,a}
{a=Complement[x=Alphabet[],b=x[[{1,5,9,15,21,25}]]],b,a,b,a}

(Note that we don't need to apply Characters to the whole thing any more, because Alphabet[] gives a list of letters, not a string.)

So let's try that arithmetic business. If we represent the entire alphabet as a product of letters instead of a list, then we can remove letters by simple division, due to the cancelling rule. That saves a lot of bytes because we won't need Complement. Furthermore, "a""e""i""o""u""y" is actually a byte shorter than Characters@"aeiouy". So we do this with:

a=##/(b="a""e""i""o""u""y")&@@Alphabet[]

Where we're storing the consonant and vowel products in a and b, respectively. This works by writing a function which multiplies all its arguments with ## and divides them by the product of vowels. This function is applied to the alphabet list, which passes each letter in as a separate argument.

So far so good, but now we have

{a=##/(b="a""e""i""o""u""y")&@@Alphabet[],b,a,b,a}

as the argument to Tuples, and those things are still products, not lists. Normally, the shortest way to fix that is putting a List@@@ at the front, which turns the products into lists again. Unfortunately, adding those 7 bytes makes it longer than the naive approach.

However, it turns out that Tuples doesn't care about the heads of the inner lists at all. If you do

Tuples[{f[1, 2], f[3, 4]}]

(Yes, for an undefined f.) You'll get:

{{1, 3}, {1, 4}, {2, 3}, {2, 4}}

Just as if you had used a List instead of f. So we can actually pass those products straight to Tuples and still get the right result. This saves 5 bytes over the naive approach using two hardcoded strings.

Now the "a""e""i""o""u""y" is still fairly annoying. But wait, we can save a few bytes here as well! The arguments of our function are the individual letters. So if we just pick out the right arguments, we can reuse those instead of the string literals, which is shorter for three of them. We want arguments # (short for #1), #5, #9, #15, #21 and #25. If we put # at the end, then we also don't need to add any * to multiply them together, because (regex) #\d+ is a complete token that can't have any non-digit appended to it. Hence we end up with #5#9#15#21#25#, saving another 4 bytes.

\$\endgroup\$
  • 11
    \$\begingroup\$ Reads explanation. So... basically magic. \$\endgroup\$ – Tally Jan 12 '17 at 14:57
  • \$\begingroup\$ I'm surprised and impressed by your Tuples trick. That's entirely undocumented, right? And unexpected given how the two-input form Tuples[list,n] deals with list not having the List head (to me at least)! \$\endgroup\$ – A Simmons Jan 12 '17 at 17:26
  • 1
    \$\begingroup\$ @ngenisis I find that wording very confusing. Because it's not clear that this refers to the outer list when using multiple lists. Indeed Tuples[f[{1,2}, {3,4}]] gives {f[1, 3], f[1, 4], f[2, 3], f[2, 4]} instead. It's not documented that the inner head is completely ignored. \$\endgroup\$ – Martin Ender Jan 12 '17 at 21:45
  • \$\begingroup\$ @ASimmons cc. ^ \$\endgroup\$ – Martin Ender Jan 12 '17 at 21:45
16
\$\begingroup\$

Perl, 47 bytes

#!perl -l
/((^|[aeiouy])[^aeiouy]){3}/&&print for a..1x5

Counting the shebang as one.

Try it online!

\$\endgroup\$
  • 2
    \$\begingroup\$ This is nice, well done! Any reasons you're not using say ? \$\endgroup\$ – Dada Jan 12 '17 at 12:57
  • \$\begingroup\$ Thanks. I disagree that -M5.01 should be 'free'. \$\endgroup\$ – primo Jan 12 '17 at 13:02
  • 1
    \$\begingroup\$ I like your opinion on -M5.010. And the intersting part in the golfing isn't to replace print with say... \$\endgroup\$ – Dada Jan 12 '17 at 13:05
  • \$\begingroup\$ Isn't -E (and subsequently say) a freebie? \$\endgroup\$ – Zaid Jan 12 '17 at 18:20
  • \$\begingroup\$ @Zaid See Primo's first comment \$\endgroup\$ – Dada Jan 12 '17 at 19:12
11
\$\begingroup\$

Python 3 - 110 bytes

a,b="bcdfghjklmnpqrstvwxz","aeiouy";print(*(c+d+e+f+g for c in a for d in b for e in a for f in b for g in a))

Straightforward looping fun :)

\$\endgroup\$
  • \$\begingroup\$ Think our ideas are the same but you beat me by 10 with Python 3! \$\endgroup\$ – ElPedro Jan 12 '17 at 16:03
  • \$\begingroup\$ I was just about to post a python2 equivalent using this approach. Too slow, a vote for you instead. \$\endgroup\$ – Chris H Jan 12 '17 at 16:15
8
\$\begingroup\$

Ruby, 72 71 52 bytes

puts (?z..?z*5).grep /#{["[^aeiouy]"]*3*"[aeiouy]"}/

Thanks to Value Ink for the basic idea, which brought that down to 60 bytes.

\$\endgroup\$
  • 1
    \$\begingroup\$ It's shorter to generate a list of 5-letter words and using grep. If you generate a range that uses lower-case strings, you get a sequence of the lower-case words only. puts ("babab".."zyzyz").grep /#{["[^aeiouy]"]*3*"[aeiouy]"}/ for 60 bytes \$\endgroup\$ – Value Ink Jan 13 '17 at 2:20
7
\$\begingroup\$

05AB1E, 18 16 bytes

05AB1E uses CP-1252 encoding.

žP3ãžO3ãâ€øJ€¨ê»

Explanation

žP3ã                # push all combinations of 3 consonants
    žO3ã            # push all combinations of 3 vowels
        â           # cartesian product
         €ø         # zip each pair of [ccc,vvv] (c=consonant,v=vowel)
           J        # join to list of strings ['cvcvcv','cvcvcv' ...]
            ۬      # remove last vowel from each
              ê     # sort and remove duplicates
              »     # join on newlines

For testing purposes I recommend replacing žP with a few consonants and žO with a few vowels.

Example using 5 consonants and 3 vowels

\$\endgroup\$
  • \$\begingroup\$ nice use of Cartesian product. Wouldn't've thought of that. \$\endgroup\$ – Magic Octopus Urn Jan 12 '17 at 14:45
7
\$\begingroup\$

Python 2, 120 102 94 bytes

from itertools import*
lambda:map(''.join,product(*(('AEIOUY','BCDFGHJKLMNPQRSTVWXZ')*3)[1:]))

Try it online!

\$\endgroup\$
7
\$\begingroup\$

Pure Bash, 74

v={a,e,i,o,u,y}
c={b,c,d,f,g,h,{j..n},{p..t},v,w,x,z}
eval echo $c$v$c$v$c

Straightforward brace expansion.

Try it online.


If each item must be on its own line, then we have:

Pure Bash, 84

v={a,e,i,o,u,y}
c={b,c,d,f,g,h,{j..n},{p..t},v,w,x,z}
eval printf '%s\\n' $c$v$c$v$c
\$\endgroup\$
7
\$\begingroup\$

PHP, 88 86 84 80 bytes

pretty string increment :)
6 bytes saved by @Christoph

for($s=$v=aeiouy;++$s<zyzza;preg_match("#[^$v]([$v][^$v]){2}#",$s)&&print"$s
");

loops through all strings from bababa to zyzyz and tests if they match the pattern. Run with -nr.

\$\endgroup\$
  • \$\begingroup\$ Lol, golfing with a buggy language spec, I like it \$\endgroup\$ – Patrick Roberts Jan 12 '17 at 16:48
  • 1
    \$\begingroup\$ @PatrickRoberts It´s not a bug. It´s a feature. :D I am sad they embedded an implicit cast to integer into $a="001";$a++; some day. That was a very unconvenient change. \$\endgroup\$ – Titus Jan 12 '17 at 16:52
  • 1
    \$\begingroup\$ for($s=$v=aeiouy;++$s<zyzza;)preg_match("#[^$v][$v][^$v][$v][^$v]#",$s)&&print"$s\n"; saves you 1 char. Sadly you have to change echo to print to use &&. Replacing \n with a real line break saves another. \$\endgroup\$ – Christoph Jan 13 '17 at 11:04
  • 1
    \$\begingroup\$ you might save some chars using "#([^$v][$v]){2}​[^$v]#" but I haven't tested it. \$\endgroup\$ – Christoph Jan 13 '17 at 13:08
  • 1
    \$\begingroup\$ @Christoph: Idk why, but ([^$v][$v]​){2}[^$v] does not work in the loop, while [^$v]([$v]​[^$v]){2} does. Both work standalone (even with the variable) though. \$\endgroup\$ – Titus Jan 13 '17 at 14:01
6
\$\begingroup\$

MATL, 21 bytes

11Y2'y'h2Y2X~6Myyy&Z*

Try it online! (but output is truncated).

11Y2   % Push 'aeiou' (predefined literal)
'y'    % Push 'y'
h      % Concatenate: gives 'aeiouy'
2Y2    % Push 'abcdefghijklmnopqrstuvwxyz' (predefined literal)
X~     % Set symmetric difference: gives 'bcdfghjklmnpqrstvwxz'
6M     % Push 'aeiouy' again
yyy    % Duplicate the second-top element three times onto the top. The stack now
       % contains 'bcdfghjklmnpqrstvwxz', 'aeiouy', 'bcdfghjklmnpqrstvwxz',
       % 'aeiouy', 'bcdfghjklmnpqrstvwxz'
&Z*    % Cartesian product of all arrays present in the stack. Implicity display
\$\endgroup\$
  • \$\begingroup\$ I think this should work, shaving a byte: 11Y2'y'h2Y2yX~yyy&Z* (Try it online!) \$\endgroup\$ – Conor O'Brien Jan 12 '17 at 16:45
  • \$\begingroup\$ @ConorO'Brien Unfortunately, that creates the vcvcv pattern, not cvcvc as required. Thanks though! \$\endgroup\$ – Luis Mendo Jan 12 '17 at 16:55
6
\$\begingroup\$

Python, 92 bytes

f=lambda i=-4,s='':i*[s]or sum([f(i+1,s+c)for c in i%2*'AEIOUY'or'BCDFGHJKLMNPQRSTVWXZ'],[])

Can't let itertools win out. Iterative is 1 byte longer in Python 2.

W='',
for s in(['AEIOUY','BCDFGHJKLMNPQRSTVWXZ']*3)[1:]:W=[w+c for w in W for c in s]
print W
\$\endgroup\$
  • \$\begingroup\$ This is awesome ^_^ \$\endgroup\$ – ABcDexter Jan 13 '17 at 9:09
6
\$\begingroup\$

Haskell, 54 51 bytes

l="bcdfghjklmnpqrstvwxz":"aeiouy":l
mapM(l!!)[0..4]

mapM func list builds all words by taking the possible characters for index i from the list returned by func (list!!i).

Edit: @xnor found 2 bytes to save and looking at his solution, I found another one.

\$\endgroup\$
  • \$\begingroup\$ mapM id$take 5$cycle["bcdfghjklmnpqrstvwxz","aeiouy"] saves a byte. \$\endgroup\$ – xnor Jan 12 '17 at 21:47
  • \$\begingroup\$ Better yet, mapM(cycle["bcdfghjklmnpqrstvwxz","aeiouy"]!!)[0..4] or mapM(["bcdfghjklmnpqrstvwxz","aeiouy"]!!)[0,1,0,1,0]. It would be nice not to hardcode the vowels and consonants, but mapM(\n->[x|x<-['a'..'z'],elem x"aeiou"==odd n])[0..4] doesn't quite make it. \$\endgroup\$ – xnor Jan 12 '17 at 21:55
  • \$\begingroup\$ @xnor: Thanks! Replacing cycle from your first variant with explicit recursion saves an additional byte. \$\endgroup\$ – nimi Jan 13 '17 at 1:03
5
\$\begingroup\$

Brachylog, 18 bytes

@W:@Dg:2jcb:eac@w\

Try it online!

Explanation

@W:@D                 The list ["aeiouy", "bcdfghjklmnpqrstvwxz"]
     g:2jcb           The list ["bcdfghjklmnpqrstvwxz", "aeiouy", "bcdfghjklmnpqrstvwxz", "aeiouy", "bcdfghjklmnpqrstvwxz"]
           :ea        Take one character of each string
              c       Concatenate into a single string
               @w     Write to STDOUT followed by a newline
                 \    Backtrack: try other characters of the string
\$\endgroup\$
  • \$\begingroup\$ I was surprised at the need for the g and b, but testing it, this is because j seems to refuse to take a list of strings as input? :ea really shows off the strengths of Prolog/Brachylog, though, and is a step that most other languages find much more difficult. \$\endgroup\$ – user62131 Jan 12 '17 at 18:46
  • \$\begingroup\$ @ais523 Yes, I was also suprised that the g and b were needed. j seems to be bugged and this is due once again to the difficulty of distinguishing a list of arguments from just a list. I might fix this though this will once again complexify the implementation. I might as well just not fix it and invest my time on fixing the core problem in a new version of Brachylog. \$\endgroup\$ – Fatalize Jan 13 '17 at 9:26
5
\$\begingroup\$

JavaScript (ES6), 91 90 bytes

f=(s='',i=4)=>{for(c of i%2?'aeiouy':'bcdfghjklmnpqrstvwxz')i?f(s+c,i-1):console.log(s+c)}

Edits

  • ETHproductions: -1 byte by removing extraneous group around ternary operator in for statement

Explanation

This defines a 5-deep recursive function that uses the parity of its depth of call to determine whether to iterate vowels or consonants. On each iteration, it checks to see whether to recurse or print by checking the amount of recursions left, and concatenates the letter of its current iteration to the end of the 5 character string that is currently being built depth-first.

Alternative 89 byte solution assuming ISO8859-1 encoding:

f=(s='',i=4)=>{for(c of i%2?'aeiouy':btoa`mÇ_äi骻-¿s`)i?f(s+c,i-1):console.log(s+c)}

Alternative 96 byte solution that returns entire output as single string:

f=(s='',i=4,o='')=>eval("for(c of i%2?'aeiouy':'bcdfghjklmnpqrstvwxz')o+=i?f(s+c,i-1):s+c+`\n`")

Run at your own risk. For the 91 byte solution, just use f() and for the 97 byte alternative, use console.log(f()).

\$\endgroup\$
  • \$\begingroup\$ I tried turning the solution into a generator in two different ways. Using the shorthand form supported only by Firefox is the same length: f=(s='',i=2)=>(for(c of(i%2?'aeiouy':'bcdfghjklmnpqrstvwxz'))for(q of i?f(s+c,i-1):[s+c])q) Using the standard form is unfortunately a byte longer: function*f(s='',i=2){for(c of(i%2?'aeiouy':'bcdfghjklmnpqrstvwxz'))yield*i?f(s+c,i-1):[s+c]} Still waiting for the day when a generator is the shortest option... \$\endgroup\$ – ETHproductions Jan 12 '17 at 19:30
  • 1
    \$\begingroup\$ btw, you can remove the inner parens in the for...of statement to save a byte \$\endgroup\$ – ETHproductions Jan 12 '17 at 19:30
5
\$\begingroup\$

C, 201 199 186 184 183 169 163 bytes

Doing it a bit differently than with the previous basic counting method:

f(){for(char*c="bcdfghjklmnpqrstvwxz",*v="aeiouy",i[5]={0},*s[]={c,v,c,v,c},j=0;j<5;puts("")){for(j=5;j--;putchar(s[j][i[j]]));for(;j++<5&&!s[j][++i[j]];i[j]=0);}}

Ungolfed:

f() {
    for(char *c="bcdfghjklmnpqrstvwxz", *v="aeiouy", i[5]={0}, *s[]={c,v,c,v,c}, j=0; j<5; puts("")) {
        for (j=5; j--; putchar(s[j][i[j]])) ;
        for (; j++ < 5 && !s[j][++i[j]]; i[j]=0) ;
    }
}

And written in a bit more conventional way:

f() {
    char *c="bcdfghjklmnpqrstvwxz", *v="aeiouy", i[]={0,0,0,0,0}, *s[]={c,v,c,v,c}, j=0;
    while (j>=0) {
        for (j=0; j<5; j++) putchar(s[j][i[j]]); // output the word
        while (--j>=0 && !s[j][++i[j]]) i[j]=0; // increment the counters
        puts("");
    }
}

Basically, i are the counters, and s the array of strings containing all the chars over which we should iterate, for each counter. The trick is the inner while loop: it is used to increment the counters, starting from the rightmost one. If we see that the next character we should display is the ending null char, we restart the counter to zero and the "carry" will be propagated to the next counter.

Thanks Cristoph!

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ – Martin Ender Jan 13 '17 at 10:50
  • 1
    \$\begingroup\$ char *c I think the space is unnecessary. \$\endgroup\$ – Christoph Jan 13 '17 at 12:09
  • 1
    \$\begingroup\$ f(){char*c="bcdfghjklmnpqrstvwxz",*v="aeiouy",i[]={0,0,0,0,0},*s[]={c,v,c,v,c},j=0;while(j>=0){for(j=0;j<5;++j)putchar(s[j][i[j]]);for(;--j>=0&&!s[j][++i[j]];)i[j]=0;puts("");}} gets you to 177. Come on you can do even better ;). \$\endgroup\$ – Christoph Jan 13 '17 at 12:21
  • 2
    \$\begingroup\$ Using i[5]={0} instead of i[]={0,0,0,0,0} saves 7 bytes. \$\endgroup\$ – Falken Jan 13 '17 at 12:24
  • 1
    \$\begingroup\$ @Christoph Aha, thanks. Good job. But you seemed to enjoy it, that's why I was pushing the challenge (no, I'm kidding: I did that just because I'm a pain in the ass). Seriously, thanks for the enlightenments. \$\endgroup\$ – dim Jan 13 '17 at 13:47
4
\$\begingroup\$

Perl, 71 bytes

map{push@{1+/[aeiouy]/},$_}a..z;$"=",";say for glob"{@1}{@2}"x2 ."{@1}"

Try it online!

Explanation

I'll add more explanations later.

map{push@{1+/[aeiouy]/},$_}a..z; creates two arrays: @1 contains the consonants, and @2 contains the vowels.
glob when call with arguments like {a,b}{c,d} returns all permutations of the elements in the braces.

\$\endgroup\$
4
\$\begingroup\$

Befunge, 95 bytes

::45*%\45*/:6%\6/:45*%\45*/:6%\6/1g,2g,1g,2g,1g,55+,1+:"}0":**-!#@_
bcdfghjklmnpqrstvwxz
aeiouy

Try it online!, although note that the output will be truncated.

This is just a loop over the range 0 to 287999, outputting the index as a mixed based number 20-6-20-6-20, with the "digits" of the number retrieved from the tables on the last two lines.

\$\endgroup\$
4
\$\begingroup\$

Perl 6, 70 bytes

$_=<a e i o u y>;my \c=[grep .none,"a".."z"];.say for [X~] c,$_,c,$_,c

Explanation of the interesting part:

.say for [X~] c, $_, c, $_, c

              c, $_, c, $_, c  # list of five lists
         [X ]                  # lazily generate their Cartesian product
           ~                   # and string-concatenate each result
.say for                       # iterate to print each result

The code before that just generates the list of vowels ($_) and the list of consonants (c), which is regrettably verbose.

\$\endgroup\$
4
\$\begingroup\$

Python 2, 120 117 bytes

Thanks to @WheatWizard for the tabs tip.

x,y='aeiouy','bcdfghjklmnpqrstvwxz'
for a in x:
 for e in x:
	for b in y:
		for c in y:
			for d in y:print b+a+c+e+d

Try it online!

Not sure that this can be golfed much. Try it online truncates at 128KB but shows enough to give an idea. A local run with debug code to count the words gave a total of 288000. Runs in about 45 seconds if anyone wants to test.

zyzyv
zyzyw
zyzyx
zyzyz
Total word count: 288000

Non-compliant and therefore non-competing version (prints out nested arrays instead of the specified format) for 110 bytes:

x,y='aeiouy','bcdfghjklmnpqrstvwxz'
print[[[[c+a+d+b+e for e in y]for d in y]for c in y]for b in x]for a in x]
\$\endgroup\$
  • 1
    \$\begingroup\$ Was my first implemenation :) \$\endgroup\$ – Carra Jan 12 '17 at 17:14
  • \$\begingroup\$ Instead of using spaces for all your indentation you can use spaces for the single indent and tabs for double. \$\endgroup\$ – Sriotchilism O'Zaic Jan 13 '17 at 1:46
4
\$\begingroup\$

Perl 6, 53 Bytes

/<-[aeiouy]>**3%<[aeiouy]>/&&.say for [...] <a z>Xx 5

Takes a little time to have any output. Very inefficient. Does the job.

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ – Martin Ender Jan 13 '17 at 11:05
4
\$\begingroup\$

xeger, 49 bytes

([bcdfghj-np-tvwxz][aeiouy]){2}[bcdfghj-np-tvwxz]

Given a regular expression, xeger simply generates all matching strings. In order not to kill the browser, it pauses every 1000 outputs and you need to click to continue, but it'll get there eventually.


Here's a 23-byte version with a bug in ^ fixed:

([:c^y][:v:y]){2}[:c^y]

These are character classes "all lower-case ASCII consonants" [:c] with y excluded ^y, and "all lower-case ASCII vowels" [:v:] with y added.

\$\endgroup\$
  • \$\begingroup\$ What regex flavour is this based on? (Or if you rolled your own, what features does it support? Is there any documentation on this?) \$\endgroup\$ – Martin Ender Jan 13 '17 at 10:10
  • \$\begingroup\$ @MartinEnder It's a roll-your-own from DFA traversal (grown from a DFA/NFA visualiser I built for students, which has some limited documentation) - no backreferences, nothing non-regular. It's very slow for longer strings. The only interesting feature of the expressions themselves is conjunction with &. \$\endgroup\$ – Michael Homer Jan 13 '17 at 20:35
  • \$\begingroup\$ I added documentation of the rest to the page, and some samples. \$\endgroup\$ – Michael Homer Jan 13 '17 at 22:02
  • 1
    \$\begingroup\$ Looks like you've implemented ranges in character classes. Then you could do [bcdfghj-np-tvwxz]. \$\endgroup\$ – Martin Ender Jan 14 '17 at 9:37
4
\$\begingroup\$

JavaScript (Firefox 30-57), 82 bytes

f=(i=5)=>i?[for(s of f(i-1))for(c of i%2?'bcdfghjklmnpqrstvwxz':'aeiouy')s+c]:['']

Returns an array of strings. Very fast version for 102 101 (1 byte thanks to @ETHproductions) bytes:

_=>[for(i of c='bcdfghjklmnpqrstvwxz')for(j of v='aeiouy')for(k of c)for(l of v)for(m of c)i+j+k+l+m]
\$\endgroup\$
  • \$\begingroup\$ Nice. There's an extraneous space in the fast version which can be removed for 101 bytes \$\endgroup\$ – ETHproductions Jan 13 '17 at 17:06
3
\$\begingroup\$

CJam, 32 31 29 28 bytes

Saved 2 bytes thanks to Martin Ender and 1 byte thanks to kaine

"aeiouy"_'{,97>^\1$1$1$N]:m*

Try it online! (Note that the output gets cut off on TIO)

Explanation

"aeiouy"_ e# Push the six vowels and duplicate
'{,97>    e# Push the whole alphabet
^         e# Symmetric set difference of the alphabet with the vowels, yields the consonants only
\         e# Swap top two elements
1$1$1$    e# Copy the second-from-the-top string to the top three times
          e# This results in the array being consonants-vowels-consonants-vowels-consonants
N         e# Add a newline character to the end of the list
]         e# End an array. Puts everything done so far in an array
          e# since there was no explicit start of the array.
:m*       e# Reduce the array using Cartesian products
\$\endgroup\$
  • \$\begingroup\$ '{,97> to get the alphabet. And then "aeiouy"_'{,97>^ to save another byte on 1$. \$\endgroup\$ – Martin Ender Jan 12 '17 at 15:42
  • \$\begingroup\$ you don't need the very first character. It is assumed if it gets to start of the stack. \$\endgroup\$ – kaine Jan 12 '17 at 18:04
  • \$\begingroup\$ @kaine Interesting, didn't know that. Thanks. \$\endgroup\$ – Business Cat Jan 12 '17 at 18:30
  • \$\begingroup\$ $"aeiouy"_'{,97>^]3*(;:m*N*$ ignore the $ signs. Idk how to put code in comments. \$\endgroup\$ – kaine Jan 12 '17 at 20:55
  • \$\begingroup\$ @kaine Use backticks, like "`". \$\endgroup\$ – Conor O'Brien Jan 15 '17 at 16:45
3
\$\begingroup\$

Stacked, noncompeting, 51 bytes

(consonants:@c vowels:@v c v c)multicartprod$outmap

Pretty simple. Try it here!

\$\endgroup\$
3
\$\begingroup\$

Perl, 63 59 54 bytes

$a="aeiouy";$b="[^$a][$a]"x2;for("a"x5.."z"x5){say if/$b[^$a]/}
$a="aeiouy";$b="[^$a][$a]"x2;/$b[^$a]/&&say for"a"x5.."z"x5

$a=aeiouy;$b="[^$a][$a]"x2;/$b[^$a]/&&say for a.."z"x5

Trying Perl golf for a change.
EDIT: Looks like I've still got much to learn... :)

\$\endgroup\$
  • \$\begingroup\$ Nice one (even if Primo's answer is shorter). You can write the end as /$b[^$a]/&&say for"a"x5.."z"x5 to save a few bytes. Edit: and you can drop the $b and do $a="aeiouy";/([^$a][$a]){2}[^$a]/&&say for"a"x5.."z"x5. \$\endgroup\$ – Dada Jan 12 '17 at 13:11
  • \$\begingroup\$ Also, you don't need the quotes around aeiouy. Also, since your regex checks for 5 characters, you can do a.."z"x5. \$\endgroup\$ – Dada Jan 12 '17 at 19:19
  • \$\begingroup\$ @Dada: Thanks. As someone who uses Perl for normal programming but until now not for golfing, I didn't even think to exploit non-strict mode. That's why I chose $a and $b as variable names, because those don't need to be declared even in strict mode... :) I also use Perl 6 a lot these days, which doesn't even have a non-strict mode. \$\endgroup\$ – smls Jan 13 '17 at 7:05
3
\$\begingroup\$

Scala, 87 86 bytes

val a="aeiouy"
val b='a'to'z'diff a
for(c<-b;d<-a;e<-b;f<-a;g<-b)println(""+c+d+e+f+g)
\$\endgroup\$
  • \$\begingroup\$ You can replace f"$c$d$e$f$g" with ""+c+d+e+f+g to save a byte. \$\endgroup\$ – corvus_192 Jan 13 '17 at 10:18
3
\$\begingroup\$

R, 143 132 bytes

q=letters;v=c(1,5,9,15,21,25);x=list(q[-v],q[v],q[-v],q[v],q[-v]);Reduce(paste0,mapply(function(a,b)rep(a,e=b/20),x,cumprod(sapply(x,length))))

q=letters;v=c(1,5,9,15,21,25);x=list(a<-q[-v],b<-q[v],a,b,a);Reduce(paste0,mapply(function(a,b)rep(a,e=b/20),x,cumprod(lengths(x))))

This is my first go at code golf so I'd welcome any suggestions to chop it down further. So far it's all pretty standard R; the only possibly tricky thing here is that paste0 recycles its arguments to the length of the longest one.

Edit: used assignment trick from rturnbull, replaced sapply(x,length) with lengths.

\$\endgroup\$
  • \$\begingroup\$ Welcome to the site! This looks quite good (I have only programmed a bit in R myself) I would just recommend not including old code in your answer. The edit history is always available so anyone that wishes to can always view it. This is more of a personal stylistic thing so feel free to ignore my opinion. \$\endgroup\$ – Sriotchilism O'Zaic Jan 14 '17 at 2:56
  • \$\begingroup\$ You can brute-force it with function assignments for 114 bytes! \$\endgroup\$ – Punintended Sep 4 at 22:34
3
\$\begingroup\$

R, 111 98 bytes

Added y as a vowel, and golfed off 13 bytes, thanks to @Patrick B.

l=letters
v=c(1,5,9,15,21,25)
apply(expand.grid(C<-l[-v],V<-l[v],C,V,C)[,5:1],1,cat,fill=T,sep="")

We use expand.grid to generate all possible combinations of V and C in a matrix, which we define from the preset variable letters (the alphabet). We reverse the combinations (as the default is for the first variable to rotate the fastest) to ensure alphabetical order. Then we iterate through each row of the matrix, printing each letter to stdout. We use the fill argument to cat to ensure that each word begins on a new line.

\$\endgroup\$
  • \$\begingroup\$ Nice! You can chop this down further to 98 characters (adding 'y' as a vowel, or 95 if not) by using some options in cat and by renaming "letters": l=letters;v=c(1,5,9,15,21,25);apply(expand.grid(C<-l[-v],V<-‌​l[v],C,V,C)[,5:1],1,‌​cat,fill=T,sep="") \$\endgroup\$ – Patrick B. Jan 14 '17 at 2:30
  • \$\begingroup\$ @PatrickB. Thanks! I've incorporated your suggestions. \$\endgroup\$ – rturnbull Jan 16 '17 at 9:23
  • \$\begingroup\$ 86 bytes \$\endgroup\$ – J.Doe Sep 17 '18 at 11:46
2
\$\begingroup\$

Clojure, 101 bytes

(print(apply str(for[V["aeiouy"]C["bcdfghjklmnpqrstvwxz"]a C b V c C d V e C](str a b c d e "\n")))))

Not that exciting...

\$\endgroup\$
2
\$\begingroup\$

Ruby, 65 61 bytes

Completely different approach:

(b=[*?a..?z]-a="aeiouy".chars).product(a,b,a,b){|x|puts x*""}

New things I learned today: the Array#product function

\$\endgroup\$
2
\$\begingroup\$

C 361 bytes

f(){i,j,k,l,m;v[6]={97,101,105,111,117,121};c[25];s=26;for(i=0;i<26;i++)c[i]=97+i;for(i=0;i<26;i++){for(j=0;j<6;j++)if(c[i]==v[j])c[i]+=1;}for(i=0;i<s;i++)for(j=i+1;j<s;){ if(c[i]==c[j]){for(k=j;k<s-1;++k)c[k]=c[k+1];--s;}else ++j;}for(i=0;i<s;i++)for(j=0;j<6;j++)for(k=0;k<s;k++)for(l=0;l<6;l++)for(m=0;m<s;m++)printf("%c%c%c%c%c\n",c[i],v[j],c[k],v[l],c[m]);}

Ungolfed version:

void f()
{   
int i,j, k,l,m;
int s=26;
int v[6]={97,101,105,111,117,121};
int c[s];

for(i=0;i<s;i++)
 c[i]=97+i;
for(i=0;i<s;i++)
{     
  for(j=0;j<6;j++)
    if(c[i]==v[j])
      c[i]+=1;
     }
for(i=0;i<s;i++)
 for(j=i+1;j<s;)
 { if(c[i]==c[j])
  {
    for(k=j;k<s-1;++k)
      c[k]=c[k+1];
      --s;  
  }else
   ++j;  
  }
for(i=0;i<s;i++)
  for(j=0;j<6;j++)
       for(k=0;k<s;k++)
        for(l=0;l<6;l++)
         for(m=0;m<s;m++)       
      printf("%c%c%c%c%c\n",c[i],v[j],c[k],v[l],c[m]);
}

There must be some way to shorten this definitely.

Explanation

  • Stored the integer values of a,e,i,o,u,y in a numerical array,
  • Stored all alphabets in array, if it was a vowel, replaced it with a consonant, so there were duplicate consonant values in the array,
  • Removed duplicate consonant values,
  • Printed all combinations c-v-c-v-c.
\$\endgroup\$
  • \$\begingroup\$ If you could put an ungolfed version that would help immensely. \$\endgroup\$ – SIGSTACKFAULT Jan 12 '17 at 15:35

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.