Skip to content

Instantly share code, notes, and snippets.

@ara-ta3

ara-ta3/Makefile Secret

Created December 11, 2016 09:49
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 ara-ta3/3e3a97380a56f4fbb016f51e938c2c57 to your computer and use it in GitHub Desktop.
Save ara-ta3/3e3a97380a56f4fbb016f51e938c2c57 to your computer and use it in GitHub Desktop.
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