Why does random work like this in Ruby? - ruby

I was trying to be clever about deterministically picking random stuff, and found this:
irb(main):011:0> Random.new(Random.new(1).rand + 1).rand == Random.new(1).rand
=> true
irb(main):012:0> Random.new(Random.new(5).rand + 1).rand == Random.new(5).rand
=> false
irb(main):013:0> Random.new(Random.new(5).rand + 5).rand == Random.new(5).rand
=> true
For a second, I thought "wow, maybe that's a property of random number generators", but Python and C# fail to reproduce this.

You’re probably going to be disappointed with this one. Let’s take a look at the output of rand:
irb(main):001:0> Random.rand
0.5739704645347423
It’s a number in the range [0, 1). Random.new accepts an integer seed.
irb(main):002:0> Random.new(5.5) == Random.new(5)
true
Mystery solved!

Related

How to check if a value is included between two other values?

I'm trying to express a condition like this:
if 33.75 < degree <= 56.25
# some code
end
But Ruby gives this error:
undefined method `<=' for true:TrueClass
I'm guessing that one way to do it is something like:
if 33.75 < degree and degree <= 56.25
# code
end
But there is no another, easier way?
Ruby also has between?:
if value.between?(lower, higher)
There are many ways of doing the same things in Ruby.
You can check if value is in the range by use of following methods,
14.between?(10,20) # true
(10..20).member?(14) # true
(10..20).include?(14) # true
But, I would suggest using between than member? or include?. You can find more about it here.
You can express a <= x <= b as (a..b).include? x and a <= x < b as (a...b).include? x.
>> (33.75..56.25).include? 33.9
=> true
>> (33.75..56.25).include? 56.25
=> true
>>
>> (33.75..56.25).include? 56.55
=> false
Unfortunately, there seems no such thing for a < x <= b, a < x < b, ..
UPDATE
You can accomplish using (-56.25...-33.75).include? -degree. But it's hard to read. So I recommend you to use 33.75 < degree and degree <= 56.25.
use between? is the easiest way, I found most answers here didn't mention (ruby doc explanation is hard to understand too), using between? does INCLUDE the min and max value.
for example:
irb(main):001:0> 2.between?(1, 3)
=> true
irb(main):002:0> 3.between?(1, 3)
=> true
irb(main):003:0> 1.between?(1, 3)
=> true
irb(main):004:0> 0.between?(1, 3)
=> false
by the way, ruby doc quote:
between?(min, max) → true or false Returns false if obj <=> min is
less than zero or if anObject <=> max is greater than zero, true
otherwise.
undefined method `<=' for true:TrueClass
means that Ruby is not parsing your if-condition the way you expect it.
Using && and adding parentheses helps!
if (33.75<degree) && (degree<=56.25)
...
end
It's a bad habit to leave out parentheses -- as soon as the expression gets more difficult, you could get a surprising outcome. I've seen this many times in other people's code.
Using and instead of && in Ruby is a very bad idea, see:
https://www.tinfoilsecurity.com/blog/ruby-demystified-and-vs
http://rubyinrails.com/2014/01/30/difference-between-and-and-in-ruby/
You can also use this notation:
(1..5) === 3 # => true
(1..5) === 6 # => false
Adjust value to range?
value = 99
[[value,0].max, 5].min # 5
value = -99
[[value,0].max, 5].min # 0
value = 3
[[value,0].max, 5].min # 3

What does .between? method means in Ruby?

I have a exercise of the school and i can't resolve it. Can you help me?
The problem is this:
Try using a method that takes two arguments - use the between? method
to determine if the number 2 lies between the numbers 1 and 3.
I tried to find what is the .between? method but í couldn't find it.
I just know that is a method
The method is Comparable#between?, and you can use it like this:
2.between?(1, 3)
# => true
use between? is the easiest way, I found most answers here didn't mention (ruby doc explanation is hard to understand too), using between? does INCLUDE the min and max value.
for example:
irb(main):001:0> 2.between?(1, 3)
=> true
irb(main):002:0> 3.between?(1, 3)
=> true
irb(main):003:0> 1.between?(1, 3)
=> true
irb(main):004:0> 0.between?(1, 3)
=> false
by the way, ruby doc quote (too hard to understand for newbie):
between?(min, max) → true or false Returns false if obj <=> min is
less than zero or if anObject <=> max is greater than zero, true
otherwise.
From "between" ruby documentation:
between?(min, max) → true or false
Returns false if obj <=> min is less than zero or if anObject <=> max is greater than zero, true otherwise.
Uh oh, and of course, it's #=== method for ranges:
( 1..3 ) === 2 #=> true
( 1..3 ) === 4 #=> false
You can use Range#cover? as a solution :
(1..3).cover? 2 #=> true

Shorthand for "return x if x" in Ruby

One thing I love about Ruby is that you can express things in the shortest way possible.
I know that one can do, when assigning
x ||= a
# instead of
x = a unless x
# which is
x = x || a
Is there an analog form for return?
# instead of
return x if x
I'm trying to "say" x only once. This question asks about just returning (nothing), but I don't see how to do it when returning something other than void.
I'm just about certain that there exists no shorthand for your second example—nor could one be written without modifying the Ruby syntax—since it's not a common enough idiom. Sorry, bro, but it looks like you're going to have to be verbose on this one. (Though, really, as far as verbosity goes, this one isn't all that bad.)
(Note, too, that the first example isn't quite right: x ||= a is equivalent to x = x || a, which can also be expressed as x = a unless x.)
you can omit the return if it is the last statement in a block code.
example
irb(main):002:0> def b(c)
irb(main):003:1> c if c
irb(main):004:1> end
=> nil
irb(main):005:0> b(4)
=> 4
irb(main):006:0> b(nil)
=> nil
irb(main):007:0> b(true)
=> true
irb(main):008:0> b(false) # TADA!!!
=> nil

How to: Ruby Range that doesn't include the first value

With Ranges in Ruby you can do 0..5 to include all numbers between and including 0 and 5. You can also do 0...5 to include the same numbers except 5 is not included.
(1..5) === 5
=> true
(1...5) === 5
=> false
(1...5) === 4.999999
=> true
Is there a way to exclude the first number instead of the last to get a result like this?
(1...5) === 1
=> false
(1...5) === 1.00000001
=> true
No, there is no built-in support for such a range. You might want to roll your own Range-like class if this behavior is necessary.
Not natively with a Range. You can mess with its mind but you're better off using an incremented first value. This is ugly but:
[(1..5).to_s].map{ |s| a,b=s.split('..').map{|i| i.to_i}; (1+a .. b) } #=> [2..5]
or
Range.new(*[(1..5).to_s].map{ |s| a,b=s.split('..').map{|i| i.to_i}; [1+a,b] }.flatten) #=> 2..5
or
irb(main):004:0> asdf = (1..5)
=> 1..5
irb(main):005:0> Range.new(asdf.min.succ, asdf.max)
=> 2..5
None seem overly elegant.
Besides just sending first_arg.succ instead of first_arg? No, there is no special support for this.
You could monkey patch Range to add a method to behave the way you want. Ex:
class Range
def exclusive()
Range.new(self.first+1, self.last-1)
end
end
(1..5).exclusive === 5
==>false
(1..5) === 5
==>true
Beware of monkeypatching though, as it changes the functionality of existing classes. There is probably a better way to do it in this case, but given the question, this is an acceptable answer.

Type-indifferent comparison in Ruby

I'm sure this is a basic question in Ruby:
Is there a way to check if
a == b
even if a is an integer and b is a string? I realize that I can do
a.to_s == b.to_s
but I'd like to know if there's some other, better way.
I'm not sure that I understand the question. If I do understand it, I think you're trying to slip one by the interpreter:
telemachus ~ $ irb
irb(main):001:0> a = 1
=> 1
irb(main):002:0> b = '1'
=> "1"
irb(main):003:0> a == b
=> false
You can compare 1 and '1' all you like, but they aren't equal according to the way Ruby handles strings and numbers. In a nutshell, Ruby ain't Perl. (Edit: I should clarify. Clearly the number 1 is not the same thing as the string '1'. So it's not really a question of how Ruby handles them. If you compare them directly, they're just not the same. I just meant that Ruby doesn't do automatic conversions the way that Perl would. Depending on what language you come from and your attitude towards typing, this will make you happy or suprised or annoyed or some combination of these.)
What about something like:
class Object
def compare_as_strings(other)
return self.to_s == other.to_s
end
end
I hate extending something that fundamental, but this DOES work...
>> a = 1
=> 1
>> b = "1"
=> "1"
>> a.compare_as_strings(b)
=> true
I haven't run into one, and Rails gets tripped up by this regularly, so I suspect that there's no slick way to do it - you have to force the to_s.

Resources