App Academy's practice test says their chosen way of finding if an input is a power of 2 is to keep dividing it by 2 on a loop and check whether the end result is 1 or 0 (after having tested for the numbers 1 and 0 as inputs), which makes sense, but why won't this way work?
def try
gets(num)
counter = 0
go = 2 ** counter
if num % go == 0
return true
else
counter = counter + 1
end
return false
end
I can't figure out why this won't work, unless the counter isn't working.
There are a number of problems with your code.
First of all, there is no loop and your counter will reset to zero each time if you intend to use the method in a loop, because of counter = 0
.
counter = 0; go = 2 ** counter
basically means go = 2 ** 0
which is 1
. Therefore num % 1
will always be 0
You actually need to divide the number and change it in the process. 12 % 4
will return 0
but you don't know by that if 12 is a power of 2.
IO#gets returns a string and takes a separator as an argument, so you need to use num = gets.to_i
to actually get a number in the variable num. You are giving num
to gets
as an argument, this does not do what you want.
Try:
# Check if num is a power of 2
#
# @param num [Integer] number to check
# @return [Boolean] true if power of 2, false otherwise
def power_of_2(num)
while num > 1 # runs as long as num is larger than 1
return false if (num % 2) == 1 # if number is odd it's not a power of 2
num /= 2 # divides num by 2 on each run
end
true # if num reached 1 without returning false, it's a power of 2
end
I add some checks for your code. Note, that gets(num)
returns a String. Your code is fine, but not for Ruby. Ruby hates type-cross-transform like Perl does.
def try(num = 0)
# here we assure that num is number
unless (num.is_a?(Integer))
puts "oh!"
return false
end
counter = 0
go = 2 ** counter
if num % go == 0
return true
else
counter = counter + 1
end
return false
end
The general problem is "how string could use '%' operator with number?"
Try some code in the interpretator (irb
):
"5" % 2
or
"5" % 0