Random Samples
Video transcript & code
Sometimes we need to pick a random selection of items. Ruby provides some easy to use tools for this. Some of these tools may be familiar from other programming languages, but Ruby puts some twists on them that may be new to you.
Let's start with the basics. To simply get a random number, we use the rand
method, which is globally available thanks to the Kernel
module.
rand # => 0.05823762482076911
rand # => 0.24481532875262757
rand # => 0.3715421503879194
What sort of random numbers are these? When we don't supply any argument at all, Ruby gives us a floating point number between zero and one. So for instance if we wanted to make a quarter of users lucky winners, we send rand
and see if the output is less than 0.25.
if rand < 0.25
puts "you're a lucky winner!"
end
Very often it's more convenient to work with integers than with floating point numbers. In that case, we can give rand
an integer argument. For instance, we might want to simulate a 6-sided die. In that case, we could give it the argument 6.
rand(6) # => 3
rand(6) # => 3
rand(6) # => 5
When given an integer, rand
will return a random number between zero and one less than the integer. So when given six, the output will always be between zero and five.
But maybe we want to simulate a 6-sided die more literally, and not have to compensate for the zero-base. In that case, we can pass a range to rand, telling it exactly what range of numbers to pick from.
rand(1..6) # => 2
In this case, rand
will pick a number between one and six, inclusive.
A lot of times in programs, the reason we want a random number is to help us pick a random element in some collection. For instance, in a recent episode I needed to randomly generate status updates for a feline social media site.
I started with a list of words, but I needed a way to pick random sentences out.
words = %W[meow rowwwwr mew meep purrp ewoo meooooow purrrr ack thpppt
rrrrrrr MEOW mrowr HURRRRK mroooooo ssssst spsss fsst]
If we were working in other programming languages, we'd probably start out something like this: we'd use the random number generator to generate a random array index.
words = %W[meow rowwwwr mew meep purrp ewoo meooooow purrrr ack thpppt
rrrrrrr MEOW mrowr HURRRRK mroooooo ssssst spsss fsst]
words[rand(words.size)] # => "mew"
But Ruby knows this is a common use case, so it provides a shortcut: we can send an array the #sample
message, and it will pick a random element for us.
words = %W[meow rowwwwr mew meep purrp ewoo meooooow purrrr ack thpppt
rrrrrrr MEOW mrowr HURRRRK mroooooo ssssst spsss fsst]
words.sample # => "mrowr"
Even better, #sample
takes an argument, specifying how many elements to pick. So if we want random "sentences" of four words, we can do that:
words = %W[meow rowwwwr mew meep purrp ewoo meooooow purrrr ack thpppt
rrrrrrr MEOW mrowr HURRRRK mroooooo ssssst spsss fsst]
words.sample(4) # => ["mroooooo", "fsst", "mew", "rrrrrrr"]
If we put everything we've learned so far together, we can use #rand
to randomize the number of words we pick from the word list.
words = %W[meow rowwwwr mew meep purrp ewoo meooooow purrrr ack thpppt
rrrrrrr MEOW mrowr HURRRRK mroooooo ssssst spsss fsst]
words.sample(rand(1..5))
# => ["mew", "mroooooo", "meow", "rowwwwr"]
Every time we run this code, we get a random sampling of between one and five words. All we need to do now is stitch them together with #join
.
words = %W[meow rowwwwr mew meep purrp ewoo meooooow purrrr ack thpppt
rrrrrrr MEOW mrowr HURRRRK mroooooo ssssst spsss fsst]
words.sample(rand(1..5)).join(" ")
# => "thpppt purrp meep ewoo rrrrrrr"
There's a lot more to be said about randomness. We should talk about random seeds and security at some point. But what you've seen here today should be enough to get you started easily generating things like randomized test data sets, or probabilities for games. Happy hacking!
Responses