How to make a method take one or two arguments? [duplicate] - ruby

This question already has answers here:
Should repeat a number of times
(3 answers)
Closed 8 years ago.
I am working on an exercise to make the following tests pass:
describe "repeat" do
it "should repeat" do
repeat("hello").should == "hello hello"
end
# Wait a second! How can you make the "repeat" method
# take one *or* two arguments?
#
# Hint: *default values*
it "should repeat a number of times" do
repeat("hello", 3).should == "hello hello hello"
end
end
I am not understanding this part for some reason.
When I use this:
def repeat(z)
return z + " " + z
end
The first part of the test passes but the second one fails.
Then when I try this:
def repeat(z, 2)
return z * 2
end
I get an error the quits the test/rake.
And then when I try:
f = 2
def repeat(z, f)
return z * f
end
The test won't pass and I get this message:
wrong number of arguments (1 for 2)
I have no idea what is happening here, can someone explain how this works?

You can define the function like following:
def repeat(z, y=2)
return z * y
end
So now, repeat("hello") will result: hellohello and repeat("hello", 3) will return hellohellohello

It seems you're doing the Simon Says exercise.
The purpose of this exercise is to teach you how to take one or multiple arguments, using the default values.
Whenever you assign a default value using the "x = default value", it will be used. If the method was called with a different value, it would be used.
In the example below, the default value of number is 2.
def repeat(word, number = 2)
([word] * number).join(" ")
end
Using the above, we can call repeat("Hello", 3) and it would result with "hello hello hello"
If we call repeat("Hello"), by default it will return "hello hello"
Hope this helps!!!

Related

How to solve ruby string [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm new to ruby, and I'm trying to make a simple calculator in which a user types in a simple problem (such as addition or subtraction) and the answer is returned. The problem is when the user types in a question, the question itself is being returned instead of the answer to that question.
puts "How many Questions?"
questions = gets.chomp.to_i
questions.times do |problem|
puts "question: "
problem = gets.chomp
puts "answer: #{problem}"
end
Inside your loop, instead of:
problem = gets.chomp
puts "answer: #{problem}"
Try this:
problem = gets.chomp
solved_problem = eval(problem)
puts "answer : #{solved_problem}"
eval will take care of interpreting your string as a Ruby instruction. But it's very messy, because anyone could write any Ruby program in your input and eval will make it run, so it's not safe at all.
If you only want to take care of simple operations, you can use a regex first to check if the input string looks like what you want:
problem_is_ok = (problem =~ /^\d+ *[+-] *\d+$/)
This will be true if the string starts with a number, followed by 0 to many spaces, followed by either a + or - sign, followed by 0 or more spaces, followed by another number and nothing else. Then you raise an error if this is not true.
Your loop now look like this:
questions.times do |problem|
puts "question: "
problem = gets.chomp
problem_is_ok = (problem =~ /^\d+ *[+-] *\d+$/)
if problem_is_ok
puts "answer: #{eval(problem)}"
else
#I raise an error, but you might aswell just print it instead for your simple program
raise ArgumentError("Can't compute this")
end
end
Add and subtract can be simple ruby definitions
We pass in 5 and 1
The lower portion of the code is the clear user interface implementation
when we loop we do it 3 times
It outputs 3 options for the user to select from
We read in with chomp, standard in, the keyboard, chooses 1, 2, or 3
If elsif statements conditionally select for each case
Using string interpolation we render the variables a and b into a new string,
and run their respective methods (add or subtract)
Converting that methods integer output to a string, and concatenate it.
Outputting that to the users screen
The 3rd option does no calculation,
instead it prints to users screen a simple string
our else condition catches the case when people don't enter one of the choices of 1, 2 or 3
It tells you to correct your choice to the options provided
Hope this helps
#!/usr/bin/env ruby
questions = 3
a, b = 5, 1
def add(a,b)
a + b
end
def subtract(a,b)
a - b
end
questions.times do |questions|
puts "Please choose:
1. add
2. subtract
3. exit"
questions = gets.chomp
if questions == '1'
puts "#{a} + #{b} = " + add(a,b).to_s
elsif questions == '2'
puts "#{a} - #{b} = " + subtract(a,b).to_s
elsif questions == '3'
puts 'exiting, goodbye.'
exit
else
p 'please choose again'
end
end

How to make Lambda (or lambda-like object) to call itself with a new parameter it got (Ruby)

I am within a method and want a simple solution to check client's response.
l=lambda { |answer|
if answer == 1
x*5
elsif answer == 2
x*10
elsif
puts "Please enter 1 or 2"
answer = gets.chomp
l.call(answer)
end
}
Obviously this code doesn't work, since lambda can't "see" itself, but is there a way to achieve the desired effect in a simple-fashioned way?
Because right now I'm just writing a new method to call and passing bunch of parameters, which I wouldn't need to if I were able to check the answers within the current method.
Slightly confused, is this what you're trying to achieve? I notice you have variable x, but this isn't referred anywhere (just answer is).
lam = ->(x) do
x = Integer(x)
case x
when 1
x * 5
when 2
x * 10
else
puts 'Please enter 1 or 2'
input = gets.chomp
lam.call(input)
end
end
# 2.2.2 > lam.call(5)
# Please enter 1 or 2
# 3
# Please enter 1 or 2
# 2
# => 20
# 2.2.2 > lam.call(1)
# => 5

Building a ruby factorial calculator

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)}

Passing variables/parameters from one Ruby class to a loaded Ruby program

The below combined programs should ask for a number remove the first digit (lets call this new number x) and then compute x % 7. Ex: (1121546 % 7) = 5
This all appears to be working except that the number entered in will always compute to 0. modulo_7.rb works by itself and will print the correct outcome when passed a parameter.
The question is am I not passing the variables/ parameters properly or is there something else that is getting in the way?
class Number_check_interface
def get_cert_number
print "You are about to check receive the check number for a policy/cert id."
#cert_id = nil
until #cert_id.is_a?(Fixnum) do
puts " Enter the policy/cert ID. "
begin
#cert_id = Integer(gets)
rescue ArgumentError
end
end
end
end
class Run_number_check_interface
def run
load 'modulo_7.rb'
n = Number_check_interface.new
n.get_cert_number
checking_policy_number = Get_policy_check_digit.new(#cert_id)
checking_policy_number.create_check_digit
end
end
run = Run_number_check_interface.new
run.run
modulo_7.rb
This program removes the first digit (index 0) of a 7 digit number and returns the difference 7%18 is 4 since 4 is remainder of how many times 7 can fit into 18.
class Get_policy_check_digit
def initialize(cert_id)
#instance variable
#cert = cert_id
end
def create_check_digit
cert_id_6 = #cert.to_s
cert_id_6.slice!(0)
puts cert_id_6
check_digit = cert_id_6.to_i % 7
puts "Your check digit is #{check_digit}"
end
end
# n = Get_policy_check_digit.new(1121546) When uncommented this will create a new instance
# of Get_policy_check_digit with the parameter 1121546
# n.create_check_digit This will run the method create_check_digit with the
# parameter 1121546
Instance variables are scoped to an individual instance of a class. So when you say #cert_id = Integer(gets) inside Number_check_interface, you are only setting #cert_id for that particular instance of Number_check_interface. Then, when you later write Get_policy_check_digit.new(#cert_id) inside Run_number_check_interface, you are referring to an entirely different #cert_id, one which is specific to that particular instance of Run_number_check_interface, and not to the Number_check_interface you stored in n earlier.
The simple solution is to return #cert_id from Number_check_interface#get_cert_number, and then pass the returned value to Get_policy_check_digit.new:
class Number_check_interface
def get_cert_number
print "You are about to check receive the check number for a policy/cert id."
#cert_id = nil # This is an instance variable. It's only accessible
# from inside this instance of `Number_check_interface`
until #cert_id.is_a?(Fixnum) do
puts " Enter the policy/cert ID. "
begin
#cert_id = Integer(gets)
rescue ArgumentError
end
end
return #cert_id # Return the contents of #cert_id
end
end
class Run_number_check_interface
def run
load 'modulo_7.rb'
n = Number_check_interface.new
cert_number = n.get_cert_number # Here we call `get_cert_number` and
# set `cert_number` to it's return
# value.
# Notice how we use `cert_number` here:
checking_policy_number = Get_policy_check_digit.new(cert_number)
checking_policy_number.create_check_digit
end
end
Other tips:
Convention in Ruby is to name classes with CamelCase.
Require dependencies at the top of your files, not in the middle of method calls.
Unless you have a very good reason not to, use require, not load
You might want to think a bit harder about what purpose these classes serve, and what behavior they are intending to encapsulate. The API seems a bit awkward to me right now. Remember, tell, don't ask.
Why are these separate classes? The design here seems strange, is this ported from another language? It's more complicated than it needs to be. Without changing your structure, here's what's wrong:
In Run_number_check_interface you are reading #cert_id, it doesn't have an instance variable named that, but Number_check_interface does. Just return it from get_cert_number:
class Number_check_interface
def get_cert_number
print "You are about to check receive the check number for a policy/cert id."
cert_id = nil
until cert_id.is_a?(Fixnum) do
puts " Enter the policy/cert ID. "
begin
cert_id = Integer(gets)
rescue ArgumentError
end
end
cert_id # <-- returing the value here
end
end
class Run_number_check_interface
def run
load 'modulo_7.rb'
n = Number_check_interface.new
cert_id = n.get_cert_number # <-- saving here
checking_policy_number = Get_policy_check_digit.new(cert_id) # <-- no longer an ivar
checking_policy_number.create_check_digit
end
end
run = Run_number_check_interface.new
run.run

What does "wrong number of arguments (1 for 0)" mean in Ruby?

What does "Argument Error: wrong number of arguments (1 for 0)" mean?
When you define a function, you also define what info (arguments) that function needs to work. If it is designed to work without any additional info, and you pass it some, you are going to get that error.
Example:
Takes no arguments:
def dog
end
Takes arguments:
def cat(name)
end
When you call these, you need to call them with the arguments you defined.
dog #works fine
cat("Fluffy") #works fine
dog("Fido") #Returns ArgumentError (1 for 0)
cat #Returns ArgumentError (0 for 1)
Check out the Ruby Koans to learn all this.
You passed an argument to a function which didn't take any. For example:
def takes_no_arguments
end
takes_no_arguments 1
# ArgumentError: wrong number of arguments (1 for 0)
I assume you called a function with an argument which was defined without taking any.
def f()
puts "hello world"
end
f(1) # <= wrong number of arguments (1 for 0)
If you change from using a lambda with one argument to a function with one argument, you will get this error.
For example:
You had:
foobar = lambda do |baz|
puts baz
end
and you changed the definition to
def foobar(baz)
puts baz
end
And you left your invocation as:
foobar.call(baz)
And then you got the message
ArgumentError: wrong number of arguments (0 for 1)
when you really meant:
foobar(baz)

Resources