Skip to content

Instantly share code, notes, and snippets.

@edvardm
Created December 10, 2012 11:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edvardm/4250114 to your computer and use it in GitHub Desktop.
Save edvardm/4250114 to your computer and use it in GitHub Desktop.
potter kata
class Memo
def initialize; @memo = {}; end
def ized(key, &block); (k = @memo[key]) ? k : @memo[key] = block.call; end
end
class Harry
NSLOTS = 5
DISCOUNTS = [0, 0, 0.05, 0.10, 0.20, 0.25]
UNIT_PRICE = 8
def self.compute_masks
def self.mask_to_array(mask); (0...NSLOTS).map { |i| 1 & (mask >> i) }.reverse; end
(1..(2**NSLOTS)-1).map { |m| mask_to_array(m) }
end
MASKS = compute_masks
def sum(a); a.inject(0) {|acc, i| acc+i}; end
def initialize; @memo = Memo.new; end
def price(bs)
@memo.ized(bs.sort) do
sum(bs).zero? ? 0 : MASKS.select { |s| valid_picks(bs, s) }.map { |s| discounted(sum(s)) + price(pick_books(bs, s)) }.min
end
end
def valid_picks(books, s); pick_books(books, s).all? { |i| i >= 0 }; end
def pick_books(books, selection); books.zip(selection).map { |orig_count, i| orig_count - i }; end
def discounted(uniq_count); (1-DISCOUNTS[uniq_count]) * UNIT_PRICE * uniq_count; end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment