Nested Loop Ruby Answer [closed] - ruby

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 3 years ago.
Improve this question
Need assistance saving and totaling the "rainfall input" after the loop has ended. Any advice would be appreciated.
puts "How many years"
years_input = gets.to_i
for years_input in (1..years_input)
puts "Years Passed: Years = " + years_input.to_s
for m in (1..12)
puts "Month: Month # = " + m.to_s
puts "Inches of rainfall"
rainfall_input = gets.to_i
end
end
puts "Total Months"
puts (years_input * 12).to_s
puts "Total Rainfall"

You need to have a place to store your "counter" in this case the total:
puts "How many years"
years_input = gets.to_i
total_rainfall = 0
for years_input in (1..years_input)
puts "Years Passed: Years = " + years_input.to_s
for m in (1..12)
puts "Month: Month # = " + m.to_s
puts "Inches of rainfall"
total_rainfall += gets.to_i
end
end
puts "Total Months"
puts (years_input * 12).to_s
puts "Total Rainfall"
puts total_rainfall

#Danilo has answered your question, so let me suggest how you might write your code in a more Ruby-like way. Let me first mention that for loops are never used by Ruby coders. Instead we use enumerators (like each and, here, times and sum) and blocks. That's in part to hide information within blocks to avoid it being seen by prying eyes outside the block.
require 'date'
puts "How many years?"
nbr_years = gets.to_i
puts "Number of years: #{nbr_years}"
nbr_years.times do
puts "Which year?"
y = gets.to_i
tot = (1..12).sum do |m|
puts "How many inches of rainfall in #{Date::MONTHNAMES[m]}, #{y}?"
gets.to_f
end
puts "Total rainfall in #{y} was #{tot} inches"
end
#{nbr_years} in "Number of years: #{nbr_years}" converts nbr_years to a string by computing nbr_years.to_s. (See Integer#to_s). It's called string interpolation. If nbr_years were an array, Array#to_s would be applied, and so on.
Search for "MONTHNAMES" in Date and you will find that Date::MONTHNAMES (among several date-related constants) has been defined for your convenience:
Date::MONTHNAMES
#=> [nil, "January", "February", "March", "April", "May", "June",
# "July", "August", "September", "October", "November", "December"]
In pure Ruby we need include 'date' to access that constant (no need for that with Rails).
nil is just a placekeeper. Date::MONTHNAMES[0] is never referenced by coders.
Note that for inches of rainfall per month you want gets.to_f rather than gets.to_i.
We can simulate this code by replacing the gets statements with generated values.
y = 2015
puts "How many years?"
nbr_years = 2
puts "Number of years: #{nbr_years}"
nbr_years.times do
puts
puts "Which year?"
y += 1
tot = (1..12).sum do |m|
puts "How many inches of rainfall in #{Date::MONTHNAMES[m]}, #{y}?"
f = (10 * rand).round(2)
puts "#{f} inches of rainfall in #{Date::MONTHNAMES[m]}, #{y}?"
f
end
puts "Total rainfall in #{y} was #{tot} inches"
end
The following (after minor editing) is displayed.
Which year?
How many inches of rainfall in January, 2016?
3.12 inches of rainfall in January, 2016?
How many inches of rainfall in February, 2016?
2.64 inches of rainfall in February, 2016?
...
How many inches of rainfall in December, 2016?
4.48 inches of rainfall in December, 2016?
Total rainfall in 2016 was 60.71 inches
Which year?
How many inches of rainfall in January, 2017?
7.15 inches of rainfall in January, 2017?
...
How many inches of rainfall in December, 2017?
7.87 inches of rainfall in December, 2017?
Total rainfall in 2017 was 36.31 inches

Related

Ruby - How do you add data into a nested array?

