Cleanest way of fitting an integer in a range [duplicate] - ruby

This question already has answers here:
Ruby Elegant Way to Return Min/Max if Value Outside Range
(8 answers)
Closed 9 years ago.
What's the cleanest way of fitting an integer in a given range in ruby? A method that returns the given range's min or max if the integer it's invoked on exceeds the range.
Does a method like this exist in native ruby?
120.fit(1..100) # => 100
-20.fit(1..100) # => 1
Or maybe there's a nice one liner that does the same?
Edit
To achieve this I now have to do something like:
some_integer = some_range.min if some_integer <= some_range.min
some_integer = some_range.max if some_integer >= some_range.max

Something like this?
class Fixnum
def fit(range)
self > range.max ? range.max : (self < range.min ? range.min : self)
end
end
Usage:
> 5.fit(1..4) #=> 4
> 0.fit(1..4) #=> 1
> 3.fit(1..4) #=> 3

Not confident of being cleanest, but this is a way
(1..100).minmax.push( -50 ).sort[1]
# => 1
(1..100).minmax.push( 120 ).sort[1]
# => 100

r = (1..100)
v = -12
r.include?(v) ? v : ( r.begin > v ? r.begin : r.last)

Related

Float - two digits after comma - how to?

I tried to execute a calculation in Ruby. The result I get is 1589.5833333333333. I would like to limitat the numbers of digits after the comma.
The result should always be limited to 2 digits as followed:
1589.58
Question #1 = how can I set the limitation?
Question #2 = how can I round up 1589.60 or down 1589.55
Many thanks for help. Language is ruby
Other option but keeping the object as Float:
n = 1589.5833333333333
m = n.truncate(2) #=> 1589.58
h = n.round(1) #=> 1589.6 # for the last zero you need to format the string
And a tricky:
k = (n*100).to_i.digits.tap{ |ary| ary.first > 5 ? ary[0] = 5 : ary[0] = 0 }.reverse.join('').to_i/100.0
#=> 1589.55
For question 1:
num = 1589.5833333333333
printf('%.2f', num)
=> 1589.58
For question 2 to round up to first digit:
num = 1589.5833333333333
printf('%.2f', num.round(1))
=> 1589.60
1589.55 is a bit of an arbitrary number, rounding down would usually be calculated as 1589.58. I don't know of any Ruby function that does that off-hand.

Can I implement round half to even?

I need to do round half to even on floats, i.e.,
if the value is half-way between two integers (tie-breaking, fraction part of y is exactly 0.5) round to the nearest even integer,
else, standard round (which is Round to nearest Integer in Ruby).
These are some results, for example:
0.5=>0
1.49=>1
1.5=>2
2.5=>2
2.51=>3
3.5=>4
The BigDecimal class has the rounding mode half to even already implemented. You just have to set the ROUND_MODE to :half_even with BigDecimal.mode method:
require 'bigdecimal'
def round_half_to_even(float)
BigDecimal.mode(BigDecimal::ROUND_MODE, :half_even)
BigDecimal.new(float, 0).round
end
Or by using the round with some arguments:
require 'bigdecimal'
def round_half_to_even(float)
BigDecimal.new(float, 0).round(0, :half_even).to_i
end
Please note that BigDecimal#round returns an Integer when used without arguments, but a BigDecimal when used with arguments. Therefore the need to call to_i in the second example but not in the first.
I would reopen the Float class to create a round_half_to_even function :
class Float
def round_half_to_even(precision)
if self % 1 == 0.5
floor = self.to_i.to_f
return floor % 2 == 0 ? floor : floor + 1
else
return self.round(precision)
end
end
end
def round_half_to_even f
q, r = f.divmod(2.0)
q * 2 +
case
when r <= 0.5 then 0
when r >= 1.5 then 2
else 1
end
end
round_half_to_even(0.5) # => 0
round_half_to_even(1.49) # => 1
round_half_to_even(1.5) # => 2
round_half_to_even(2.5) # => 2
round_half_to_even(2.51) # => 3
round_half_to_even(3.5) # => 4
You could do the following:
def round_half_to_even(f)
floor = f.to_i
return f.round unless f==floor+0.5
floor.odd? ? f.ceil : floor
end
round_half_to_even(2.4) #=> 2
round_half_to_even(2.6) #=> 3
round_half_to_even(3.6) #=> 4
round_half_to_even(2.5) #=> 2
round_half_to_even(3.5) #=> 4

