3

I'm looking for a method to generate a invite code. I would prefer the code not looks like garbled text: JakSj12

But rather more like heroku, using a fun word with 3 numbers.

lightspeed131 or happy124, jetski99

How can I build a method that takes a list of words, maybe 100? and randomly assigns 3 numbers to them?

Thanks

5 Answers 5

3

Other answers given here are a bit slow, since they shuffle their lists on every call. Here's something a bit faster:

def wordwithnumber(words)
   words[rand(words.length)]+(rand(900)+100).to_s()
end

wordwithnumber(["lightspeed", "happy", "jetski"])

This gives you three digits every time, if you want a number from 0 to 999 modify the rand() call accordingly.

Sign up to request clarification or add additional context in comments.

3 Comments

@AnApprentice, if that's the selected answer then you only wanted one word, the question said "assigns 3 numbers to them", I guess you meant "to it".
@rwat Note that as of Ruby 1.9 you can use words.sample in place of words[rand(words.length)].
@Phrogz Cool, that's a handy function I didn't know about :)
2
def random_name(words, number = nil)
  number ||= rand(999)

  words.sample.to_s + number.to_s # concatenate a random word and the number
end

# example:
random_name(["lightspeed", "happy"]) # lightspeedXXX, happyXXX (where XXX is a random number)
random_name(["lightspeed", "happy"], 5) # lightspeed5, happy5

3 Comments

You might want that to be rand(899) + 100 if you want guaranteed three digit numbers.
@tadman Yep, +1. However, in the example he provided (heroku), there are numbers which have only two digits, so I inferred that they may be any number, provided they have at max 3 digits.
if you want 3 digits you could also do sprintf("%s%03d", words.sample.to_s, number)
2

Always 3 different numbers? not very efficient but simple:

words.zip((100..999).to_a.shuffle).map(&:join)

If you don't mind getting repeated numbers (I guess not):

words.map { |word| word + 3.times.map { rand(10) }.join }

Or simply in Ruby 1.9:

words.map { |word| word + Random.new.rand(100..999).to_s }

([edit] This generate 100 words with numbers, which is what I understood. )

Comments

1
def random_word_and_number( words, max=999 )
  "%s%0#{max.to_s.length}d" % [ words.sample, rand(max+1) ]
end 

(1..4).map{ random_word_and_number( %w[ foo bar jim jam ] ) }
#=> ["jim048", "bar567", "jim252", "foo397"]

Let's you specify an arbitrary maximum value while ensuring that all answers have the same number of digits.

Comments

1

I would use following (very readable IMHO) solution:

names = %w[tinky\ winky dipsy laa-laa po]

def random_name(names)
  [names, (100..999).to_a].collect(&:sample).join
end

3.times.collect { random_name(names) }
# => ["dipsy147", "dipsy990", "po756"]

More memory friendly solution:

def random_name(names)
  @numbers ||= (100..999).to_a
  [names, @numbers].collect(&:sample).join
end

5 Comments

"Further, the name with the number 100 will always be the first name in the array." - Can you please explain?
That "Further..." statement by me was a mistake on my part. I misread your code. I have deleted my comment and removed my downvote (though there's still no good reason to create a 900-element array just to pick a value randomly).
This dependents of the app/code. In a rake task or other background job, I don't see a problem. And you can even add a cache for the numbers. Will edit my solution.
You're right that the performance and memory will probably be fine, but I don't see why you would go to the effort of (100..999).to_a.sample instead of simply rand(900)+100. Just for readability?
Yes, Ruby is a sexy language for me. Readability is very important, otherwise I would switch back to C or another "ugly" language.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.