Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialMaximiliane Quel
Courses Plus Student 55,489 PointsImproving the script for the user prompted average?
Hi,
I have tried the extra credit question and am would like to know if anyone can make it even more efficient? It would be really great to have feedback and/or to see other solutions to learn from them.
Here is my solution:
def user_answer
print "Please enter a number (or press another key to finish): "
gets.chomp
end
def numeric? test
#ternary operator: expression ? if-true : if-false
test.match(/\d/) == nil ? false : true
end
def create_arr
arr = []
input = user_answer
while numeric? input
arr = arr.push input.to_f
input = user_answer
end
return arr
end
x = create_arr
sum = x.inject 0, &:+
average = sum / x.length
puts "You entered the numbers #{x}. The average is #{average}."
Thanks ?
2 Answers
Jay McGavren
Treehouse TeacherMaximiliane Quel this is great! This already goes way beyond the parameters of the extra credit. I like the use of arrays, and the fact that it can accept any length of array, not just 4. And using inject
is super-advanced! That's one I don't use very often myself.
There are always improvements to be made, though. Ready? Some of this will be advanced. Look up what you can, ask me questions about what you can't.
One improvement is to use the =~
operator with your regular expression, which will make it so you no longer need to call match
. This will work just like your existing numeric?
method:
def numeric? test
test =~ /\d/
end
Another improvement is to use the printf
function to round the output the a reasonable number of decimal places.
printf("You entered the numbers %s. The average is %0.2f.\n", x, average)
Regular expressions in general are slow, so it's better to avoid matching when possible. If to_f
returns a number other than 0
, we can be certain the input was numeric (or that it started with a number, at least). If to_f
returns 0
, the input could be non-numeric. Or, it could be that the user input was 0
or 0.0
. If we do a regular expression test on the input only when the result is 0
, we'll do the matching much less often, which is more efficient.
Returning nil
makes it clear that convert_to_f
was unsuccessful. nil
is treated as false, a sign we should break out of our loop.
def user_answer
print "Please enter a number (or press another key to finish): "
gets.chomp
end
def convert_to_f(input)
# Attempt to convert string to a Float.
float = input.to_f
# If we got 0, and the input was not "0" or "0.0", return nil.
if float == 0 && input !~ /\A0\.?0?\Z/
return nil
# Otherwise, return whatever number we got from to_f.
else
return float
end
end
def create_arr
arr = []
loop do
input = user_answer
# Attempt to convert the input to a Float.
number = convert_to_f(input)
# If nil was returned, it wasn't a number, so exit the loop.
break unless number
# Otherwise, appent the number to the array and continue.
arr = arr.push number
end
return arr
end
x = create_arr
sum = x.inject 0, &:+
average = sum / x.length
printf("You entered the numbers %s. The average is %0.2f.\n", x, average)
You probably have questions. :) Ask away!
rhupp
11,019 PointsThis isn't even my question, but thank you both very much. Way over my head at the moment, but I look forward to coming back and understanding all of this. Meanwhile, I was able to complete the extra credit as well, but nowhere near as elegantly.
# My approach to the extra credit was likely more complicated than it needed to be.
# Apologies in advance for the newbie code. :)
puts "*** Welcome to ~Averages~, where everyone can be anyone. ***"
print "Please enter the amount of numbers you will be averaging: "
numbers = gets().to_i
counter = numbers
print "Okay. You may enter the first number: "
x = gets().chomp
total = x.to_f
while counter > 1
print "And the next? "
y = gets().to_f
total += y
counter -= 1
end
average = total / numbers
puts "\nYou entered #{numbers} numbers...\n...the sum of which is #{total.to_i.round(2)}..."
puts "...the average of which is #{average.round(2)}."
puts "\nHave an average day..."
# Here is sample output:
#
# *** Welcome to ~Averages~, where everyone can be anyone. ***
# Please enter the amount of numbers you will be averaging: 3
# Okay. You may enter the first number: 90
# And the next? 87
# And the next? 98
#
# You entered 3 numbers...
# ...the sum of which is 275.0...
# ...the average of which is 91.67.
#
# Have an average day...
So...yeah. I was just glad it worked, but thanks, @Maximiliane Quel, for giving me something to aspire to! Thanks as well to Jay McGavren for taking it up another notch. I had a feeling you were keeping things deceptively simple, and to be honest was feeling a bit bored. Glad to know I have much, much to learn.
Cheers!
Maximiliane Quel
Courses Plus Student 55,489 PointsMaximiliane Quel
Courses Plus Student 55,489 PointsThat's exactly what I was looking for. Thanks very much. It helps seeing how someone else would solve it and getting this kind of feedback. I found the most challenging part was finding a way let people finish inputting numbers and your solution with the break condition is great. Really appreciated.
I also didn't know I could improve performance by avoiding tests for regular expressions. And I hardly ever used printf but will probably use it in the future.