range in an array [duplicate]

This question already has answers here:
how to show all integers of an array in ruby?
(2 answers)
Closed 8 years ago.
I cannot seem to iterate through a range. Here is what I get:
[1..6].to_a.each{ |n|
puts(n)
}
# => [1..6]
This is one iteration without offering each number. Is there any way to make this work?
[1..6] does not define a range. It defines an array with one element that is a range:
[1..6] == (1..6)
# => false
[1..6].class
# => Array
[1..6] == [(1..6)]
# => true
[1..6][0].class
# => Range
The correct syntax to create a range is (1..6):
(1..6).each { |n| puts n }
You can use
6.times { |n| puts n }
if u want to iterate n times
Your one is not working, as you created an array of range of size 1. Now, to make it working you can do as :
[*1..3].each { |n| puts n }
It would output as :
1
2
3
But better in such case, to use
(1..3).each { |n| puts n }
As Range is an enumerable, you can call on it the Range#each method.

Ruby Object Comparable to Fixnum

I'd like to implement a class in Ruby that's comparable (using the <=> operator) with any Fixnum, and vice-versa. This will ultimately be used in a range. Here is an outline of my class:
class N
include Comparable
attr :offset
def initialize(offset = 0)
#offset = offset
end
def succ
N.new(#offset + 1)
end
def +(offset)
N.new(#offset + offset)
end
def <=>(other)
return #offset <=> other.offset if other.kind_of? N
return 1 # N is greater than everything else
end
end
def n; N.new(0); end
Now this works great when used in n..n+2 and n..999, but not in 1..n. This is due to the fact that n <=> 1 works but 1 <=> n does not (returns nil).
Is there any way I can get Fixnum to treat my N class as a comparable object? Your thoughts are appreciated :)
If you want to implement your own number type, you must implement coerce:
class N
def coerce(other)
return N.new(other), self
end
end
n = N.new
1 <=> n # => -1
All of Ruby's builtin number types in the core library, all number types in the standard library, as well as all third-party number types use the coerce protocol to find a common type in order to make operators such as +, * and == commutative and -, / and <=> symmetric.
It's not quite clear to me what the semantics of N should be, so the above implementation is only an example.
Okay, I did a little monkey patching (freedom patching ;) that seems to have solved my problem for now.
class Fixnum
def <=>(other)
return -1 if other.kind_of? N
return -1 if self < other
return 0 if self == other
return 1 if self > other
end
end
Output seems to be as expected and it doesn't break anything in the inner workings of Fixnum as far as I can tell. Any better ideas/comments, feel free to post 'em.
1 <=> n # => -1
1 <=> 1 # => 0
1 <=> 2 # => -1
2 <=> 1 # => 1
1 == 1 # => true
1 == 2 # => false
1 < 2 # => true
1 > 2 # => false

Ruby factorial function

I'm going crazy: Where is the Ruby function for factorial? No, I don't need tutorial implementations, I just want the function from the library. It's not in Math!
I'm starting to doubt, is it a standard library function?
There is no factorial function in the standard library.
Like this is better
(1..n).inject(:*) || 1
It's not in the standard library but you can extend the Integer class.
class Integer
def factorial_recursive
self <= 1 ? 1 : self * (self - 1).factorial
end
def factorial_iterative
f = 1; for i in 1..self; f *= i; end; f
end
alias :factorial :factorial_iterative
end
N.B. Iterative factorial is a better choice for obvious performance reasons.
Shamelessly cribbed from http://rosettacode.org/wiki/Factorial#Ruby, my personal favorite is
class Integer
def fact
(1..self).reduce(:*) || 1
end
end
>> 400.fact
=> 64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
This implementation also happens to be the fastest among the variants listed in Rosetta Code.
update #1
Added || 1 to handle the zero case.
update #2
With thanks and appreciation to Mark Thomas, here's a version that is a bit more efficient, elegant and obscure:
class Integer
def fact
(2..self).reduce(1,:*)
end
end
In math, factorial of n is just the gamma function of n+1
(see: http://en.wikipedia.org/wiki/Gamma_function)
Ruby has Math.gamma() so just use Math.gamma(n+1) and cast it back to an integer if desired.
You could also use Math.gamma function which boils down to factorial for integer parameters.
class Integer
def !
(1..self).inject(:*)
end
end
examples
!3 # => 6
!4 # => 24
I would do
(1..n).inject(1, :*)
I just wrote my own:
def fact(n)
if n<= 1
1
else
n * fact( n - 1 )
end
end
Also, you can define a falling factorial:
def fall_fact(n,k)
if k <= 0
1
else
n*fall_fact(n - 1, k - 1)
end
end
With high respect to all who participated and spent their time to help us, I would like to share my benchmarks of the solutions listed here.
Params:
iterations = 1000
n = 6
user system total real
Math.gamma(n+1) 0.000383 0.000106 0.000489 ( 0.000487)
(1..n).inject(:*) || 1 0.003986 0.000000 0.003986 ( 0.003987)
(1..n).reduce(1, :*) 0.003926 0.000000 0.003926 ( 0.004023)
1.upto(n) {|x| factorial *= x } 0.003748 0.011734 0.015482 ( 0.022795)
For n = 10
user system total real
0.000378 0.000102 0.000480 ( 0.000477)
0.004469 0.000007 0.004476 ( 0.004491)
0.004532 0.000024 0.004556 ( 0.005119)
0.027720 0.011211 0.038931 ( 0.058309)
Just call this function
def factorial(n=0)
(1..n).inject(:*)
end
examples
factorial(3)
factorial(11)
Using Math.gamma.floor is an easy way to produce an approximation and then round it back down to the correct integer result. Should work for all Integers, include an input check if necessary.
Just another way to do it, although it really isn't necessary.
class Factorial
attr_reader :num
def initialize(num)
#num = num
end
def find_factorial
(1..num).inject(:*) || 1
end
end
number = Factorial.new(8).find_factorial
puts number
You will probably find a Ruby feature request useful. It contains a nontrivial patch that includes a demo Bash script. The speed difference between a naive loop and the solution presented in the batch can be literally 100x (hundred fold). Written all in pure Ruby.
Here is my version seems to be clear to me even though it's not as clean.
def factorial(num)
step = 0
(num - 1).times do (step += 1 ;num *= step) end
return num
end
This was my irb testing line that showed each step.
num = 8;step = 0;(num - 1).times do (step += 1 ;num *= step; puts num) end;num
Why would the standard library require a factorial method, when there is a built-in iterator for this exact purpose? It is called upto.
No you do not need to use recursion, like all these other answers show.
def fact(n)
n == 0 ? 1 : n * fact(n - 1)
end
Rather, the built-in iterator upto can be used to calculate factorials:
factorial = 1
1.upto(10) {|x| factorial *= x }
factorial
=> 3628800
class Integer
def factorial
return self < 0 ? false : self==0 ? 1 : self.downto(1).inject(:*)
#Not sure what other libraries say, but my understanding is that factorial of
#anything less than 0 does not exist.
end
end
And yet another way (=
def factorial(number)
number = number.to_i
number_range = (number).downto(1).to_a
factorial = number_range.inject(:*)
puts "The factorial of #{number} is #{factorial}"
end
factorial(#number)
Just one more way to do it:
# fact(n) => Computes the Factorial of "n" = n!
def fact(n) (1..n).inject(1) {|r,i| r*i }end
fact(6) => 720
In Ruby standard library function for factorial is not available. We can make a simple function of factorial in ruby in this way.
def factorial_number(n)
if n <= 1
1
else
n * factorial_number(n-1)
end
end
puts factorial_number(6) #Output is 720 => (6*5*4*3*2*1)
puts factorial_number(8) #Output is 40320 => (8*7*6*5*4*3*2*1)

Resources