Building a ruby factorial calculator - ruby

I'm working on writing a factorial program in ruby and I'm trying to write it where it does as follows:
Asks the user to enter a value to perform factorial on
takes in that value entered
performs factorial on it
and 4. returns the factorial value using "puts"
My goal is to get this to work then expand on this by building it out to include other statistical functions.
So far this is the code I have:
puts "Welcome to the Calculator for Ruby"
puts "Please enter your value to value"
#N factorial value
def n
n = gets.chomp
end
def fact
n * fact(n-1)
end
puts fact(n)
Fyi, I might add I've seen the generic factorial code available on the web but what I'm trying to do is set it so that the user defines n rather than setting n statically but when I try to do it, my code as above is erroring with the below error message:
"fact" : wrong number of arguments (1 for 0) (ArgumentError)
My apologies for some of the wording and not including a specific question. My question would be 3 parts:
How would I properly write the factorial calculation to operate on the user provided value? (Which I see was answered).
Once the calculation is performed how can I store that value so it persists in case the user wants to recall it for other calculations.
Lastly, are there any good sources for guidance in writing statistical functions in ruby?
Thank you to all for the assistance

No need to declare n using def, simply assign it (e.g. as n = gets.chomp).
You must include a named argument to your fact function, like def fact(x).
The fact(x) function needs a base case since you are using recursion.
You must convert the user input string n to a number, like n.to_i.
puts "Welcome to the Calculator for Ruby"
puts "Please enter your value to value"
def fact(x)
(x <= 1) ? 1 : x * fact(x-1)
end
n = gets.chomp.to_i
puts "#{n}! => #{fact(n)}"

Simpler way. Just inject numbers from 1 till n.
puts 'Welcome to the Calculator for Ruby'
puts 'Please enter your value to value'
n = gets.chomp.to_i
puts (1..n).inject(:*)

Might no be the best of solutions but here you go
puts "Welcome to the Factorial Calculator for Ruby"
puts "Please enter your value to exaluate"
n = gets.chomp.to_i
def fact(num)
return num <= 1 ? 1 : num * fact(num - 1)
end
puts "The factorial of #{n} is #{fact(n)}

Related

Simple program but so very stuck- Loops in Ruby

I have to write a program which asks the user to enter a number.
The program keeps on asking the user for a number until the user types 'Stop'
at which point the sum of the numbers that the user has entered should be printed.
I've tried many,many things and none of my ideas work.
This is what I have - but I can that it isn't correct. What am I doing wrong?
I've only used while loops and arrays
total_user_input = []
# As long as the user inputs a number, the program will keep putting Give me a number
# and then adding that number to the total_user_input array.
puts "Give me a number: "
while user_input = gets.chomp.to_i
#add the input to the array total_user_input
total_user_input.push(user_input.to_i)
puts "Give me a number: "
# If the user however types stop, then the loop is broken and we jump down to the
# sum bit - where all of the numbers in the total_user_input array are added together
# and printed. End of program!
if user_input == "stop"
break
end
sum = 0
total_user_input.each { |num|
sum += num
}
puts sum
end
The output isn't as it should be.
As others have identified the problems with your code let me suggest how you might reorganize it. Ruby provides many ways to execute loops but you many find it desirable to primarily relay on the method Kernel#loop and the keyword break. (As you will learn in time, loop is particularly convenient when used with enumerators.)
def sum_numbers
tot = 0
loop do
print 'Gimme a number: '
s = gets.chomp
break if s == 'Stop'
tot += s.to_i
end
tot
end
The keyword break can optionally take an argument (though why that is not mentioned in the doc I cannot say), in which case it (if a literal) or its value (if a variable or method) is returned by loop. Here one would generally see
break tot if s == 'Stop'
without the final line, tot. As the loop returns tot and that is the last calculation performed by the method, the method will return the final value of tot.
You could have instead written
return tot if user_input == 'Stop'
but I think most coders believe best practice dictates that one should not return from a method from within a loop (or from within nested loops) unless there is a good reason for doing so.
Some small points:
I used print rather than puts to that the user's entry will be shown on the same line as the prompt.
I used s (for "string") rather than user_input because it reduces the chance of spelling mistakes (e.g., user_imput), speeds reading, and (possibly a foible of mine), looks neater. True, s is not descriptive, but one only has to remember its meaning for three consecutive lines of code. Others may disagree.
You could write, break if s.downcase == 'stop' if you want, say, 'stop' or 'STOP' to have the same effect as 'Stop'.
'23O3'.to_i #=> 23 (that's an an oh, not a zero), so in real life you'd want to confirm that either 'Stop' or the string representation of a number had been typed.
This is how I would do this preferring to use loop do end syntax with a break when it should. Also added a bit more text so user knows what's happening.
total_user_input = []
puts 'Give me a number or "stop" to end: '
loop do
user_input = gets.chomp
total_user_input << user_input.to_i
puts "Give me a number: "
break if user_input.downcase == "stop"
end
puts "Total entered: #{total_user_input.inject(&:+)}" unless total_user_input.empty?
puts 'goodbye!'
Note these few things:
get.chomp.to_i will convert every input to integer. ("stop" or any non integer string will be 0)
Arrangement of the flow is quite messy.
total_user_input = []
puts "Give me a number: "
while user_input = gets.chomp.strip
total_user_input.push(user_input.to_i)
sum = 0
total_user_input.each { |num|
sum += num
}
puts sum
if user_input == "stop"
break
end
end
Hope you understand this.

Cant figure out where I am making mistake

Issue:
def average_of_three(num1, num2, num3)​
puts "Enter first number"
num1= gets.to_i
puts "Enter second number"
num2 = gets.to_i
puts "Enter third number"
num3 = gets.to_i
avg=0
avg = (num1 +num2 + num3 )/3
puts "your average is#{avg}"
end
Solution:
I was missing the following statement :
average_of_three(10, 20, 30)
This code should work if you call that method, but the method doesn't need arguments. Those variables are declared locally anyway.
Right now you'd do:
average_of_three(0, 0, 0)
Where the initial values don't matter as you ignore them anyway. They could be :zero or "Who cares!" just the same.
This isn't very Ruby code though. When writing Ruby think first in terms of data structures.
For example, to get three values:
def get_n(n = 3)
n.times.map do |i|
print "Enter number #{i+1}: "
gets.to_i
end
end
This asks a series of questions and stores the result in an array, that's what map does.
Now you can average those:
def average(values)
return unless (values.any?)
values.sum / values.length
end
This has a guard clause where it won't execute unless there's at least one value. Then it calls sum, which not surprisingly adds up all the values. Divide by the length and you're done.
So you'd tie this all together with:
values = get_n
puts "Average is: #{average(values)}"
Note: In Ruby when you divide an integer by an integer you always get an integer. This means the values get rounded. If you'd prefer to have fractional results you can switch the input converter from .to_i to .to_f. That change will cause floats to flow through the rest of the code.

User input to create factorial

Need some help on making the def fact(n) command to work off user input. My script works great when I input something like "Ruby factorial.rb 5". However, I need this to run with prompts. The script should run something like:
puts 'Please input a non-negative integer:'
n = gets.chomp.to_i
puts "The factorial of #{n} is #{factorial}
Here's what my code looks like now. Like I said however, it does work. It's when I add n = gets.chomp.to_i before the def fact(n) command that I automatically receive a value of 1. It doesn't matter what number the user puts in, it always returns 1.
#!/user/bin/ruby
def fact(n)
if n==0
1
else
n * fact(n-1)
end
end
puts fact(ARGV[0].to_i)
How do I make this work with the user input? I think I'm just having a syntax issue, but don't know how to make it work.
You actually seem to be asking for two different things. The first thing you want is an application that does something like this
$ ruby factorial.rb
> Please input a non-negative integer
(GET USER INPUT)
> The factorial of (USER INPUT) is (FACTORAIL OF USER INPUT)
And a command line tool that does something like this
$ fact 10
> 3628800
The first one could look something like this
def fact(n)
(1..n).inject(:*)
end
puts 'Please input a non-negative integer'
a = gets.to_i
puts "The factorial of #{a} is #{fact(a)}"
The second one could look something like this
#!/usr/bin/ruby
puts (1..ARGV[0].to_i).inject(:*)

Code should return highest of two numbers entered by the user

This is the code.
puts "Give me a number"
one = gets.chomp
puts "Give me another number"
two = gets.chomp
if one > two
puts "This is the bigger number #{one}"
else
puts "This is the bigger number #{two}"
end
I don't know where my fault is.
you didn't change them to integer, gets.chomp gives you string.
puts "Give me a number"
one = gets.chomp.to_i
puts "Give me another number"
two = gets.chomp.to_i
First, you are gathering input from an external user of your "application", you then have to decide how you want to manage wrong input and conversion.
In any case, gets will return a String
You are going for numbers, but are they Integer, Float ?
Since String is Comparable, your original code will run but will probably not yield the expected returns.
Let's say you are only interested in Integers.
You will have three conversion functions to consider :
Kernel#Integer (which is included in the top-level binding)
String#to_i.
String#to_i will never return an error.
'abcd'.to_i #=> 0
'1.2'.to_i #=> 1
nil.to_i #=> 0
Kernel#Integer will return an error if the String is not a valid Integer. (which I generally find more appropriate for user inputs).
Integer('0') #=> 0
Integer('abcd') #=> ArgumentError
Integer(nil) #=> TypeError
Finally, you will have to compare your inputs. I personnally would use Array#max since it conveys optimal readability (at the expense of performance still, but you do not seem to be in a performance critical system).
My final code would look like this (without error handling):
inputs = []
2.times do
puts 'Give me a number'
inputs << Integer(gets.chomp) # or use gets.chomp.to_i
end
puts "This is the bigger number : #{inputs.max}"
More refactoring can be done but I don't think it would serve for beginners in Ruby.

How would I reuse a random number in ruby?

I am trying to create a random math equation (just with simple addition) where two random numbers are given to you and you need to add them up. My problem is that the two random numbers used for the answer are different from the ones that are used in the equation
puts "Choose the number range (difficulty of the equation)"
difficulty = gets.chomp
a = rand(difficulty)
b = rand(difficulty)
answer = a + b
puts "#{a} + #{b}"
UserAnswer = gets.chomp
if UserAnswer == answer
puts "good"
else
puts "bad"
end
Your problem has nothing to do with random numbers. The problem is that you are comparing a number (the sum of the random numbers) with a string (from the user input). You should replace the relevant line with:
UserAnswer = gets.to_i
By the way, I don't see any reason to use a constant here. It would most likely be better using a local variable like user_answer.
Try storing the of a and b in other two variables like a_aux and b_aux, and then refer to these instead of a and b everytime you would use a and b.

Resources