I'm relatively new to Ruby and I'm trying to design a code that will help me with work.
What I would like the code to do is allow the user to input the "invoice numbers" for each day of the week starting on Monday, then when the user has finished entering the invoice numbers, the program should ask how many hours were worked for each day. Then, I would like for the program to divide the amount of hours worked by the amount of invoice numbers inputted for each respective day and output the "billable time" in a format like this:
say Monday worked 10 hours and you inputted invoice #123 and #124
The program should output the following -
Monday
#123 - 5 Hours
#124 - 5 Hours
but I would like for this to happen for every day of the week. I'm assuming I'll need to use a nested Array but I'm just confused as to how to go about adding the entries from the user and having the program know when to "move" to the next day to add the next set of entries.
Here is the code I have so far:
days = ["Mon","Tue","Wed","Thurs","Fri","Sat","Sun"]
entry = Array.new
days.each do |day|
while entry != "ok"
puts "Enter PR # for " + day
puts "/n Type 'ok' when finished"
entry.each do |input|
input << gets.to_s.chomp
end
end
end
Essentially I would just like for the program to recognize that the user is done inputting entries for that day by typing "ok" or something so that it can move from Monday to Tuesday, etc.
In a perfect world... at the end of the sequence, I would like for the program to combine the values of all similarly named invoice numbers from each day into one result (i.e. if invoice #123 applied on Monday and Tuesday, the program would add the sums of the billable hours from those two days and output the result as one total billable amount.)
Thank you in advance for any assistance with this as the knowledge that comes with it will be deeply valued!!
You might collect the needed information as follows.
DAYS = ["Mon", "Tue", "Wed", "Thurs", "Fri", "Sat", "Sun"]
def invoices_by_day
DAYS.each_with_object({}) do |day, inv_by_day|
prs = []
loop do
puts "Enter PR # for #{day}. Press ENTER when finished"
pr = gets.chomp
break if pr.empty?
prs << pr
end
hours =
if prs.any?
puts "Enter hours worked on #{day}"
gets.to_f
else
0
end
inv_by_day[day] = { prs: prs, hours: hours }
end
end
Suppose
h = invoices_by_day
#=> { "Mon"=>{ prs: ["123", "124"], hours: 21.05 },
# "Tue"=>{ prs: ["125"], hours: 31.42 },
# "Wed"=>{ prs: ["126", "127"], hours: 68.42 },
# "Thu"=>{ prs: ["128"], hours: 31.05 },
# "Fri"=>{ prs: [], hours: 0 },
# "Sat"=>{ prs: ["129", "130"], hours: 16.71 }
# "Sun"=>{ prs: ["131"], hours: 55.92 } }
Then you could display this information in various ways, such as the following.
h.each do |day, g|
puts day
if g[:prs].empty?
puts " No invoices"
else
avg = (g[:hours]/g[:prs].size).round(2)
g[:prs].each { |pr| puts " ##{pr}: #{avg}" }
end
end
Mon
#123: 10.53
#124: 10.53
Tue
#125: 31.42
Wed
#126: 34.21
#127: 34.21
Thurs
#128: 31.05
Fri
No invoices
Sat
#129: 8.36
#130: 8.36
Sun
#131: 55.92
As a rule it is good practice to separate the data collection from the manipulation of the data and the presentation of the results. That makes it easier to change either at a later date.
I use Kernel#loop with break for virtually all looping. One advantage of loop is that employs a block (unlike while and until), confining the scope of local variables created within the block to the block. Another advantage is that it handles StopIteration exceptions by breaking out of the loop. That exception is raised by an enumerator when it attempts to generate an element beyond its last value. For example, if e = 3.times #=> #<Enumerator: 3:times>, then e.next #=> 0, e.next #=> 1 e.next #=> 2, e.next #=> StopIteration.
Hey – here you go –> https://gist.github.com/Oluwadamilareolusakin/4f147e2149aa97266cfbb17c5c118fbf
Made a gist for you that may help, let me know!
NOTE: Be careful with the while true so you don't run into an infinite loop
Here's it is for easy reference:
# frozen_string_literal: true
def display_billable_hours(entries)
entries.each do |key, value|
puts "#{key}:"
puts value
end
end
def handle_input
days = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]
entries = {}
days.each do |day|
loop do
p "Enter your invoice number for #{day}:"
invoice_number = gets.chomp
break if invoice_number.length > 0
end
loop do
p "How many hours did you work on #{day}?:"
hours_worked = gets.chomp
break if hours_worked.length > 0
end
entries[day] = "##{invoice_number} - #{hours_worked} Hours"
end
entries
end
def do_audit
entries = handle_input
display_billable_hours(entries)
end
do_audit

I don't understand what's wrong with this simple Ruby code

