17
\$\begingroup\$

In the English language, a surefire way to make a pronounceable nonsense letter combination is to make it entirely out of consonant-vowel pairs, e.g., Wu ko pa ha, or, Me fa ro, consonant first, followed by vowel.

Challenge:

Write a program or function that will, given a user-specified number of letters, create a random name using this principle. It's that simple.

Input:

An integer greater than or equal to 2 which designates the required number of letters in the output. Input can be taken from STDIN, command line arguments, or function arguments.

Output:

A string of the given length containing randomly selected consonant-vowel pairs. It can be printed to STDOUT or closest alternative or returned in the case of a function.

Rules:

  1. Each consonant of the English alphabet should have equal probability of being selected for the first character of each pair, and each vowel of the English alphabet should have equal probability of being selected for the second character of each pair.
  2. Letter pairs may be repeated.
  3. Since this is a name, the first letter must be capitalized.
  4. If the input is odd, a randomly selected letter pair in the name should have y or h appended to the end. The choice of y or h should be random as well.
  5. Standard loopholes are not permitted.
  6. Smallest code in bytes wins.

Letter definitions:

Consonants:

bcdfghjklmnpqrstvwxyz

Vowels:

aeiou

Example I/O:

Input: 6
Output: Mefaro

Input: 9
Output: Wukohpaha

Enjoy!

\$\endgroup\$
11
  • 3
    \$\begingroup\$ And by the way, welcome to Programming Puzzles and Code Golf.SE :) \$\endgroup\$ Jul 7, 2015 at 2:29
  • \$\begingroup\$ I think my new format is more clear. Is it? @trichoplax \$\endgroup\$
    – jman294
    Jul 7, 2015 at 15:19
  • 1
    \$\begingroup\$ I post all my potential questions in the sandbox where they can get plenty of feedback before posting here. It makes things easier - I recommend it for future questions. \$\endgroup\$ Jul 7, 2015 at 16:31
  • \$\begingroup\$ Thanks, @alex, Since this is my first question, I now know some good technique on how to use this site. I have learned a lot, and I hope my next question will be better! \$\endgroup\$
    – jman294
    Jul 7, 2015 at 17:04
  • 1
    \$\begingroup\$ @ASCIIThenANSI Per rule #4, a randomly selected letter pair will get a y or h. In that example, it was ko that got the h, not ha. jman: If that's not what you had in mind, better modify the rules quick before more answers start coming in! \$\endgroup\$
    – Alex A.
    Jul 7, 2015 at 17:46

15 Answers 15

7
\$\begingroup\$

Pyth, 33 bytes

rsXOtQmO*-GJ"aeiou"J/Q2*%Q2O"hy"4

Demonstration.

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

JavaScript ES6, 187 180 168 bytes

f=l=>{r=m=>Math.random()*m|0
d=l%2&&r(--l/2)*2+1
for(s='';l--;s+=s?a:a.toUpperCase())a=l%2?'bcdfghjklmnpqrstvwxyz'[r(21)]:'aeiou'[r(5)]+(l==d-1?'hy'[r(2)]:'')
return s}

Edit: I switched from using regex replace to a simple for loop, which improved the length considerably. Ungolfed code and test UI below. Input a negative number at your own risk because it makes an infinite loop. (Thanks to unclemeat for pointing that out.)

f=function(l){
  // Function to return a random integer between 0 and m-1 inclusive
  r=function(m){
    return Math.random()*m|0
  }
  // d is the position the h or y will be added
  // l is decremented only if l is odd so an extra consonant won't be added to the end
  d=l%2&&r(--l/2)*2+1
  
  for(s='';l--;){
    a=l%2?'bcdfghjklmnpqrstvwxyz'[r(21)]:'aeiou'[r(5)]+(l==d-1?'hy'[r(2)]:'')
    // If `s` is empty (i.e. this is the first leter), make it uppercase
    s+=s?a:a.toUpperCase()
  }
  return s
}

run=function(){ip=parseInt(document.getElementById('input').value);if(ip<2)return alert('Input must be greater than one.');document.getElementById('output').innerHTML=f(ip)};document.getElementById('run').onclick=run;run()
<input type="number" id="input" value="7" min="2" /><button id="run">Run</button><br />
<pre id="output"></pre>

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Note: Do not put a negative number into the test UI.. \$\endgroup\$
    – unclemeat
    Jul 8, 2015 at 1:51
