"Already initialized constant" warning [duplicate] - ruby

This question already has answers here:
What is the difference between a constant and a variable in Ruby?
(3 answers)
Closed 6 years ago.
Here's my code:
puts "Input a number."
Divisor = 2
inputNumber = gets.chomp
if inputNumber.to_i == 1 || inputNumber.to_i == 2
if inputNumber.to_i == 1
puts inputNumber + " is not a prime."
else
puts inputNumber + " is a prime."
end
else
while Divisor.to_i < inputNumber.to_i
if inputNumber.to_i%Divisor.to_i == 0
puts inputNumber + " is not a Prime as " + Divisor.to_s + " is a factor."
break
else
Divisor = Divisor.to_i + 1
end
end
puts inputNumber + " is a prime!"
end
I got the following error:
test1.rb:30: warning: already initialized constant Divisor
test1.rb:3: warning: previous definition of Divisor was here
What is wrong?

Constants and variables
Divisor is a constant. You want a variable : divisor. See this answer.
Notes
puts inputNumber + " is a prime!" is always called.
You could replace break by exit, or use a boolean variable.
Since you work with numbers, you could also call .to_i once, do your calculation, and just use .to_s to display results
You only have to check for factors in the range (2..Math.sqrt(inputNumber))
You don't have to check twice if inputNumber == 1
puts 'Input a number.'
divisor = 2
inputNumber = gets.chomp.to_i
prime = true
if inputNumber == 1
puts inputNumber.to_s + ' is not a prime.'
else
while divisor <= Math.sqrt(inputNumber)
if inputNumber % divisor == 0
puts inputNumber.to_s + ' is not a Prime as ' + divisor.to_s + ' is a factor.'
prime = false
break
else
divisor += 1
end
end
puts inputNumber.to_s + ' is a prime!' if prime
end
Alternative
A shorter alternative can be written with Enumerable#find. It executes the block with every element, stops as soon as the code in block returns a truthy value, and returns the element for which the block is truthy. If no element is found, it returns nil :
puts 'Input a number.'
number = gets.chomp.to_i
divisor = (2..Math.sqrt(number)).find { |i| number % i == 0 }
if number == 1
puts '1 is not a prime.'
elsif divisor
puts format('%d is not a prime as %d is a factor.', number, divisor)
else
puts format('%d is a prime!', number)
end

Related

Ruby- prime number unique and duplicates

I'm just learning Ruby :) and Im trying to create a simple prime-number program where all the primes of a number are printed.
I'm getting errors where the prime and nonprime numbers are mixed up
(ie: input of 9 will get you all nonprimes).
I'm sorry for such a beginner question - I'm struggling alot and need some help :)
puts "Enter a number please "
num = gets.chomp.to_i
i = 2
number = 2
while i < num
if number % i == 0
prime = false
end
i += 1
end
if prime == true
puts "#{number} is prime"
else
puts "#{number} is not prime"
end
number += 1
end
while i < num
if number % i == 0
prime = false
end
i += 1
end
# ...
It looks like that first end is meant to be an else.
It's easier to catch these things when you simplify your code, e.g. this method reduces to this (although there are other issues with it):
i = 2
number = 2
while i < num
(number % i).zero? ? prime = false : i += 1
puts "#{number} is #{'not ' unless prime}prime"
number += 1
end
End error is because of else
while i < num
if number % i == 0
prime = false
else
i += 1
end
if you have a short If - neater is writing it like:
if-condition ? 1 : 0
and in your case while is.. not the nicest choice - you should use range
(1...3).map{|x| puts(x) }
{} - allows multiline(with do end end)
this prints [1,2]
(1..3).map{|x| x*2 }
would be [2,4,9]
This should be enough hints of how to play around with your code without ruining the process.

Can you someone support me to use ordinal in while loop in Ruby?

I am having a difficult time figuring ordinal in the program below. I need to use the ordinal in the loop statement. When I print statement, It print out backward like 3rd, 2nd, 1st, and so on.
I tried changing my loop statment from (number -= 1) to (number += 1) but that would make infinite while loop. Can someone give me feedback on what I can do here? Thank you.
class Integer
def ordinal
case self % 10
when 1
return "#{self}st"
when 2
return "#{self}nd"
when 3
return "#{self}rd"
else
return "#{self}th"
end
end
end
puts "Let's play a numbers game."
print "How many numbers would you like to enter? >"
number = gets.chomp.to_i
while number >= 1
print "\n\nEnter the #{number.ordinal} positive integer:"
user_int = gets.chomp.to_i
number -= 1
if user_int % 3 == 0
print "#{user_int} is divisible by 3."
else
print "#{user_int} is not divisible by 3."
end
end
puts "\n\nEnd of the Game"
First I'd suggest you to patch Integer class in this way:
module MyIntegerPatch # <------ a custom module
def to_ordinal # <------ to_ordinal is better
case self % 10
when 1
return "#{self}st"
when 2
return "#{self}nd"
when 3
return "#{self}rd"
else
return "#{self}th"
end
end
end
Integer.include MyIntegerPatch # <------ "patch" the class
Then for your loop just use a Range:
(1..number).each do |n| # <---- a range here
puts "\n\nEnter the #{n.to_ordinal} positive integer:"
user_int = gets.chomp.to_i
if user_int % 3 == 0
puts "#{user_int} is divisible by 3."
else
puts "#{user_int} is not divisible by 3."
end
end
Maybe you can try below, use the ruby style times to control
class Integer
def ordinal
case self % 10
when 1
"#{self}st"
when 2
"#{self}nd"
when 3
"#{self}rd"
else
"#{self}th"
end
end
end
puts "Let's play a numbers game."
print 'How many numbers would you like to enter? >'
number = gets.chomp.to_i
number.times do |time|
print "\n\nEnter the #{(time + 1).ordinal} positive integer:"
user_int = gets.chomp.to_i
if user_int % 3 == 0
print "#{user_int} is divisible by 3."
else
print "#{user_int} is not divisible by 3."
end
end
puts "\n\nEnd of the Game"

Ruby looping program gives error

Here's what I wrote to check if a number is prime or not
print "Enter number : "
num = gets.chomp
i = 1
boo = true
while (i<num)
if (i%num==0)
boo=true
end
i++
end
if (boo==true)
puts (num+"is a prime number")
else
puts (num+"is not a prime number")
end
This gives an error, how can I fix it?
The output from cmd prompt:
Some problems:
++ operator doesn't exist in Ruby, you can use += 1 instead
your num is a string, you can make it a number with to_i method, like num.to_i
if the reminder of your number divided by a precedent number is zero you should set to false, not true
if you start at 1 your number will result always prime
Anyway, in a more idiomatic Ruby you can write this code something like
print "Enter number : "
num = gets.chomp.to_i
prime = (2..num - 1).all? { |i| num % i != 0 }
if prime
puts "#{num} is prime"
else
puts "#{num} is not prime"
end

Ruby: Factorial Recursion

The difference between the two methods occurs at second if condition. The if condition in the first method is "if num <= 1" and the if condition in the second method is "if num = 1". I mapped out both methods on a piece of paper step by step but I don't understand why the factorial2 returns 1 instead of 6. On paper, I get 6 for both methods.
def factorial1(num)
if num < 0
return "Please use a positive number"
end
if num <= 1
1
else
num * factorial(num-1)
end
end
puts factorial1(3)
#returns 6
def factorial2(num)
if num < 0
return "Please use a positive number"
end
if num = 1
1
else
num * factorial(num-1)
end
end
puts factorial2(3)
#returns 1
if num = 1
Comparator operator is ==, not = (assignment operator).
Also don't forget to use return keyword, it is good convention to make each branch return something.
def fact(n)
return 1 if n==0
return n * fact(n-1)
end
puts "Enter number"
n=gets.to_i
a=fact(n)
puts a

If type is character I want to puts error

puts "Let's sum many numbers"
sum = 0
num = 0
while(num != 'x')
puts "Press a number and then Enter if you exit press 'x'"
num = gets.chomp
if num != 'x'
num = num.to_i
print "#{sum} + #{num} = "
sum += num
puts "#{sum}"
elsif num == 'x'
puts "Total sum is #{sum}"
break
else
puts "error!"
end
end
I want to make code to show error If user press char except 'x'.
How should I do?
Change your first if to a condition that checks if the input is a number, e.g.
if num =~ /\A[0..9]+\z/ # or /\A\d+\z/
The way your code is currently, all strings except 'x' are treated as number -- with value 0 in case they aren't really numbers:
'foobar'.to_i # => 0

Resources