Skip to content

Instantly share code, notes, and snippets.

@hchood
Last active December 28, 2015 19:09
Show Gist options
  • Save hchood/7548554 to your computer and use it in GitHub Desktop.
Save hchood/7548554 to your computer and use it in GitHub Desktop.
Ruby Fundamentals III - Challenge
# Ruby Fundamentals III - Challenge
# NOTE: I worked on this with Jonah and then refactored on my own.
# METHOD DEFINITIONS
def get_input(prompt)
puts prompt
input = gets.chomp.to_f
end
def validate_input(input, regex, error_message)
while input.to_s.match(regex)
puts error_message
input = gets.chomp.to_i
end
input
end
def valid?(price)
if price.match(/\A\d+(\.\d{0,2})?\z/)
true
end
end
def calc_subtotals(array)
array.each do |hash|
hash[:subtotal] = hash[:quantity] * hash[:price]
end
end
def total(array)
array = calc_subtotals(array)
products = []
array.each {|hash| products << hash[:subtotal]}
products.inject(0) {|total, num| total + num}
end
# INITIALIZED VARIABLES
sales = [{type: "Light", price: 5.00, quantity: 0, subtotal: 0},
{type: "Medium", price: 7.50, quantity: 0, subtotal: 0},
{type: "Bold", price: 9.75, quantity: 0, subtotal: 0}]
# PROGRAM
puts "Welcome to James' coffee emporium!\n\n"
puts "1) Add item - $5.00 - Light Bag"
puts "2) Add item - $7.50 - Medium Bag"
puts "3) Add item - $9.75 - Bold Bag"
puts "4) Complete Sale\n\n"
# PART 1: gets input (items & quantity sold), puts subtotal
while true
selection = get_input("Make a selection:").to_i
selection = validate_input(selection, /[^1-4]/, "Please enter a selection 1 through 4.")
break if selection == 4
quantity = get_input("How many bags:").to_i
quantity = validate_input(quantity, /\D/, "Please enter a number.")
sales[selection - 1][:quantity] += quantity
subtotal = total(sales)
puts "Subtotal: $#{sprintf("%.2f", subtotal)}\n\n"
end
if total(sales) == 0
puts "You did not sell anything. Goodbye!"
exit
end
# PART 2: when finished adding sales, output subtotals & total due
puts "\n===Sale Complete===\n\n"
sales.each do |item|
puts "$#{sprintf("%.2f", item[:subtotal])} - #{item[:quantity]} #{item[:type]}\n" unless item[:subtotal] == 0
end
puts "\nTotal: $#{sprintf("%.2f", subtotal)}\n\n"
# PART 3: calculates change
amount_due = subtotal
amount_tendered = get_input("What is the amount tendered?")
if valid?(amount_tendered.to_s)
amount_tendered = amount_tendered.to_f
else
puts "WARNING: Invalid currency detected! Exiting..."
abort
end
total_change_due = amount_tendered - amount_due
total_change_due_formatted = sprintf("%.2f", total_change_due.abs)
if total_change_due >= 0
current_time = Time.now.strftime("%m/%d/%Y %l:%M %p")
puts "\n===Thank You!==="
puts "The total change due is $#{total_change_due_formatted}"
puts
puts "#{current_time}"
puts "================"
else
puts "WARNING: Customer still owes $#{total_change_due_formatted}! Exiting..."
abort
end
@jchuang
Copy link

jchuang commented Nov 21, 2013

I've run this program a few times, and I think Part 3 doesn't correctly calculate change when the amount due isn't a whole dollar value. If I buy 2 of each item, the subtotal is $66.75, but then if the customer pays $66.75, it says the customer still owes $0.75.

On the other hand, the functions at the top are beautiful. Yay for pair refactoring! It's really nice to see how others approached the same problem.

@hchood
Copy link
Author

hchood commented Nov 23, 2013

Thanks! I updated it so it works. (I was converting the input I got in my get_input method to an integer, which rounded down the amount_tendered. I changed my get_input method to return a float, and then converted selection & quantity to_i when I called get_input on lines 56 & 60.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment