ruby weird behavior with integer#times and modulo - ruby

If I run this
100.times do |i|
unless i == 0 || i.modulo(2) == 0
p "odd number #{i}"
end
end
I only get back odd numbers, which is the way it should work.
if I run this though
100.times do |i|
unless i == 0 || i.modulo(3) == 0
p "even number #{i}"
end
end
then I get back a mixture of numbers, some of which are even.
Maybe it's me, or 'unless' isn't the best control to use here. Kind of weird though that one gives me the result I want, the other not.

i.modulo(3) == 0 is not a test for odd; it is a is a test of numbers divisible by 3.
Recall the definition of even is divisible by two (or x % 2 == 0) and odd is !even. Therefore only modulo test for even vs odd is mod 2 with a result of 0 or 1.
Example:
100.times { |i|
p "even number #{i}" unless i % 2==1 # better as if i % 2==0
p "odd number #{i}" unless i % 2==0 # better as if i % 2==1
}
To keep it straight, you can also use .even? and .odd?

Related

Ruby one-liner and warning: 'else without rescue is useless'

I'm trying to print a basic triangle pattern with a Ruby function which only accepts positive odd number for n
def triangle(n, chars)
puts "#{n} must be odd and positive" if n % 2 == 0 || n < 0 else (n + 1).times { |i| puts chars * i }
end
The problem is this function accepts not only odd but also positive n.
triangle(3, '#')would print
#
##
###
but 'triangle(4, '#')' also works fine
#
##
###
####
It seems my if statement is not working correctly and I get the warning else without rescue is useless. Why and how should I fix this?
Ruby is interpreting your code as two separate statements.
puts "#{n} must be odd and positive" if n % 2 == 0 || n < 0
else (n + 1).times { |i| puts chars * i }
The else is not associated with the if. Ruby is, I guess in desperation, interpreting that as part of a begin/rescue/else condition. Why it's not a syntax error, I have no idea, but it's interpreting it as having no begin block which is technically "successful" so the else always runs.
Conditional statements like do this if that are intended only for simple conditions covering simple statements. Trying to wedge in an else condition is right out. Instead, use a normal condition.
def triangle(n, chars)
if n % 2 == 0 || n < 0
puts "#{n} must be odd and positive"
else
(n + 1).times { |i| puts chars * i }
end
end
In general, avoid the else entirely by taking care of the error condition immediately. It avoids nesting the bulk of the function in an else block. This is more relevant for longer functions, but it's a good habit to get into.
def triangle(n, chars)
if n % 2 == 0 || n < 0
puts "#{n} must be odd and positive"
return nil
end
(n + 1).times { |i| puts chars * i }
end
Finally, errors should be handled with exceptions, not printed error messages. Exceptions can be caught and dealt with by the caller, printed error messages are difficult to catch and bubble up to the user. Exceptions, if not dealt with, halt the program; if the user forgets to handle an error the program will stop and they'll know to fix it. Printed error messages simply let the program plow forward and can be ignored leading to further problems down the road.
Exceptions can also be categorized allowing the caller to figure out what sort of error happened and act appropriately.
def triangle(n, chars)
if n % 2 == 0 || n < 0
raise ArgumentError, "#{n} must be odd and positive"
end
(n + 1).times { |i| puts chars * i }
end
The problem seems to be the flow control is getting confused with the logic as to what is output. This will do what you want, I think:
def triangle(n, chars)
if (n % 2 == 0) || (n < 0)
puts "#{n} must be odd and positive"
else
(n + 1).times { |i| puts chars * i }
end
end
As a more graceful implementation lets take this a step further and handle unexpected arguments
def triangle(n, chars='#')
raise(ArgumentError, "{n} must be odd and positive") unless n.to_i.odd? && n.to_i > 0
1.upto(n.to_i) { |i| chars.to_s * i}
end
This will now handle any n that responds to to_i and any chars that responds to to_s. e.g. '13', ['x', 'x', 1] are still valid arguments even if they make a weird triangle.
Ruby is extremely supportive of duck typing in this fashion and it makes your code less type specific.

Trying to figure out if user input is prime or not with ruby

