Ordinal numbers in Ruby - ruby

My code works perfectly on everything except 11, 12 and 13 or numbers that end in those last two digits.
def ordinal()
n = gets.chomp.to_i
suffix = n % 10
if suffix == 1
return "That's the #{n}st item!"
elsif suffix == 2
return "That's the #{n}nd item!"
elsif suffix == 3
return "That's the #{n}rd item!"
else
return "That's the #{n}th item!"
end
end
Any help would greatly appreciated! Thank you.

This is a special case. Check 2 digit suffix before you check 1 digit suffix. Something like this
def ordinal(n)
ending = case n % 100
when 11, 12, 13 then 'th'
else
case n % 10
when 1 then 'st'
when 2 then 'nd'
when 3 then 'rd'
else 'th'
end
end
"This is #{n}#{ending} item"
end
ordinal(1) # => "This is 1st item"
ordinal(10) # => "This is 10th item"
ordinal(12) # => "This is 12th item"
ordinal(15) # => "This is 15th item"
ordinal(112) # => "This is 112th item"
ordinal(123) # => "This is 123rd item"

Related

Strong number identifier (Ruby code issue)

I need to write some code that can identify a Strong Number.
A strong number is the number that the sum of the factorial of its digits is equal to number itself.
For example : 145 , since 1! + 4! + 5! = 1 + 24 + 120 = 145
I've been trying to solve this but to no avail. Can anyone tell me where I'm going wrong? I need the "adder" and "multiplier" variables to increase with each loop, so I can compare the total at the end of the method, but they keep defaulting to zero. Can anyone see where I'm going wrong? Thanks!
def strong_num(n)
digits=n.divmod(1)
multiplier=1
adder=0
digits.each do |digit|
x=digit
digit-1.times do
multiplier=multiplier*x
adder=adder+multiplier
x=x-1
end
end
if n==adder
return "STRONG!!!!"
else
return "Not Strong !!"
end
end
Sample input:
Test.assert_equals(strong_num(1) , "STRONG!!!!")
Test.assert_equals(strong_num(2) , "STRONG!!!!")
Test.assert_equals(strong_num(7) , "Not Strong !!")
Test.assert_equals(strong_num(93) , "Not Strong !!")
Test.assert_equals(strong_num(145), "STRONG!!!!")
Test.assert_equals(strong_num(185), "Not Strong !!")
Sample output:
Test Passed: Value == "STRONG!!!!"
Test Passed: Value == "STRONG!!!!"
Expected: "Not Strong !!", instead got: "STRONG!!!!"
Expected: "Not Strong !!", instead got: "STRONG!!!!"
Test Passed: Value == "STRONG!!!!"
Expected: "Not Strong !!", instead got: "STRONG!!!!"
Test Passed: Value == "STRONG!!!!"
Expected: "Not Strong !!", instead got: "STRONG!!!!"
Hope this helps!
I have tried to reduce the code by breaking it into pieces
Input: 145
def method_name(num)
array = num.to_s.chars.map(&:to_i) # => [1,4,5]
fact_arr = array.map {|f| fact(f)} # => [1, 24, 120]
if (num == fact_arr.inject(:+))
return "STRONG!!"
else
return "NOT STRONG!!"
end
end
def fact(n)
if (n == 0)
1
else
n * fact(n-1)
end
end
k.divmod(n) returns an array = [quocient_of_division(k/n), rest of division(k/n)]. Example: 145.divmod(1) returns =>[145, 0]. Also, digit-1.times in your code should be (digit-1).times
The way I thought that this could be done is like this:
def is_strong?(number)
result = 0
numbers = number.to_s.chars.map(&:to_i)
powers = { 0 => 1, 1 => 1, 2 => 2, 3 => 6, 4 => 24, 5 => 120, 6 => 760, 7 => 5040, 8 => 40320, 9 => 362880 }
numbers.each do |n|
result += powers[n]
end
return (result == number)
end

loop through ranges and custom outputs