I wrote this program to ask users for their age, and then tell them how old they will be in 10-50 years. I don't understand what's wrong with it :( I'm just a beginner and any help would be greatly appreciated.
print "How old are you?"
age = gets.chomp
i = 1
while i < 6
multiple = i * 10 + age
puts "In #{multiple} years you will be #{multiple}"
i++
end
Many ways to accomplish what you're trying to do. Make sure you're indenting blocks correctly - it'll make your code much more readable. Note that to_i converts your input from a String to an Integer. Also, try to name your variables more specifically; multiple doesn't really mean anything in your example.
puts "How old are you?"
age = gets.chomp.to_i
(1..5).each do |i|
years_passed = i * 10
new_age = years_passed + age
puts "In #{years_passed} years you will be #{new_age}"
end
If you want to use a while loop, you could do:
puts "How old are you?"
age = gets.chomp.to_i
multiplier = 1
while multiplier <= 5
years_passed = multiplier * 10
new_age = years_passed + age
puts "In #{years_passed} years you will be #{new_age}"
multiplier += 1
end

I can't multiply decimals, in ruby

I'm making a interest calculator
I go 10 * .10 * 10 and i get 0 so how do i multiply a decimal without it being 0?
my source code is
def interest()
puts "Type the original loan."
loan = gets.chomp.to_i
puts "Type the amount of interest in decimal."
interest = gets.chomp.to_i
puts "How many years?"
years = gets.chomp.to_i
puts "Your interest is"
puts loan * interest * years
end
interest()
You've got integers there, so result will be an integer too. You could use 'to_f but beware, it's not good for dealing with money or anything else needing precision. Use BigDecimal instead:
require 'bigdecimal'
def interest
puts "Type the original loan."
loan = BigDecimal(gets.chomp)
puts "Type the amount of interest in decimal."
interest = BigDecimal(gets.chomp)
puts "How many years?"
years = BigDecimal(gets.chomp) # suggested in comment, agreed with that
puts "Your interest is"
puts loan * interest * years
end
What's the difference between them?
Do this
interest = gets.chomp.to_f
.to_i changes the string to an integer. An integer is a WHOLE number.
.to_f is to float, a float is a number that allows decimal places
The problem is that you're using .to_i when you don't really want to use integers here. Integers are represented without decimal parts to them, and therefore when you call .10.to_i it truncates it to 0.
Consider using floats by .to_f instead

currency converter in ruby [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 9 years ago.
Improve this question
Been straggling for couple of hours with my work of creating a converter. it should convert from one currency to the other
this is the code:
def converter
puts "Enter the amount you wish to convert"
userAmount = gets
puts "Enter your choice: 1 for converting Qatari
Riyals to US Dollars"
puts "Enter your choice: 2 for converting USD ollars to Qatari Riyals"
choiceConvert = gets
while choiceConvert != 1 || choiceConvert != 2 do
puts "please enter either 1 or 2"
choiceConvertNew = gets
choiceConvert = choiceConvertNew
end
if choiceConvert == 1
convertedAmount = userAmount / 3.65
puts "Your choice is to convert #{userAmount} Qatari Riyals to US Dollars;
You get #{convertedAmount} US Dollars"
else
convertedAmount = userAmount * 3.65
puts "Your choice is to convert #{userAmount} US Dollars to Qatari Riyals;
You get #{convertedAmount} Qatari Riyals"
end
end
converter
You are trying to do to much in one place try this
def convert_currency(amount,choice)
converted_amount = choice == 1 ? amount / 3.65 : amount * 3.65
from, to = choice == 1 ? ["Qatari Riyals", "US Dollars"] : ["US Dollars","Qatari Riyals"]
puts "Your choice is to convert #{sprintf('%.2f',amount)} #{from} to #{to}; You get #{sprintf('%.2f',converted_amount)} #{to}"
end
puts "Please Enter an Amount"
user_amount = gets.to_f
choice_convert = nil
while ![1,2].include?(choice_convert)
puts "Enter your choice: 1 for converting Qatari Riyals to US Dollars"
puts "Enter your choice: 2 for converting US Dollars to Qatari Riyals"
choice_convert = gets.to_i
end
convert_currency(user_amount,choice_convert)

Using Loops for prompts with If/Else/Esif

I started with:
puts "Hello there, and what's your favorite number?"
favnum = gets.to_i
puts "Your favorite number is #{favnum}?" " A better favorite number is #{favnum + 1}!"
puts "Now, what's your favorite number greater than 10?"
favnumOverTen = gets.to_i
if favnumOverTen < 10
puts "Hey! I said GREATER than 10! Try again buddy."
else
puts "Your favorite number great than 10 is #{favnumOverTen}?"
puts "A bigger and better number over 10 is #{favnumOverTen * 10}!"
puts "It's literally 10 times better!"
end
That worked fine, but if the user entered a number less than 10 the program ended.
I want the user to be prompted to try again until they enter a number greater than 10.
Am I supposed to do that with a loop?
Here's what I took a swing at, but clearly it's wrong:
puts "Hello there, and what's your favorite number?"
favnum = gets.to_i
puts "Your favorite number is #{favnum}?" " A better favorite number is #{favnum + 1}!"
puts "Now, what's your favorite number greater than 10?"
favnumOverTen = gets.to_i
if favnumOverTen < 10
loop.do
puts "Hey! I said GREATER than 10! Try again buddy."
favnumOverTen = gets.to_i
until favnumOverTen > 10
else
puts "Your favorite number great than 10 is #{favnumOverTen}?"
puts "A bigger and better number over 10 is #{favnumOverTen * 10}!"
puts "It's literally 10 times better!"
end
Here's a way that's a little shorter than the previous two:
puts "Now, what's your favorite number greater than 10?"
until (favnumOverTen = gets.to_i) > 10
puts "Hey! I said GREATER than 10! try again buddy."
end
This works because assignment returns the value assigned to the variable.
A better solution would be to get the favorite number of 10 once, then start an until loop checking for favnumOverTen > 10 like this:
puts "What is your favorite number greater than 10?"
favnumOverTen = gets.to_i
until favnumOverTen > 10 do
puts "Hey! I said GREATER than 10! Try again buddy."
favnumOverTen = gets.to_i
end
This way, if the initial entry is greater than 10, the until loop is never executed (saves you the if statement).
Also, just so you're aware, it's not considered idiomatic Ruby to write variable names using camel case (i.e. favnumOverTen should be favnum_over_ten).

Resources