5
\$\begingroup\$

SWI-Prolog, 286 285 bytes

a(I):-a(I,[]).
a(I,R):-(I=1,r(1,K),nth0(K,`hy`,V),length(R,L),random(1,L,W),nth0(W,[O:P|Q],V:0xFEFF,R);I=0,[O:P|Q]=R),N is O-32,p([N:P|Q]);r(5,A),nth0(A,`aeiou`,X),r(21,B),nth0(B,`bcdfghjklmnpqrstvwxyz`,Y),J is I-2,a(J,[Y:X|R]).
p([A:B|R]):-put(A),put(B),p(R);!.
r(I,R):-random(0,I,R).

Example: a(13). outputs Leqihsekeqira.

Note: You might need to replace the ` with " if you have an old version of SWI-Prolog.

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

Pyth, 52 42 bytes

V/Q2=k++kO-GJ"aeiou"OJ;rs.SXZck2*%Q2O"hy"4

You can try it in the online compiler here.

Thanks to Jakube for golfing it down further, NinjaBearMonkey for clarifying the challenge, and issacg for creating Pyth and inadvertently teaching me about X.

This program randomly selects a consonant and a vowel to fill the string, adds 'h' or 'y' to one pair if the input is odd, then capitalizes the first character. Here is the breakdown:

V/Q2                                              For N in range(1, input/2):
    =k                                            Set k to:
        k                                         k (defaults to ""),
       + O G                                      plus a random letter from the alphabet... 
          - J"aeiou"                              without the vowels,
      +             OJ                            plus a random vowel
                      ;                           End the loop
                             ck2                  Chop k into strings of length 2
                           XZ                     Append to the first string:
                                    O"hy"         'h' or 'y' picked at random,
                                *%Q2              repeated input mod 2 times
                         .S                       Shuffle the strings
                        s                         Convert them back to a single string
                       r                 4        Capitalize and print the string

It seems inefficient to append 'h' or 'y' to the first consonant-vowel pair and then scramble the list. I tried appending to a random pair but the code was always longer than this.

\$\endgroup\$
6
  • \$\begingroup\$ Pyth, and the coders who know it, always amaze me. \$\endgroup\$
    – jman294
    Jul 7, 2015 at 19:12
  • 1
    \$\begingroup\$ Just a few tricks: rX1 capitalizes X. t is the same thing as _P_. \$\endgroup\$
    – Jakube
    Jul 7, 2015 at 19:29
  • 1
    \$\begingroup\$ You can remove the assignment to J, since you use J only once. \$\endgroup\$
    – Jakube
    Jul 7, 2015 at 19:30
  • 2
    \$\begingroup\$ I think this adds h or y to the end, not a randomly selected pair. \$\endgroup\$ Jul 7, 2015 at 19:31
  • \$\begingroup\$ @Jakube Thanks once again for your help! \$\endgroup\$ Jul 7, 2015 at 21:56
3
\$\begingroup\$

Perl, 253 238 bytes

@c=split"","bcdfghjklmnpqrstvwxyz";@v=split"","aeiou";@t=();chomp($n=<>);for(1..$n/2){$l=$c[$$=rand(21)];if($_<2){$l=uc$l};push@t,$l.$v[$$=rand(5)]};$x=0;$y=int(rand(@t));for(@t){print;if($x==$y&&$n%2>0){print qw(h y)[int(rand(1))]};$x++}

I can probably golf it further, but this should do for now.

Changes:

  • Saved 10 bytes by myself, and 5 thanks to Alex A.
\$\endgroup\$
0
3
\$\begingroup\$

Julia, 141 bytes

n->(R=rand;r=isodd(n)?R(1:n÷2):0;ucfirst(join([string("bcdfghjklmnpqrstvwxyz"[R(1:21)],"aeiou"[R(1:5)],i==r?"yh"[R(1:2)]:"")for i=1:n÷2])))

This creates an unnamed lambda function that accepts an integer as input and returns a string. it takes advantage of the fact that strings in Julia can be indexed and referenced like character arrays. To call it, give it a name, e.g. f=n->....

Ungolfed + explanation:

function f(n)
    # There will be n÷2 consonant-vowel pairs
    p = n ÷ 2

    # Determine which pair will get a y or h, if any
    r = isodd(n) ? rand(1:p) : 0

    # Consonants and vowels
    c = "bcdfghjklmnpqrstvwxyz"
    v = "aeiou"

    # Randomly select letters for pairs, appending y or h as needed
    s = [string(c[rand(1:21)], v[rand(1:5)], i == r ? "yh"[rand(1:2)] : "") for i in 1:p]

    # Join s into a string and convert the first letter to uppercase
    ucfirst(join(s))
end

Examples:

julia> f(9)
"Luyvunize"

julia> f(2)
"Fe"

julia> f(16)
"Pahonapipesafuze"
\$\endgroup\$
3
\$\begingroup\$

Marbelous, 203 bytes

}0}0@1
>>^0&1
--=0@1FF
??&0}0&0
&1
qqqqqq\\\\
//\\pppppp
:p
0000
?K\\?4..}2
<G++<4+5=0\/}0
<B++<3+5?111>1!!
<6++<2+3Mult-2
<3++<1+3+7}2{<
++//mm//mm--
mm..{1..{2{>
{0
:q
}2{2}0
pppppp{0{1
-W
:m
}061
{0{0

Test it out here (online interpreter). Input via arguments. Libraries and cylindrical boards must be enabled.

Commented/readable version:

}0 }0 @1 .. .. # 1st column: generate a number from 0 to length/2-1, wait on &1
>> ^0 &1 .. .. # 2nd column: check bottom bit; if zero activate &1, otherwise &0
-- =0 @1 FF .. # FF (wait on &0): if no h/y, set counter to 255 (0xFF)
?? &0 }0 &0 .. # Send copy of full length to :q
&1 .. .. .. .. 
qq qq qq \\ \\ # Call :q with counter and length
// \\ pp pp pp # Output of :q falls into :p, which is called repeatedly until done

:p                      # prints a consonant/vowel pair, and h/y if needed
00 00 .. .. .. .. .. .. # two zeros, to be passed into ?K and ?4
?K \\ ?4 .. }2 .. .. .. # pass through ?K (0-20 = consonants) and ?4 (0-4 = vowels)
<G ++ <4 +5 =0 \/ }0 .. # 1st/2nd column: add 1-4 to skip vowels
<B ++ <3 +5 ?1 11 >1 !! # 3rd/4th column: add 3/6/11/16 to create nth vowel
<6 ++ <2 +3 Mu lt -2 .. # 5th/6th column: if counter is 0, generate either h or y 
<3 ++ <1 +3 +7 }2 {< .. # 7th/8th column: if length left to print is 0-1, terminate
++ // mm // mm -- .. .. # mm: add 'a'. 1st/2nd start at 'b' (++)
                        #              5th/6th start at 'h' (+7)
mm .. {1 .. {2 {> .. .. # output consonant, vowel, h/y to {0, {1, {2
{0 .. .. .. .. .. .. .. # left input (length left): -2 + output to left
                        # right input (counter until print h/y): -1 + output to right

:q             # calls :p, but with the first letter capitalized
}2 {2 }0 .. .. # {2 is an unused output which prevents exit when all outputs are filled
pp pp pp {0 {1 # call :p, and forward return outputs to MB to start loop
-W .. .. .. .. # subtract W (0x20) from the first letter = capitalize it

:m    # add 0x61 ('a')
}0 61
{0 {0 # input + 0x61 is returned

This is roughly equivalent to the following pseudocode (random(a,b) generates numbers between a and b inclusive):

main(length)
    if length & 0x01 == 0 then
        counter, length_left = q(0xFF, , length)
    else
        counter, length_left = q(random(0, (length >> 1) - 1), , length)
    end
    while true do
        length_left, counter, consonant, vowel, hy = p(length_left, , counter) 
        print consonant, vowel, hy
    end
p(length_left, , counter)
    if length_left <= 1 then terminate_program end
    consonant = random(0, 20)
    switch consonant
        case >16: ++consonant
        case >11: ++consonant
        case >6:  ++consonant
        case >3:  ++consonant
    ++consonant
    consonant = m(consonant)
    vowel = random(0, 4)
    switch vowel
        case >4: vowel += 5
        case >3: vowel += 5
        case >2: vowel += 3
        case >1: vowel += 3
    vowel = m(vowel)
    if counter == 0 then
        hy = random(0, 1) * 0x11
        hy += 7
        hy = m(hy)
    return length_left - 2, counter - 1, consonant, vowel, hy
q(counter, , length_left)
    length_left, counter, consonant, vowel, hy = p(length_left, , counter)
    print consonant - 0x20, vowel, hy
    return counter, length_left
m(number)
    return number + 'a'
\$\endgroup\$
3
\$\begingroup\$

Python 2, 148 169 156

from random import*
I=input()
R=choice
i=I/2
S=[R('hybcdfgjklmnpqrstvwxz')+R('aeiou')for _ in[0]*i]
if I%2:S[R(range(i))]+=R('hy')
print ''.join(S).title()

Edit: Realized it didn't capitalize the first letter. Ill see if I can golf it back down tomorrow.
Edit 2: Remembered .title but I think that will be it.

\$\endgroup\$
1
  • \$\begingroup\$ If only strings supported item assignment... \$\endgroup\$
    – mbomb007
    Jul 8, 2015 at 21:48
3
\$\begingroup\$

SmileBASIC 2 (Petit Computer), 197 177 bytes

CONTEMPORARY EDIT MAY 2018: This was my first submission ever, nearly 3 years ago! My skills have improved a lot since then; -20 just from minor adjustments.

It starts with a prompt (it's left blank to save bytes, so it's just a ?) where you put in the length (stored in variable L).

C$="bcdfgjklmnpqrstvwxzhyaeiou"INPUT L
J=0 OR L/2K=-1IF L%2THEN K=RND(J)
FOR I=0TO J-1?CHR$(ASC(MID$(C$,RND(21),1))-32*!I)+MID$(C$,RND(5)+21,1)+MID$(C$,RND(2)+19,1)*(K==I);
NEXT

I'm sure participating with an obscure BASIC language is gonna get me nothing but weird looks, but I managed to make it pretty small for BASIC. It takes advantage of SB's weird quirks (like conditionals evaluating to 1 or 0 since there's no boolean type) to eliminate as many bytes as I possibly could have when I wrote this at 3AM.

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

Ruby, 119 bytes

13 bytes for capitalizing...

->n{z=(0...n/2).map{([*(?a..?z)]-v=%w[a e i o u]).sample+v.sample}
n.odd?&&z[rand n/2]+='yh'[rand 2]
(z*'').capitalize}

Usage:

f=
->n{z=(0...n/2).map{([*(?a..?z)]-v=%w[a e i o u]).sample+v.sample}
n.odd?&&z[rand n/2]+='yh'[rand 2]
(z*'').capitalize}

2.upto(20) do |i|
  puts f[i]
end

Output:

Qo
Gah
Gilu
Baygu
Tevaba
Rohyori
Jigupadi
Diguvareh
Bidifenaji
Xohsuyileze
Depixoyizili
Boqizurejupiy
Buhuboketedasa
Vuwuhojetayduno
Forigikedawojawe
Qacetihxiheciyaju
Zoqigafukedugusoku
Bavuhlarofetucebapi
Zusiraxoxureqimavugo
\$\endgroup\$
1
\$\begingroup\$

C, 219 characters

Seems to work, I'm still new to this.

char o[]="aeiouqwrtypsdfghjklzxcvbnm";n,i=0;main(int h,char**v){n=atol(v[1]);srand(time(0));h=n%2;for(;i<n-n%2;i+=2)printf("%c%c%c",o[rand()%21+5]-(i?0:32),o[rand()%5],(rand()%(n-1)<(i+2)&h)?h=0,'h'+(rand()%2?17:0):0);}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ You need rand()%(n-1-i)<2 instead of rand()%(n-1)<(i+2) to get a uniform distribution, unless you generate this random number only once and save it somewhere. \$\endgroup\$
    – jimmy23013
    Jul 7, 2015 at 21:13
  • \$\begingroup\$ Is each character a byte, or how many bytes it it? \$\endgroup\$
    – jman294
    Jul 7, 2015 at 22:12
  • \$\begingroup\$ @jman294 Because the ASCII alphabet uses 8 bits per character, a character is one byte. You only really need to use bytes if you are using non-ASCII characters like 🙋 which uses more than one byte. \$\endgroup\$
    – Beta Decay
    Jul 8, 2015 at 6:23
1
\$\begingroup\$

R, 166 bytes

Takes input from STDIN and outputs to STDOUT.

l=letters;s=sample;n=scan();v=c(1,5,9,15,21);o=rbind(s(l[-v],i<-n/2),s(l[v],i,T));if(n%%2)o[a]=paste0(o[a<-s(i,1)*2],s(c('h','y'),1));o[1]=toupper(o[1]);cat(o,sep='')

Explanation

# Alias letters and sample
l=letters;
s=sample;
# Get input
n=scan();
# Vowel positions
v=c(1,5,9,15,21);
# Create a matrix with a row of 
# consonants and a row of vowels 
o=rbind(s(l[-v],i<-n/2),s(l[v],i,T));
# If odd paste either h or y to a vowel
if(n%%2)o[a]=paste0(o[a<-s(i,1)*2],s(c('h','y'),1));
# Upper case first letter
o[1]=toupper(o[1]);
# Output
cat(o,sep='')

Some tests

> l=letters;s=sample;n=scan();v=c(1,5,9,15,21);o=rbind(s(l[-v],i<-n/2),s(l[v],i,T));if(n%%2)o[a]=paste0(o[a<-s(i,1)*2],s(c('h','y'),1));o[1]=toupper(o[1]);cat(o,sep='')
1: 13
2: 
Read 1 item
Vetigiysurale
> l=letters;s=sample;n=scan();v=c(1,5,9,15,21);o=rbind(s(l[-v],i<-n/2),s(l[v],i,T));if(n%%2)o[a]=paste0(o[a<-s(i,1)*2],s(c('h','y'),1));o[1]=toupper(o[1]);cat(o,sep='')
1: 12
2: 
Read 1 item
Mucowepideko
\$\endgroup\$
1
\$\begingroup\$

K5, 131 bytes

{r:(`c$-32+c@1?#c),{*d@1?#d:(v;(c::(`c$97+!26)^v::"aeiou"))@2!x}'1+1_!x;$[x=p:2*_x%2;r;,/(*w),("yh"@1?2),*|w:(0,2+2**1?_(#r)%2)_r]}

This will NOT work on Kona or kdb+; you need to use a K5 interpreter like oK.

Live demo. (Try setting the 5 at the end to a different number to try different inputs.)

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

Ruby, 316 238 216 chars

v=%w{a e i o u};c=[];(?a..?z).map{|i|v.include?(i)||c.push i};combos=[];c.map{|i| v.map{|j| combos.push i+j}};i=gets.to_i;o="";(i/2).times{o+=combos.sample};if i%2==1;(rand(4)==1?o+=?y:o+=?h); end; puts o.capitalize;

Odd number combos end in h or y.

Thanks to @blutorange for a complete dictionary of ruby golfing tips.

Whoa, I shortened my code by 100 chars.

\$\endgroup\$
3
  • \$\begingroup\$ The extra combos are unnecessary. I think some of the whitespace in there is unnecessary as well. Maybe take a look at some tips for golfing in Ruby to help shorten your code. Also, does this take input? \$\endgroup\$
    – Alex A.
    Jul 7, 2015 at 18:52
  • \$\begingroup\$ Yes, it takes input, the extra combos were neccessary for extra points before the question got redone, and I thought they would still work. j was a typo. \$\endgroup\$
    – clapp
    Jul 7, 2015 at 19:19
  • \$\begingroup\$ Just a few tricks with ruby: for i in ?a..?z;...;end can be replaced with (?a..?z).map{...}; The then after if is optional. v.include?(i)||c.push(i) is short for unless v.include?(i);c.push(i). Use c<<i for c.push(i). c.map{} is shorter than c.each{}. i%2==1?1:2 is short for if i%2==1;1;else;2;end. The print "Enter..." is not needed in codegolf ; ) \$\endgroup\$
    – blutorange
    Jul 8, 2015 at 7:33
1
\$\begingroup\$

Perl 5, 112 bytes

@;=map{(grep aeiou!~$_,a..z)[rand 21].(a,e,i,o,u)[rand 5]}1..$_/2;$_%2?$;[rand@;].=time%2?h:'y':0;$_=$"^join"",@

Try it online!

\$\endgroup\$

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