puts 'Please insert a number between 1 and 100.'
num = gets.to_i
if (0..100).step(0) do |n|
# n = 10
# n = 20
# n = 30
# ...
puts 'Thanks. You inserted ' + num.to_s + '!'
# # using case
# case num2
# when 60
# puts "Student gets F grade"
# when 60..70
# puts "Student gets D grade"
# when 70..80
# puts "Student gets C grade"
# when 80..90
# puts "Student gets B grade"
# when 90..100
# puts "Student gets A grade"
# else
# puts "Grade not available for that value."
# end
else n => (100)
puts 'Please insert a number between 1 and 100.'
num = gets.to_i
puts 'Thanks. You inserted ' + num.to_s + '!'
end
the commented out code above is what I'm trying to eliminate and
accomplish with a for else loop in ruby.
Essentially I want to check if user enters a number within the
valid range (0 - 100) and then execute code associated with it, if user enters number outside of range to try again using else.
I want to spit out a letter grade correlating to the value entered.
So if valid value is entered -> get grade associated with -> else 'Please try again'. Any thoughts how to achieve this with a more
optimal loop, rather then my annoying multiple cases previous code?
update:
puts 'Please insert a number between 1 and 100.'
num = gets.to_i
while !num.between?(1, 100)
#num = gets.chomp.to_i
grade = loop do
puts 'Check your score!'
input = gets.to_i
case input
when 1..60
break 'F'
when 60..70
break 'D'
when 70..80
break 'C'
when 80..90
break 'B'
when 90..100
break 'A'
else
puts 'Please insert a VALID number between 1 and 100.'
num = gets.to_i
end
end
puts "Your grade is #{grade}"
end
I think you have the right idea with the case-expression. Just put it all into a loop and assign its return value to a variable. In the case-branches use break('grade')
grade = loop do
puts 'What\'s your score'
input = gets.to_i
case input
when 1..10
break 'F'
when 11..20
break 'E'
else
puts 'invalid score try again'
end
end
puts "Your grade is #{grade}"
This is one of many ways to obtain your desired result in a Ruby-like fashion.
NumberToLetter = [['F', 59], ['D', 69], ['C', 79], ['B', 89], ['A', 100]]
def letter_grade
num = number_grade
letter, _ = NumberToLetter.find { |_, n| num <= n }
[num, letter]
end
def number_grade
loop do
puts 'Please insert a number between 1 and 100.'
num = gets.to_i
break(num) if (1..100).cover?(num)
end
end
10.times { print letter_grade; puts }
# [43, "F"]
# [59, "F"]
# [60, "D"]
# [69, "D"]
# [70, "C"]
# [79, "C"]
# [80, "B"]
# [89, "B"]
# [90, "A"]
# [100, "A"]
The first element of each two-element array returned is the number entered by the user. The second is the associated grade.
I adopted the Ruby convention of representing a local variable that is not used in calculations with an underscore ('_'), which is in fact a valid variable name.
You're over-engineering this.
num = 0
while !num.between?(1, 100)
puts 'Please insert a number between 1 and 100.'
num = gets.chomp.to_i
end
puts "Thanks, #{num}"
It is simpler as you think, if now I understand, you just need to ask while the input of the user is in the range you want, if it is you skip the while and do what you want:
The full code would be:
puts 'Please insert a number between 1 and 100.'
num = gets.to_i
while not num.between?(0,100) do
puts 'Please insert a number between 1 and 100.'
num = gets.to_i
end
puts 'Thanks. You inserted ' + num.to_s + '!'
case num
when 60
puts "Student gets F grade"
when 60..70
puts "Student gets D grade"
when 70..80
puts "Student gets C grade"
when 80..90
puts "Student gets B grade"
when 90..100
puts "Student gets A grade"
else
puts "Grade not available for that value."
end

Ruby function to check if a number is divisible by five and is even

def is_even?(n)
remainder_when_divided_by_2 = n % 2
if remainder_when_divided_by_2 == 0
return true
else
return false
end
end
def is_odd?(n)
return ! is_even?(n)
end
puts "1 is_even? #{is_even?(1)} - is_odd? #{is_odd?(1)}"
puts "2 is_even? #{is_even?(2)} - is_odd? #{is_odd?(2)}"
puts "3 is_even? #{is_even?(3)} - is_odd? #{is_odd?(3)}"
puts "4 is_even? #{is_even?(4)} - is_odd? #{is_odd?(4)}"
puts "5 is_even? #{is_even?(5)} - is_odd? #{is_odd?(5)}"
puts "6 is_even? #{is_even?(6)} - is_odd? #{is_odd?(6)}"
def is_even_and_divisible_by_five?(n)
remainder_when_divided_by_five = n % 5
if (remainder_when_divided_by_five == 0) && (is_even?(n) == true)
return true
else
return false
end
end
puts "5 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(5)}"
puts "10 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(10)}"
puts "15 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(15)}"
puts "20 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(20)}"
puts "25 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(25)}"
puts "30 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(30)}"
The problem was I had not called the method is_even_and_divisible_by_five in the puts commands at the bottom of the code. I called it is_even_and_divisble_by_5. Then in the if statement in the is_even_and_divisble_by_five method, I left of the (n) arguement from Is_even. Thank you all very much!
Even (divisible by two) and divisible by five also means "divisible by ten":
def is_even_and_divisible_by_five?(n)
n % 10 == 0
end
You called
is_even_and_divisible_by_5?
instead of
is_even_and_divisible_by_five?
Also is_even? function is undefined. I guess there was some mistake made with its defining or maybe even not-defining. So maybe when you defined is_even_and_divisible_by_five?(n) function there were some other errors and It was not defined too. Plus I think here is much easier solution:
def is_even_and_divisible_by_five?(n)
n % 5 == 0 && n.even?
end
In Ruby You don't have to use return all the time. You should use it quite rarely. The reason is ruby functions return last calculated value by default. And nearly everything is returning value in ruby, even blocks and If-Else statements. If you open irb console and try to do some code, for example:
a = 5
=> 5
Second line is what first line returns. You can do some experiments like this by your own with any type of conditions you like.
The name of your method is is_even_and_divisible_by_five?, not is_even_and_divisible_by_5?.
is_even? is not defined by itself
Here a shorter version of your method
def is_even_and_divisible_by_five? n
0 == n % 5 + n % 2
end

