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
Related
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.
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"
Alright, so I asked an earlier question on my syntax error. I got rid of the errors, but the program doesn't do what it was intended to do. My math is wrong and doesn't find the number of trailing zeros. Here is my code:
num = " "
a = 0
sumOfFact = 1
def factorial
num = gets.to_i
a = num
(1..num).each do |a|
if a != 1
sumOfFact *= a
a -= 1
else
break
end
end
end
for c in 1..sumOfFact
if sumOfFact / c == 10
zeros += 1
end
end
factorial()
puts sumOfFact
puts zeros
Well, first, you should do the gets outside your method. Your method should accept a param. Second, why do you need the condition?
You want the multiplication from 1 to n to get the factorial. You should get started with this:
def factorial(n)
total = 1
(1..n).each do |n|
total *= n
end
total
end
puts factorial(gets.to_i)
Next is factorial with inject in case you want to learn new syntax :-)
def factorial(n)
n == 0? 1 : (1..n).inject(1) { |total, i| total*= i; total }
end
puts factorial(gets.to_i)
As #pjs commented below, here's a beautiful way of doing factorial!
def factorial(n)
n == 0? 1 : (1..n).inject(:*)
end
And, a final enhancement:
def factorial(n)
(1..n).inject(1, :*)
end
Supposing that n is a non-negative integer number, you can define a method to calculate the factorial:
def factorial(n)
tot = 1
(1..n).each do |n|
tot *= x
end
tot
end
Examples of its usage:
puts factorial(0) # 1
puts factorial(1) # 1
puts factorial(2) # 2
puts factorial(3) # 6
puts factorial(4) # 24
puts factorial(5) # 120
If you wan't to read the user input, call it like this:
puts 'Type the non-negative integer:'
n = gets.to_i
puts factorial(n)
class Factorial
attr_reader :num
def initialize(num)
#num = num
end
def find_factorial
(1..num).inject(:*) || 1
end
end
number = Factorial.new(8).find_factorial
puts number
Or you could just simply write:
(1..num).inject(:*) || 1
Try this too. Hope this helps anyone having the same problem in some way.
Method for finding the factorial of any number:
def factorial(number)
for i in 1...number do
number *= i
end
number
end
puts factorial(5)
I would like to pass an array of numbers to my is_prime? method and return if the numbers are valid or not. I do not want to use:
require 'prime'
a = [1,2,3,4,5]
Hash[a.zip(a.map(&Prime.method(:prime?)))]
This is learning experience. My current code is only outputing the first number in the array. Can someone help me understand what I am doing wrong? Thanks!
def is_prime?(*nums)
i = 2
nums.each do |num|
while i < num
is_divisible = ((num % i) == 0)
if is_divisible == false
x = "#{num}: is NOT a prime number." #false
else
x = "#{num}: is a prime number." #true
end
i +=1
end
return x
end
end
puts is_prime?(27,13,42)
You are returning in the loop.
A few bugs in your method:
def is_prime?(*nums)
nums.each do |num|
return false if num == 1
next if num == 2 # 2 is the only even prime
i = 2 # needs to be reset for each num
while i < num
return false if num % i == 0 # num is not prime
i += 1
end
end
true # We'll reach here only if all the numbers are prime
end
This will return your results in the same format as your usage of the prime library with the same logic as your custom function:
def is_prime?(*nums)
nums.each_with_object({}) do |num, hsh|
hsh[num] = num > 1 && 2.upto(num - 1).none? { |i| num % i == 0 }
end
end
puts is_prime?(27,13,42)
# => {27=>false, 13=>true, 42=>false}
Since you mention this is just for learning, I'm assuming you know that a sieve is a better way to go for this than brute force iteration.
If you want an explanation of how the above code works or further help understanding why your current code doesn't, let me know in the comments.
I need some feedback to figure out why I cant puts or print anything from my methods on the screen. This is a simple script I wrote to solve the problem of finding the 1001st prime number. Thanks
def primes
# iterates through numbers until it has the 1001th prime number and returns it.
# I chose to create the num_primes variable instead of counting the number of
# elements in in_prime_array every iteration
# based upon a guess that it would be faster to check.
is_prime_array = []
num_primes = 0
i = 2
loop do
is_prime_array << i && num_primes += 1 if is_prime?(i) == true
i += 1
break if num_primes == 1001
end
is_prime_array[1001]
end
def is_prime? (num)
# Checks to see if the individual number given is a prime number or not.
i = 2
loop do
if i == num
return true
elsif num % i == 0
return false
else
i += 1
end
end
end
Thanks for any help!
EDIT
I took your advice and tried this pice of code:
def is_prime? (num)
# Checks to see if the individual number given is a prime number or not.
i = 2
loop do
if i == num
return true
elsif num % i == 0
return false
else
i += 1
end
end
end
i = 0
count = 0
loop do
count += 1 if is_prime?(x)
puts "#{i}" if count == 1001
break
end
It still returns nothing. Hummm
i = 0
count = 0
loop do
if is_prime(i)
count += 1
end
if count == 10001
puts "#{i}"
break
end
end
Simple method :)
It's an off-by-one error. If you have 1001 elements in an array, the last element will be at index 1000.
Where you have
is_prime_array[1001]
Change it to
is_prime_array[1000]
And you can do this:
puts primes
=> 7927
You could also have
is_prime_array.last
instead of a specific index number.
What are you trying to "puts"? The first thing I notice is that there is no call to primes in the file, so nothing will happen if you try to run this code by itself. Maybe that's why you don't see anything printed.
Here's an example of how to print a few variables inside your loop:
loop do
...
puts "At iteration #{i}, we have prime=#{is_prime?(i)}"
If you don't know, enclosing a statement with #{<statement goes here>} inside a string is the same as appending the return value of <statement goes here> to the string at that position. This is the same as "Str " + blah + " rest of str" in a language like Java.