12

I am trying to get a random year between 1900 and 1980 with Ruby.

So far I have:

puts 'the year was: ' +  1900.to_s + rand(1980).to_s

but this is just adding 1900 and a random number from 0 - 1979 together to look like 19001947.

I think I'm missing something silly but can anyone shed any light?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
AndyNico
  • 863
  • 4
  • 11
  • 17

5 Answers5

29

Ruby 1.9.3

1.9.3p0 :001 > rand(1900..1980)
 => 1946 
1.9.3p0 :002 > rand(1900..1980)
 => 1929 
1.9.3p0 :003 > rand(1900..1980)
 => 1934 
Alex Gusev
  • 491
  • 1
  • 4
  • 11
14

Give this a try

(1900 + rand(81)).to_s

To be clear for passersby

First, there was an issue regarding string concatenation. The original code in the question was concatenating two strings (containing numbers) together. Example:

"1900" + "1920" = "19001920"

Second, there was an issue the range of random numbers being generated. In this case, since we only want a range of 80 years, we want to use rand(81), instead of rand(1980). We then take that result and add it to the base number, which will give us a random number between 1900 and 1980.

Brian Webster
  • 30,033
  • 48
  • 152
  • 225
  • This will generate 1900 (sometimes), but it will never generate 1980. – steenslag May 15 '11 at 23:32
  • you're mistaken about this not being an issue of string catenation: 1900.to_s and rand(80).to_s both evaluate to objects of type string, so the "+" operation is indeed the string overload of "+". This when that's changed to (1900 + rand(80)).to_s, 1900 and the result of rand(80) are numbers, and the resulting sum are then converted to a string. – Charlie Martin May 15 '11 at 23:37
  • @Charlie, I think you read my comment regarding the string incorrectly. My answer states "The original question was concatenating two strings". I believe we are no the same page. Quoting my answer: "First, there was an issue regarding string concatenation." with my intent being to communicate that the question did indeed have two problems, the first being a concatenation issue – Brian Webster May 15 '11 at 23:44
4
puts "The year was #{1900 + rand 81}"
Phrogz
  • 296,393
  • 112
  • 651
  • 745
2

Yes: you're getting the "string catenation" overload of +. Try (1900+rand(80)).to_s

Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
2

Ruby 1.8+

(1900..1980).to_a[rand(80)]
# or little more Rubyistic
(1900..1980).to_a.shuffle.first

Ruby 1.9+

[*1900..1980].sample
fl00r
  • 82,987
  • 33
  • 217
  • 237
  • 1
    The downside to this approach is an intermediate array is created for each element in the range. For a small range it's not a big deal. A large range, say `0..1_000_000_000` could be painful. – the Tin Man May 15 '11 at 22:51
  • @the Tin Man, I think it is overengineering and over optimization. Here is particular issue and I think good solution for this issue :). It is static range (1900..1980) which won't ever grow into something big. And overengineering is evel, I believe. Of course you should understand all downsides of any approach you use, but you never should use "fastest" in perfomance if it is not a goal. – fl00r May 16 '11 at 09:08
  • And yes, I prefer @Phrogz solution, but as far as obvious straight solution was here before I answered, I suggested this just for fun :D – fl00r May 16 '11 at 09:15
  • 1
    @fl00r : because it's inefficient. Instead of calling rand you're creating a possibly huge array, only to call a more complicated random method on it (.sample makes sure no duplicates are returned). – steenslag May 16 '11 at 09:34
  • @steenslag, you're totally right, but all this side effects not a problem for our topic :). – fl00r May 16 '11 at 09:39
  • 1
    "all this side effects not a problem for our topic" I disagree. It's important to provide answers that include the information the OP needs to make good decisions now, and in the future. While your solution does work for this particular question, the OP could get into trouble later because no caveat was given about that particular use. That is important information to pass on and is teaching how to fish. And, as far as over engineering, I consider it defensive programming by avoiding a potential future problem. – the Tin Man May 16 '11 at 22:41
  • @the Tin Man, totally agree that it is good idea to describe all side effects in my answer - my fault. Thanks for discussion – fl00r May 17 '11 at 08:09