I am new to Ruby and just read about methods and such I have been working on a program in order to get the user to type in a number and determine if it is prime or not. This is what I have so far.
print "Enter a number: "
num = gets.chomp
def prime(n)
factors = []
if num < 2
puts "#{num} is a prime number"
end
while n % num == 0 and num < n
factors.push(num)
num += 1
end
return factors
end
Not even sure if I'm on the right track. Really lost. Any help would be greatly appreciated!
require 'prime'
print "Enter a number: "
num = gets.chomp
Prime.prime?(n)
Or, from the scratch:
def prime?(n)
if n > 1
min_condition = Math.sqrt(n).to_i # The highest factor is necessary at most sqrt(n)
factors = 0
(1..min_condition).step(2).each do |i| # It's not necessary to check even numbers
factors += 1 if (n.to_f / i) % 1 == 0
break if factors > 1 # If the algorithm find 2 factors, the number isn't prime
end
!(factors > 1)
else
false
end
end
I know that you're doing this to learn Ruby, but keep in mind that you can just use Prime.prime? to determine whether or not a number is prime.
require 'prime'
Prime.prime?(3)
#=> true
Prime.prime?(4)
#=> false
As for your actual problem, you use both num and n inside your method, but num is defined outside, so won't be in scope. Also: you never seem to actually be calling prime.
There are some problems with your program:
You want to get the user to type in a number and determine if it is
prime or not but the output of your method prime doesn't answer
this question. It will return an array.
If a number is less then 2, it is not a prime number (wikipedia), so this piece of your code is wrong:
if num < 2
puts "#{num} is a prime number"
end
There are plenty of ways to check if a number is a prime number or not, this topic may help you to implement with Ruby.
If you don't want to use ruby base library than below code is useful for you
print "Enter a number: "
num = gets.chomp
def check_prime_number(num)
num = num.to_i
n = 1
factors = []
while (num >= n ) do
if (num % n == 0 )
factors << n unless factors.include?(n)
end
n += 1
end
if ( factors.size > 2)
puts "Factors of number #{num} :-> #{factors}"
elsif num > 0
puts "#{num} is prime"
end
end
check_prime_number(num)
Try if its helpful for you.

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

What's wrong with this Ruby code to determine whether a number is prime?

I'm getting "true"
def is_prime(n)
if (2..(n**0.5)).each {|i| n % i != 0}
puts "true"
else
puts "false"
end
end
is_prime(14)
Cary Swoveland hit the main problem, but there are some other tweaks that might make it cleaner/more useful.
def is_prime?(n)
(2..(n**0.5)).all? {|i| n % i != 0}
end
p is_prime? 14 # false
p is_prime? 17 # true
Note the addition of the question mark in the method name. The method now returns a usable result instead of printing.
If you wanted to enhance performance you could test separately for evenness and then iterate over only the odd numbers 3 to sqrt(n), stepping by 2's to cut the amount of work in half:
def is_prime?(n)
if n.odd?
3.step(Math.sqrt(n).to_i, 2).all? {|i| n % i != 0}
else
false
end
end

Generally Fizzy ruby

Given the following variables
divisor_array, low, high define a method that
Prints all numbers from low to high
If the any number being printed is divisible by any divisor number in divisor_array, print the number + the word "fizzy"
If the number being printed is divisible by ALL the numbers in the array, it should output the number + "reallyfizzy".
Testing Values: generally_fizzy([2,3],1,7)
My initial solution:
def generally_fizzy(divisor_array, low, high)
divisors = Hash[*divisor_array]
low.upto(high) do |i|
divisors.each_pair do |k,v|
if((i % k == 0) && (i % v == 0))
puts "#{i} reallyfizzy"
elsif ((i % k == 0) || (i % v == 0))
puts "#{i} fizzy"
else
puts i
end
end
end
end
this solution passes the tests given, but when the divisor_array size is increased from 2 values to 3 and over it prints out duplicates. In addition to that, the code is not very elegant.
Looking for a working alternative, that can deal with divisor_array size changes.
Just count how many divisors in the array will divide the value. There are three cases we care about:
all of them
at least one of them
none of them.
def fizzy(divisors, lo, hi)
lo.upto(hi) do |value|
puts case divisors.count{ |div| value % div == 0 }
when divisors.length # all divisors
"#{value} really fizzy"
when 0 # no divisors
value
else # at least one divisor
"#{value} fizzy"
end
end
end
this is a little bit modified answer. It uses one exit point from method which i find more readable and robust (can be optimized if performance is a concern).
def fizzy(divisors, low, high)
low.upto(high) do |value|
print "#{value} "
print "really" unless divisors.detect{ |div| value % div != 0}
print "fizzy" if divisors.detect{ |div| value % div == 0}
print "\n"
end
end
fizzy([2,3],1,7) #=>
1
2 fizzy
3 fizzy
4 fizzy
5
6 reallyfizzy
7

Resources