Back to the Checkout

A solution to Back to the Checkout kata described at CodeKata.

Solution

""" checkout.py """

# usage: python3 checkout.py


class Checkout():
    """ simulate a checkout """
    def __init__(self, pricing_rules):
        self.pricing = pricing_rules
        self.goods = {}

    def scan(self, item):
        """ add item to purchases """
        self.goods[item] = self.goods.get(item, 0) + 1

    def price(self, goods):
        """ total price of goods """
        self.goods = {}
        for item in goods:
            self.scan(item)
        return self.total()

    def total(self):
        """ total price of self.goods """
        total = 0
        for item, purchased_qty in self.goods.items():
            pricing = self.pricing[item]
            remaining_qty = purchased_qty
            for qty, price in sorted(pricing, reverse=True):
                while remaining_qty > 0:
                    if remaining_qty >= qty:
                        remaining_qty -= qty
                        total += price
                    else:
                        break
        return total


if __name__ == '__main__':

    prices = {'A': [(1, 50), (3, 130)],
              'B': [(1, 30), (2, 45)],
              'C': [(1, 20)],
              'D': [(1, 15)]}

    co = Checkout(prices)

    assert co.price('') == 0
    assert co.price('A') == 50
    assert co.price('AB') == 80
    assert co.price('CDBA') == 115

    assert co.price('AA') == 100
    assert co.price('AAA') == 130
    assert co.price('AAAA') == 180
    assert co.price('AAAAA') == 230
    assert co.price('AAAAAA') == 260

    assert co.price('AAAB') == 160
    assert co.price('AAABB') == 175
    assert co.price('AAABBD') == 190
    assert co.price('DABABA') == 190

    co = Checkout(prices)

    assert co.total() == 0
    co.scan('A')
    assert co.total() == 50
    co.scan('B')
    assert co.total() == 80
    co.scan('A')
    assert co.total() == 130
    co.scan('A')
    assert co.total() == 160
    co.scan('B')
    assert co.total() == 175

    print('tests passed')