Checking for prime number in ruby - ruby

I am trying to write a method that takes a number and checks if its a prime number. After doing some research a fast way to check is to divide the number by every number between 2 and sqrt(number we are checking). I want my method to return true if it is a prime number and false if it isn't.
So I tried to write code that made logical sense to me but I am getting an error. Here's what I have written:
def PrimeTime(num)
counter = 2
while counter <= Math.sqrt(num).ceil
(counter == Math.sqrt(num).ceil) ? "false"
(num % counter == 0) ? "true" : counter += 1
end
end
This gives me
(eval):429: (eval):429: compile error (SyntaxError)
(eval):422: syntax error, unexpected '\n'
Rewritten code
def prime?(num)
(2..Math.sqrt(num).ceil).to_a.each do |number|
if num % number == 0
return false
else
return true
end
end
end
FYI, this is not homework. I am going through coderbyte problems. Any help is appreciated!

The proximate issue you are facing is, this is not valid Ruby: (counter == Math.sqrt(num).ceil) ? "false"
?, as an operator, is a part of the trinary operator ... ? ... : ..., and always comes in pair with a :, as you write in your next line. Then again, overuse of trinary operator is also not good. You also have a problem with control flow: after evaluating "true", the loop will continue, counter won't change, and you got an infinite loop.
I suggest you work out what the algorithm should be. Write it in English, if necessary. Then make sure you convert it to Ruby correctly.
Also, Ruby methods should be in snake case (lowercase with underscores between words), so PrimeTime is not a good name. I suggest prime? (as question marks are also allowed in identifiers) if you will be returning a boolean value (true or false). If you are returning a string (as you seem to be trying to do), try check_for_primality or something similar (without the question mark).
Also... if remainder is zero, the number is not prime. I think you have your tests switched around.
If you are still stumped:
def prime?(num); (2..Math.sqrt(num)).each do |counter|; if (num % counter == 0); return false end end; true; end
EDIT On rewritten code: break & return false doesn't do what you want. They are both control statements; if you break, return won't happen. Even if it did, if the break wasn't there, it would have been better to write and, or at least &&, not & (binary and).
Your logic is still wrong though: PrimeTime(16) is true, for example, is not really what I'd expect from a primality testing function.

In my opinion, your making this way more complicated than it should be. Here's the code that I would advise using.
require 'prime'
puts 2.prime?
Its that simple. And if you want to make your own method
require 'prime'
def prime?(num)
num.prime?
end

Ruby comes with predefined classes such as Prime. All you have to do is to require that class into your project.
require 'prime'
Than, you can use some of the Prime methods such as first to get first x prime elements:
Prime.first(5) # Ret => [2, 3, 5, 6, 11]
Or you could do something like this:
Prime.each(100) do |prime|
p prime # Ret => [2, 3, 5, 7, 11, ..., 97]
end
I hope this may helpful to you.. via miksiii

You can do it without Math.sqrt this way:
def is_prime?(number)
(2..number-1).each {|n| return false if number <= 1 || number % n == 0}
return true
end

Related

Why does the string 'xabcx' return as a palindrome in my method? (Ruby)

I'm going through some exercises on App Academy Open, and I've come across a test case that I can't quite figure out. I've written a method to detect if a given string is a palindrome or not, and it seems to work fine for all strings I've thrown at it - apart from 'xabcx'. Am I missing something?
def palindrome?(str)
(str.length / 2).times do |idx|
if str[idx - 1] != str[idx * -1]
return false
end
end
true
end
p palindrome?("xabcx")
I expect an output of false, but I get true. The method works as expected for every other word I've tried.
As Cary Swoveland already pointed out your indexing is wrong. To make debugging easier for you the next time I would recommend printing out both the values of the indices your using as well as the actual value of the char you select from the strings for each iteration of the loop.
As an alternative and really shorter and simpler version you could also use:
def palindrome?(str)
str == str.reverse
end
or - taking into account ignoring upper / lower case:
def palindrome?(str)
str.downcase == str.downcase.reverse
end

Why does the modulo formula to determine what are not prime numbers work for the prime number 2?

def prime?(num)
return false if num == 1
(2..num/2).each do |x|
if num%x==0
return false
end
end
true
end
Because you never enter your each. If the value is 2, then (2..num/2) becomes (2..2/2), which is (2..1). Ruby's range operators don't go backwards, so there is nothing to "each" over.
I believe that since (num/2) is 1 in that case, the loop never runs, so it falls through to the 'true' at the bottom.
I think your method is working:
puts prime?(2)
#=> true
As someone mentioned in the comments, you can also save some steps by only going through the sqrt of the number:
(2..Math.sqrt(num)).each do |x|

Towers of Hanoi, Ruby conditional

I'm having trouble with my first if conditional, which checks to make sure the the new piece added is smaller than the one under/before it. My Towers of Hanoi game worked fine until I added it. Below is my code:
arrays = [[5,4,3,2,1],[],[]]
win = false
while win != true
puts "Choose a top piece: (1, 2, 3) "
top = gets.to_i
puts "Which stack to place this piece? (1, 2, 3)"
stack = gets.to_i
if (arrays[stack-1] == nil) ||
(arrays[stack-1][arrays[stack-1].count-1] > arrays[top-1][arrays[top-1][arrays[top-1].count]])
arrays[stack-1].push(arrays[top-1].pop)
else
"You need to follow the rules."
end
print arrays
if arrays[1] == [5,4,3,2,1] || arrays[2] == [5,4,3,2,1]
print "You're a winner!"
win = true
end
end
~
Below is the error I get. How do I perform my check and deal with my nil value arrays in a concise manner?
towers_hanoi:13:in `[]': no implicit conversion from nil to integer (TypeError)
from towers_hanoi:13:in `<main>'
Use the empty? method to determine if an array is empty. FYI, though, if you want to see if a variable has a nil value, use nil?
Also, the last method will help a ton here and subtracting 1 from the inputs right away will make the code more readable. Try this:
arrays = [[5,4,3,2,1],[],[]]
win = false
while win != true
puts "Choose a top piece: (1, 2, 3) "
stack_from = gets.to_i - 1
puts "Which stack to place this piece? (1, 2, 3)"
stack_to = gets.to_i - 1
if (arrays[stack_to].empty?) ||
(arrays[stack_to].last > arrays[stack_from].last)
arrays[stack_to].push(arrays[stack_from].pop)
else
"You need to follow the rules."
end
print arrays
if arrays[1] == [5,4,3,2,1] || arrays[2] == [5,4,3,2,1]
print "You're a winner!"
win = true
end
end
There are a lot of strange things going on in that if statement.
Definitely use Array#empty? to check if an array if empty. An empty array is not nil.
Secondly some of your array bracketing is way too convoluted, I'm not sure what you are trying to accomplish here but you are definitely going to be checking if nil > number in some cases:
(arrays[stack-1][arrays[stack-1].count-1] > arrays[top-1][arrays[top-1][arrays[top-1].count]])
I doubt this is what you are trying to do (since it will throw an error). I would take a minute to think about your logic and refactor. In Towers of Hanoi, you only need to worry about checking if the piece you are moving is less than the LAST piece on the stack you are moving to (which represents the top).
Use Array#last and you will be on your way to a much simpler solution.

Guessing game for ruby

I'm currently trying to create a simply made guessing game, In the code there will be three set number (for now) that a person has to guess. If he/she guesses all the numbers correctly it puts, "Congrats, you win!"
Now as a beginning test i just wanted the user to guess one number correctly and the code gives back correct or incorrect.
random_guess = [1, 3, 5]
puts "Please Pick a number, 1-5"
pick_num = gets.chomp
if pick_num == random_guess = true
puts "Correct!"
else
puts "Incorrect!"
end
(I know this code is very beginner, i'm very new to ruby.) for some reason every time i run this program it puts incorrect.
Your if statement is wrong. It should be:
if random_guess.include? pick_num.to_i
Note that if you leave off the to_i the equality check will always fail because you're comparing the integer 3 against the string "3".
Just to help you a bit more. Since your end goal is to have the user guess all the numbers correctly. You can just loop on the same if statement I wrote above. And every time they guess a correct number you can remove it from the array like such:
random_guess.delete(pick_num.to_i)
Once the array is empty, the user has won.
Making random_guess random:
random_guess = []
3.times{random_guess << rand(1..5)}
random_guess
# => [5, 1, 4] # will be random in every other iteration
Checking if the number exists, you can either use index or include?:
if random_guess.index(pick_num.to_i) # alternatively random_guess.index(pick_num.to_i)
puts "Correct!"
else
puts "Incorrect!"
end
Why is your code always printing incorrect?
You are doing if pick_num == random_guess = true, which is a blunder. What is actually happening here is:
you are assigning true to random_guess. i.e. irrespective to what value (Array) random_guess holds, you are overwriting it with true.
Then you are comparing random_guess with pick_num.
So essentially you are doing this:
if pick_num == (random_guess = true) # say pick_num = "1"
# "1" == true # which is obviously false.
The correct conditional statement should be:
if pick_num == random_guess
However this will also print false every time. Reason?
pick_num is a string.
random_guess is an array that contains integer values.
You are comparing two different object types. So its always false.
Therefore the right way to solve this is checking whether the user entered value exists in the Array. For that you can use Array#index or Array#include?. Hence the statement in my proposed solution:
if random_guess.index(pick_num.to_i)
NOTE: pick_num.to_i converts pick_num (a character) into an integer. This is required as your array contains only integers and not characters.

How to run a simple Ruby script

I would like to make a program that checks to see if the number you enter is an even number. Sort of like making a leap year program but for any number divisible by 2.
Something along the lines of:
num = gets.chomp
while num != 0
if (num%2) == 0
puts 'yess'
else
puts 'nooo'
end
end
I knows there's something easy that I need to change for it to run.
(btw I just started learning Ruby yesterday!)
There are two problems here.
First being something that others have put, you need to make sure you turn the input into an integer using ".to_i" on your num variable.
Secondly, this code puts you into an infinite loop since you are using a "while" loop.
Since the number is only input once, you get stuck in the "while" loop forever no matter what the input is. Basically, "num" never stops being not 0.
You'd be better off using an if..else statement. Something like:
num = gets.chomp.to_i
if num != 0
if (num%2) == 0
puts 'yess'
else
puts 'nooo'
end
else
puts "that's 0, dude"
end
Integers have two methods for this. They are even? and odd?.
You can use this in your if statement as so:
if num.even?
puts 'yess'
else
puts 'nooo'
end
However, an easier way to write this is with ternary expressions:
puts num.even? ? "yes" : "no"
However, make sure num is an Integer. Anything coming from gets will be a String. So, you should be doing num = gets.chomp.to_i. Anything that is not a number, like "h", will return 0.
"5".to_i #=> 5
"h".to_i #=> 0

Resources