undefined method (NoMethodError) ruby

I keep getting the following error message:
text.rb:2:in `<main>': undefined method `choices' for main:Object (NoMethodError)
But I can't seem to understand why my method is "undefined":
puts "Select [1] [2] [3] or [q] to quit"; users_choice = gets.chomp
choices(users_choice)
def choices (choice)
while choice != 'q'
case choice
when '1'
puts "you chose one!"
when '2'
puts "you chose two!"
when '3'
puts "you chose three!"
end
end
end
This is because you are calling method choices, before defining it. Write the code as below:
puts "Select [1] [2] [3] or [q] to quit"
users_choice = gets.chomp
def choices (choice)
while choice != 'q'
case choice
when '1'
break puts "you chose one!"
when '2'
break puts "you chose two!"
when '3'
break puts "you chose three!"
end
end
end
choices(users_choice)
I used break, to exit from the while loop. Otherwise it will create an infinite loop.
def main
puts "Select [1] [2] [3] or [q] to quit"; users_choice = gets.chomp
choices(users_choice)
end
def choices (choice)
while choice != 'q'
case choice
when '1'
puts "you chose one!"
break
when '2'
puts "you chose two!"
break
when '3'
puts "you chose three!"
break
end
end
end
main
The method only needs to be called prior to being executed. Here I wrap the definition in the main method, but only call main after the definition of choices().
I was getting the same error running Ruby in Eclipse working out the App Academy practice exercises. I forgot to add "object." to the supplied test cases. The following syntax works:
#!/usr/bin/ruby
class Prime
# Write a method that takes in an integer (greater than one) and
# returns true if it is prime; otherwise return false.
#
# You may want to use the `%` modulo operation. `5 % 2` returns the
# remainder when dividing 5 by 2; therefore, `5 % 2 == 1`. In the case
# of `6 % 2`, since 2 evenly divides 6 with no remainder, `6 % 2 == 0`.
# More generally, if `m` and `n` are integers, `m % n == 0` if and only
# if `n` divides `m` evenly.
#
# You would not be expected to already know about modulo for the
# challenge.
#
# Difficulty: medium.
def primer(number)
if number < 2
return false
end
i = 10
while i > 1
if number > i && number != i
if number % i == 0
return false
end
end
i -= 1
end
return true
end
end
object = Prime. new
# These are tests to check that your code is working. After writing
# your solution, they should all print true.
puts("\nTests for #primer")
puts("===============================================")
puts('primer(2) == true: ' + (object.primer(2) == true).to_s)
puts('primer(3) == true: ' + (object.primer(3) == true).to_s)
puts('primer(4) == false: ' + (object.primer(4) == false).to_s)
puts('primer(9) == false: ' + (object.primer(9) == false).to_s)
puts("===============================================")

How to add a message to next if statement in ruby

How to combine next with puts "#{web_url.status[0].to_i} together and display it in console but only if if part is true.
tried:
next if ... && puts "{web_url.status[0].to_i}"
web_url = open(url, :proxy => BaseParser::PROXY, "User-Agent" => BaseParser.rand_ua_string() )
next if web_url.nil?
next if web_url.status[0].to_i == 410
next if web_url.status[0].to_i == 310
next if web_url.status[0].to_i == 404
next if web_url.status[0].to_i == 530
Here it is :
next puts "#{web_url.status[0].to_i}" if x == 2 # expression here
Example :
x = 1
until x > 3
next puts("#{x} matched"),x+=1 if x == 2
puts "this iteration has number #{x}"
x += 1
end
# >> this iteration has number 1
# >> 2 matched
# >> this iteration has number 3
Go through the documentation keywords.

Resources