Can I implement round half to even? - ruby

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

Related

Ruby: Am I using the correct scope?

I come from a JavaScript background and wrote this similar to how I would in javascript. I am writing it in Ruby.
This is a codewars exercise.
n being 0 and 1 returns 0.00 and 1.00 as expected. Every other positive natural number returns 0.
# Task:
# Your task is to write a function which returns the sum of following series upto nth term(parameter).
# Series: 1 + 1/4 + 1/7 + 1/10 + 1/13 + 1/16 +...
# Rules:
# You need to round the answer to 2 decimal places and return it as String.
# If the given value is 0 then it should return 0.00
# You will only be given Natural Numbers as arguments.
# Examples:
# SeriesSum(1) => 1 = "1.00"
# SeriesSum(2) => 1 + 1/4 = "1.25"
# SeriesSum(5) => 1 + 1/4 + 1/7 + 1/10 + 1/13 = "1.57"
def series_sum(n)
sum = 0
if n == 0
return 0.00
elsif n == 1
return 1.00
else
n.times do |i|
if i == 1
sum += 1
break
end
sum += 1/( 1 + (3 * (i - 1)) )
end
end
return sum
end
puts series_sum(0)
puts series_sum(1)
puts series_sum(2)
puts series_sum(4)
puts series_sum(5)
A couple of things to note:
- Ruby has reduce method that can sum up a list of numbers: https://apidock.com/ruby/Enumerable/reduce
- You don't need to explicitly return from your method. Ruby automatically returns the last statement in your method.
I've modified your solution, and this should work:
def series_sum(n)
if n > 1
sum = (1..n).inject { |sum, i| sum + (1/(1.to_f + (3 * (i - 1)))) }
else
sum = n
end
'%.2f' % sum
end
When you are expecting a decimal number in a division, always make sure that either the numerator or the denominator is in float, hence the reason for the 1.to_f.
'%.2f' is a string format to ensure the final answer is returned in 2 decimal places.
There are two parts to this question.
How to display an operation's result as a float value?
1/2 # this will give 0
1.0/2 # this will give 0.5
How to limit a float value to 2 decimal places?
You can use the round function
22.0/7 # this will give pi value - 3.142857142857143
(22.0/7).round(2) # this will give 3.14
The two answers above can be combined to get your answer. I would leave it as an exercise for you to come up with the exact code to solve your problem.
def series_sum(n)
return "0.00" if n.zero?
sprintf("%.2f", (0..n-1).sum { |m| 1.fdiv(3*m+1) }.round(2))
end
series_sum(0) #=> "0.00"
series_sum(1) #=> "1.00"
series_sum(2) #=> "1.25"
series_sum(3) #=> "1.39"
series_sum(4) #=> "1.49"
series_sum(5) #=> "1.57"
See Kernel#sprintf. One could alternatively use String%, which shares sprintf's formatting directives:
"%.2f" % (0..n-1).sum { |m| 1.fdiv(3*m+1) }.round(2)
I am not aware of the existence of a closed-form expression for this partial sum. Though not relevant to the question, this partial sum can be shown to be divergent.

Create a method to find if a number is a power of 2?

I have this code to return true if num is a power of 2.
def is_power_of_two?(num)
result = num.inject(0) {|n1, n2| n2 ** n1}
if result == num
true
else
false
end
end
p is_power_of_two?(16)
I keep getting an error though. How could I fix and simplify this code?
Clearly, n is a non-negative integer.
Code
def po2?(n)
n.to_s(2).count('1') == 1
end
Examples
po2? 0 #=> false
po2? 1 #=> true
po2? 32 #=> true
po2? 33 #=> false
Explanation
Fixnum#to_s provides the string representation of an integer (the receiver) for a given base. The method's argument, which defaults to 10, is the base. For example:
16.to_s #=> "16"
16.to_s(8) #=> "20"
16.to_s(16) #=> "10"
15.to_s(16) #=> "f"
It's base 2 we're interested in. For powers of 2:
1.to_s(2) #=> "1"
2.to_s(2) #=> "10"
4.to_s(2) #=> "100"
8.to_s(2) #=> "1000"
16.to_s(2) #=> "10000"
For a few natural numbers that are are not powers of 2:
3.to_s(2) #=> "11"
5.to_s(2) #=> "101"
11.to_s(2) #=> "1011"
We therefore wish to match binary strings that contain one 1.
Another Way
R = /
\A # match beginning of string ("anchor")
10* # match 1 followed by zero or more zeroes
\z # match end of string ("anchor")
/x # free-spacing regex definition mode
def po2?(n)
(n.to_s(2) =~ R) ? true : false
end
po2?(4) #=> true
po2?(5) #=> false
And one for the road
This uses Fixnum#bit_length and Fixnum#[]:
def po2?(n)
m = n.bit_length-1
n[m] == 1 and m.times.all? { |i| n[i].zero? }
end
po2? 0 #=> false
po2? 1 #=> true
po2? 32 #=> true
po2? 33 #=> false
Try:
def is_power_of_two?(num)
num != 0 && (num & (num - 1)) == 0
end
It is well explained here (for C#, but #GregHewgill's explanation applies here as well)
I would do something like this, using Ruby's Math module.
def power_of_two?(n)
Math.log2(n) % 1 == 0
end
Or, if you wanted to be really cool:
def power_of_two?(n)
(Math.log2(n) % 1).zero?
end
Some IRB output:
2.1.0 :004 > power_of_two?(2)
=> true
2.1.0 :005 > power_of_two?(32768)
=> true
2.1.0 :006 > power_of_two?(65536)
=> true
This method assumes that the input is a positive integer.
Source
Another way to solve this is to go the other way around than most of the answers here - we can use the number 1 to start and find out if the number is the power of two. Like this:
def power_of_two?(num)
product = 1
while product < num
product *= 2
end
product == num
end
We start with 1. Then we multiply the 1 by 2, and keep multiplying by 2 until the product is larger than num (product < num). Once we hit that condition, we stop, exit the loop, and check if it's equal to num (product == num). If it is, the num is the power of 2.
As was pointed out in the comments above, you were getting errors because you're trying to use the inject method on a non-iterable (an int). Here's a solution using the suggested log2
def is_power_of_two?(num)
result = Math.log2(num)
result == Integer(result)
end
Note: will fail with very big numbers close to binaries (like 2 ^ 64 - 1). A foolproof version (but slower) would be:
def is_power_of_two?(num)
while (num % 2 == 0 and num != 0)
num /= 2
end
num == 1
end
Please comment any improvements that any of you may find.
Here is another solution that uses recursion:
def power_of_2?(number)
return true if number == 1
return false if number == 0 || number % 2 != 0
power_of_2?(number / 2)
end
In my opinion, the easiest -- but maybe a little long -- way of doing what you need to do is just writing this recursive method like so:
def power_of_two?(number)
continue = true
if number == 1
return true
end
if number % 2 != 0
return false
else
while continue == true do
if number.to_f / 2.0 == 2.0
continue = false
return true
else
if number % 2 != 0
continue = false
return false
else
number /= 2
continue = true
end
end
end
end
end
One is a power of two (2^0), so it first checks if the number given is 1. If not, it checks if it is odd, because 1 is the only odd number that is a power of two.
If it is odd it returns false and moves on to the else statement. It will check if the number divided by 2 is two, because then it would obviously be a power of 2. It does this as a float, because 5/2 in Ruby would return 2.
If that is false, it then again checks if the number is odd -- unnecessary on the first round, necessary after that. If the number is not odd, it will divide the number by two and then do the loop another time.
This will continue until the program resolves itself by getting 2 or any odd number, and returns true or false, respectively.
I ran into this one in a bootcamp application prep. I'm not a math person and don't understand a few of these methods, so I wanted to submit a common sense approach for people like me. this requires little knowledge of math, except to know a number to the second power will be the result of some number multiplied by itself.
def is_power_of_two?(num)
num.times {|n| return true if (n+1) * (n+1) == num}
false
end
this method counts up to the num variable starting at 1 and returns true if (any of those numbers in the sequence multiplied by itself) is equal to num & if num is not 0 (more on that below).
example:
num = 9
1 * 1 == 9 #=> false
2 * 2 == 9 #=> false
3 * 3 == 9 #=> true
true is returned and method is finished running.
the #times method requires an integer > 0, so this edge case is "handled" by virtue of the fact that #times does nothing with "0" as the variable and returns false when outside of the #times iteration.
def power_of_two?(num)
num.to_s(2).scan(/1/).length == 1
end

I ran into issue here with splitting array and adding it up

i am trying to find if array has 2 digits number and if i find one i want to add the two digit and make it single. then add all the numbers in array to come up with a a sum. here is my code so far. and also i am a noob and learning
class Imei
attr_accessor :Imei, :split_total1, :split_total2
def initialize(imei)
#imei = imei.to_i
#split_total1 = []
#split_total2 = []
end
def check_two_digit(num)
if num.to_s.length == 2
num = num.to_s.split(//).partition.with_index{|_,i| i.odd?}
num.each do |a, b|
a.to_i + b.to_i
end
else
num.to_i
end
end
def check_imei
if #imei.to_s.length == 15
split1, split2 = #imei.to_s.split(//).partition.with_index{|_, i| i.odd?}
split1.each do |a|
#split_total1 << check_two_digit(a.to_i * 2)
end
split2.pop
split2.each do |a|
#split_total2 << a.to_i
end
else
puts "IMEI NUMBER INVALID"
end
end
end
imei = Imei.new(123456789102222)
imei.check_imei
puts imei.split_total1.inspect
puts imei.split_total2.inspect
Find below the Luhn Algorithm I wrote in ruby
def luhn_10_valid? imei
digits = imei.reverse.chars.map(&:to_i)
digits.each_with_index.inject(0) do |sum, (digit, i)|
digit *= 2 if i.odd?
digit -= 9 if digit > 9
sum += digit
end % 10 == 0
end
For Luhn algorithm I really like the divmod method, which simplifies things
array.reverse.each_slice(2).map { |x, y|
y ||= 0
[x, (y * 2).divmod(10)]
}.flatten.inject(:+) % 10 == 0
If a contains only non-negative integers, this is one Ruby-like way to compute the sum:
a.reduce(0) {|t,i| t + (((10..99).cover? i) ? i.divmod(10).reduce(:+) : i )}
Explanation:
If i => 46, (10..99).cover?(46) => true, 46.divmod(10) => [4,6], [4,6].reduce(:+) => 10. Recall that reduce is aka inject. [4,6]reduce(:+) has the same result as (but,technically, is not 'equivalent to'):
[4,6].reduce { |u,j| u+j }
The zero initial value is needed for the first reduce, as
a[46].reduce {|t,i| t+(((10..99).cover? i) ? i.divmod(10).reduce(:+):i)}
#=> 46
which is incorrect.
If a instead contains string representations of integers and/or the integers may be negative, let me know and I'll change my answer accordingly.

Iterate over an infinite sequence in Ruby

I am trying to solve Project Euler problem #12:
The sequence of triangle numbers is generated by adding the natural
numbers. So the 7th triangle number
would be 1 + 2 + 3 + 4 + 5 + 6 + 7 =
28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five
divisors.
What is the value of the first triangle number to have over five
hundred divisors?
Here's the solution that I came up with using Ruby:
triangle_number = 1
(2..9_999_999_999_999_999).each do |i|
triangle_number += i
num_divisors = 2 # 1 and the number divide the number always so we don't iterate over the entire sequence
(2..( i/2 + 1 )).each do |j|
num_divisors += 1 if i % j == 0
end
if num_divisors == 500 then
puts i
break
end
end
I shouldn't be using an arbitrary huge number like 9_999_999_999_999_999. It would be better if we had a Math.INFINITY sequence like some functional languages. How can I generate a lazy infinite sequence in Ruby?
Several answers are close but I don't actually see anyone using infinite ranges. Ruby supports them just fine.
Inf = Float::INFINITY # Ruby 1.9
Inf = 1.0/0 # Ruby before 1.9
(1..Inf).include?(2305843009213693951)
# => true
(1..Inf).step(7).take(3).inject(&:+)
# => 24.0
In your case
(2..Inf).find {|i| ((2..( i/2 + 1 )).select{|j| i % j == 0}.count+2)==42 }
=> 2880
Your brute force method is crude and can, potentially, take a very long time to finish.
In Ruby >= 1.9, you can create an Enumerator object that yields whatever sequence you like. Here's one that yields an infinite sequence of integers:
#!/usr/bin/ruby1.9
sequence = Enumerator.new do |yielder|
number = 0
loop do
number += 1
yielder.yield number
end
end
5.times do
puts sequence.next
end
# => 1
# => 2
# => 3
# => 4
# => 5
Or:
sequence.each do |i|
puts i
break if i >= 5
end
Or:
sequence.take(5).each { |i| puts i }
Programming Ruby 1.9 (aka "The Pickaxe Book"), 3rd. ed., p. 83, has an example of an Enumerator for triangular numbers. It should be easy to modify the Enumerator above to generate triangular numbers. I'd do it here, but that would reproduce the example verbatim, probably more than "fair use" allows.
Infinity is defined on Float (Ruby 1.9)
a = Float::INFINITY
puts a #=> Infinity
b = -a
puts a*b #=> -Infinity, just toying
1.upto(a) {|x| break if x >10; puts x}
Currrent versions of Ruby support generators heavily:
sequence = 1.step
In Ruby 2.6 this becomes much easier:
(1..).each {|n| ... }
Source: https://bugs.ruby-lang.org/issues/12912
This would be best as a simple loop.
triangle_number = 1
i = 1
while num_divisors < 500
i += 1
triangle_number += i
# ...
end
puts i
As Amadan mentioned you can use closures:
triangle = lambda { t = 0; n = 1; lambda{ t += n; n += 1; t } }[]
10.times { puts triangle[] }
Don't really think it is much slower than a loop. You can save state in class object too, but you will need more typing:
class Tri
def initialize
#t = 0
#n = 1
end
def next
#t += n
#n += 1
#t
end
end
t = Tri.new
10.times{ puts t.next }
Added:
For those who like longjmps:
require "generator"
tri =
Generator.new do |g|
t, n = 0, 1
loop do
t += n
n += 1
g.yield t
end
end
puts (0..19).map{ tri.next }.inspect
Building on Wayne's excellent answer and in the Ruby spirit of doing things with the least number of characters here is a slightly updated version:
sequence = Enumerator.new { |yielder| 1.step { |num| yielder.yield num } }
Obviously, doesn't solve the original Euler problem but is good for generating an infinite sequence of integers. Definitely works for Ruby > 2.0. Enjoy!
On Christmas Day 2018, Ruby introduced the endless range, providing a simple new approach to this problem.
This is implemented by ommitting the final character from the range, for example:
(1..)
(1...)
(10..)
(Time.now..)
Or to update using Jonas Elfström's solution:
(2..).find { |i| ((2..( i / 2 + 1 )).select { |j| i % j == 0 }.count + 2) == 42 }
Hope this proves useful to someone!
I believe that fibers (added in Ruby 1.9 I believe) may be close to what you want. See here for some information or just search for Ruby Fibers

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

Resources