Skip to content

Instantly share code, notes, and snippets.

@sneakin
Created July 22, 2010 01:08
Show Gist options
  • Save sneakin/485433 to your computer and use it in GitHub Desktop.
Save sneakin/485433 to your computer and use it in GitHub Desktop.
require 'spec'
require 'active_support'
class Rule < Struct.new(:quantity, :price)
def apply(number)
[ number / quantity * price, number % quantity ]
end
end
class CheckOut < Struct.new(:rules, :items)
def initialize(rules)
super(rules, Hash.new)
end
def scan(item)
items[item] ||= 0
items[item] += 1
end
def total
items.inject(0) { |acc, (item, quantity)|
acc += total_for(quantity, item)
}
end
private
def total_for(quantity, item)
remaining = quantity
rules[item].inject(0) do |acc, rule|
subtotal, remaining = rule.apply(remaining)
acc += subtotal
end
end
end
describe CheckOut do
subject do
rules = {
"A" => [ Rule.new(4, 140), Rule.new(3, 130), Rule.new(1, 50) ],
"B" => [ Rule.new(2, 45), Rule.new(1, 30) ],
"C" => [ Rule.new(1, 20) ],
"D" => [ Rule.new(1, 15) ]
}
described_class.new(rules)
end
describe '#total' do
{ "" => 0,
"A" => 50,
"AB" => 80,
"CDBA" => 115,
"AA" => 100,
"AAA" => 130,
"AAAA" => 140,
"AAAAA" => 190,
"AAAAAA" => 240,
"AAAB" => 160,
"AAABB" => 175,
"AAABBD" => 190,
"DABABA" => 190
}.each do |items, total|
context "after scanning #{items.inspect}" do
it "returns #{total}" do
items.split(//).each { |i| subject.scan(i) }
subject.total.should == total
end
end
end
it "changes after scanning an item" do
subject.total.should == 0
subject.scan("A")
subject.total.should == 50
subject.scan("B")
subject.total.should == 80
subject.scan("A")
subject.total.should == 130
subject.scan("A")
subject.total.should == 160
subject.scan("B")
subject.total.should == 175
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment