Create a gist now

Instantly share code, notes, and snippets.

@ara-ta3 /Makefile Secret
Created Dec 11, 2016

CTO Challenge 2016 2nd LV2
from typing import List, Dict
from functools import reduce
from collections import Counter
from menu import Menu
Coupon = int
class CouponSelector():
def __init__(self,
limitation_of_coupons: Dict[Coupon, int],
coupons_available_for_pizza: List[Coupon],
lowest_amount_for_using_coupon: int
) -> None:
self.limitation_of_coupons = limitation_of_coupons
self.coupons_available_for_pizza = coupons_available_for_pizza
self.lowest_amount_for_using_coupon = lowest_amount_for_using_coupon
def select_optimum_combination_by_menus(
self,
menus: List[Menu],
coupons: List[Coupon]):
amount = reduce(lambda amount, m: amount + m.price, menus, 0)
available_coupons = _filter_limited_coupons(
coupons,
self.limitation_of_coupons
)
if not _pizza_exists(menus):
available_coupons = [c for c in available_coupons
if c not in self.coupons_available_for_pizza]
return self.select_optimum_combination(amount, available_coupons)
def select_optimum_combination(self, amount: int, coupons: List[Coupon]):
if amount <= self.lowest_amount_for_using_coupon:
return []
sorted_coupons = sorted(coupons, reverse=True)
rest = amount
used_coupons = []
for c in sorted_coupons:
if rest < c:
break
rest -= c
used_coupons.append(c)
return used_coupons
def _pizza_exists(menus: List[Menu]):
return any(m.is_pizza() for m in menus)
def _filter_limited_coupons(
coupons: List[Coupon],
coupon2limit: Dict[Coupon, int]):
counter = Counter(coupons)
for c, n in counter.items():
counter[c] = min(coupon2limit[c], n)
return list(counter.elements())
from coupon_selector import CouponSelector
coupon_selector = CouponSelector({}, [], 1000)
def test_select_optimum_combination_case1():
selected = coupon_selector.select_optimum_combination(
1000,
[500, 500, 200, 100, 100, 100]
)
assert selected == []
def test_select_optimum_combination_case2():
selected = coupon_selector.select_optimum_combination(1210, [])
assert selected == []
def test_select_optimum_combination_case3():
selected = coupon_selector.select_optimum_combination(
1210,
[500, 500, 200, 100, 100, 100]
)
assert selected == [500, 500, 200]
def test_select_optimum_combination_case4():
selected = coupon_selector.select_optimum_combination(
1530,
[500, 500, 200, 100, 100, 100]
)
assert selected == [500, 500, 200, 100, 100, 100]
def test_discounted_in_order_when_coupons_are_not_sorted():
selected = coupon_selector.select_optimum_combination(
1530,
[500, 200, 100, 500, 100, 100]
)
assert selected == [500, 500, 200, 100, 100, 100]
from coupon_selector import CouponSelector
from menu import PizzaMenu, SideMenu
coupon_selector = CouponSelector(
{500: 2, 200: 2, 100: 3, 400: 1},
[400],
1000
)
def test_select_optimum_combination_by_menu_case1_on_lv2():
menus = [PizzaMenu("ジェノベーゼ", "M", 1000)]
selected = coupon_selector.select_optimum_combination_by_menus(
menus,
[500, 200, 100, 400]
)
assert selected == []
def test_select_optimum_combination_by_menu_case2_on_lv2():
menus = [PizzaMenu("マルゲリータ", "M", 1200)]
selected = coupon_selector.select_optimum_combination_by_menus(
menus,
[]
)
assert selected == []
def test_select_optimum_combination_by_menu_case3_on_lv2():
menus = [
SideMenu("ポテトフライ", 400),
SideMenu("ポテトフライ", 400),
SideMenu("シーザーサラダ", 600)
]
selected = coupon_selector.select_optimum_combination_by_menus(
menus,
[500, 500, 200, 100, 100, 400]
)
assert selected == [500, 500, 200, 100, 100]
def test_select_optimum_combination_by_menu_case4_on_lv2():
menus = [PizzaMenu("ジェノベーゼ", "L", 1400)]
selected = coupon_selector.select_optimum_combination_by_menus(
menus,
[500, 500, 200, 100, 100, 400]
)
assert selected == [500, 500, 400]
def test_select_optimum_combination_by_menu_case5_on_lv2():
menus = [PizzaMenu("ジェノベーゼ", "M", 1000), PizzaMenu("マルゲリータ", "M", 1200)]
selected = coupon_selector.select_optimum_combination_by_menus(
menus,
[500, 500, 500, 200, 200, 200, 100, 100, 100, 100, 400, 400]
)
assert selected == [500, 500, 400, 200, 200, 100, 100, 100]
pip=bin/pip
python=bin/python
flake8=bin/flake8
pytest=bin/pytest
run: $(python)
$< main.py -c $(cs) -m $(ms)
test: $(pytest)
$< -v ./lv1_test.py ./lv2_test.py
install: $(pip)
$< install -r requirements.txt
$(pytest): $(pip)
$(MAKE) install
$(python):
virtualenv . -p python3
$(pip):
virtualenv . -p python3
clean:
rm -rf ./bin
rm -rf ./lib
rm -rf ./include
from typing import Dict, List, Tuple
class Menu(object):
def __init__(self, name, price):
self.name = name
self.price = price
def is_pizza(self):
return type(self) == PizzaMenu
class PizzaMenu(Menu):
def __init__(self, name, size, price):
super(PizzaMenu, self).__init__(name, price)
self.size = size
class SideMenu(Menu):
def __init__(self, name, price):
super(SideMenu, self).__init__(name, price)
not_found_menus.append(name)
pytest
flake8
mypy-lang
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment