import sys
import itertools
from bisect import bisect_right
def parse_input():
"""
Returns a couple: the objective calories and a list of
restaurants (name, calories)
"""
objective = int(sys.stdin.readline())
restaurants = []
for line in sys.stdin.readlines():
name, cal = (x.strip('" \n') for x in line.split('='))
cal = int(cal)
restaurants.append((name, cal))
return objective, restaurants
def naive_create_schedule(objective, restaurants, days=5):
"""
Returns the schedule: the calories that we will eat this week and the
list of restaurants that are the closest to our objective
"""
assert(days <= len(restaurants))
sol_value = 0
sol_names = []
for restaurants in itertools.combinations(restaurants, days):
calories = sum(restaurant[1] for restaurant in restaurants)
if abs(objective - calories) < abs(objective - sol_value):
sol_value = calories
sol_names = [restaurant[0] for restaurant in restaurants]
return sol_value, sol_names
def fast_create_schedule(objective, restaurants, days=5):
"""
Returns the schedule: the calories that we will eat this week and the
list of restaurants
Greedy: We pick the restaurant that is close to the per-day calories we
need to eat
"""
# We sort the restaurants list to use binary search and keep track of the
# old indexes
restaurants_cal = sorted(
[(restaurant[1], i) for i, restaurant in enumerate(restaurants)]
)
sol_value = 0
sol_names = []
for i in range(days):
mean = objective / (days - i)
# Find the closest restaurant to the mean
# (rightmost value less than or equal to)
j = bisect_right(restaurants_cal, (mean, 0)) - 1
cal, index = restaurants_cal[j]
sol_value += cal
sol_names.append(restaurants[index][0])
objective -= cal
del restaurants_cal[j]
return sol_value, sol_names
if __name__ == '__main__':
cal, restaurants = parse_input()
print(fast_create_schedule(cal, restaurants, days=5))
print(naive_create_schedule(cal, restaurants, days=5))