项目作者: mozanunal

项目描述 :
HashCode 2021 practice question solution with 727,667,236 points. It is a clean and readable 4 hours solution written in Python.
高级语言: Python
项目地址: git://github.com/mozanunal/hashcode2021-even-more-pizza.git
创建时间: 2021-02-18T17:04:53Z
项目社区:https://github.com/mozanunal/hashcode2021-even-more-pizza

开源协议:

下载


Hashcode 2021 Even More Pizza

It is our implementation for Hashcode 2021 practice question. It is a clean and readable 4 hours solution writen in Python.

Data Scores
A – Example 65 points
B – A little bit of everything 12,029 points
C – Many ingredients 708,861,140 points
D – Many pizzas 7,946,557 points
E – Many teams 10,847,445 points
Total 727,667,236 points

Solution

This is a brief explanation of the solution process. Please see the code for the details. We have created 2 classes:

Pizza Class

Stores ingredients as set and index to create submission file.

  1. class Pizza(object):
  2. def __init__(self, index, ings):
  3. self.index = index
  4. self.ings = set(ings)
  5. self.count = len(self.ings)
  6. self.selected = False
  7. self.score = {}

Team Class

Team class stores the pizzas which are sent to the team. Add function of team class handles:

  • adds unique ingridient with union function
  • adds pizza to pizzas
  • marks pizza as selected
  • checks the capacity and already selected pizza error states
  1. class Team():
  2. def __init__(self, cap):
  3. self.cap = cap
  4. self.pizzas = []
  5. self.ings = set()
  6. def calcSc(self, pizza):
  7. comm = self.ings.intersection(pizza.ings)
  8. uniq = self.ings.union(pizza.ings)
  9. total = pizza.count
  10. for p in self.pizzas:
  11. total += p.count
  12. sc = len(uniq) / (total)
  13. return sc
  14. def add(self, pizza):
  15. assert 1 + len(self.pizzas) <= self.cap
  16. self.pizzas.append(pizza)
  17. assert pizza.selected == False
  18. pizza.selected = True
  19. self.ings = self.ings.union(pizza.ings)
  20. def __repr__(self):
  21. return '[{}-{}-{}]'.format(self.cap, [p.index for p in self.pizzas], self.ings)
  22. @property
  23. def is_full(self):
  24. return len(self.pizzas) == self.cap

Solver

Solver takes a list of teams and a list of pizzas as argument. The pizzas
should already be sorted with count of ingredients. PART_SIZE is used to shorten the calculation process. When checking the potential pizza candidates how many sample will be check is determined with this size in enumerate(pizzas[0:PART_SIZE]).

  1. PART_SIZE=256
  2. def solve(teams, pizzas):
  3. for team in tqdm(teams):
  4. if len(pizzas) < 1:
  5. print('done--------------')
  6. break
  7. for i in range(team.cap):
  8. maxScore = 0
  9. maxScoreIdx = 0
  10. for i, pizza in enumerate(pizzas[0:PART_SIZE]):
  11. score = team.calcSc(pizza)
  12. if score > maxScore:
  13. maxScore = score
  14. maxScoreIdx = i
  15. team.add(pizzas[maxScoreIdx])
  16. pizzas.pop(maxScoreIdx)

Solving Process

Solving start with 4 member teams. Since the score is calculated the square of the unique ingredients, filling 4 member teams first gives better result.

  1. nPizza, n2, n3, n4, pizzaL, teamL2, teamL3, teamL4 = readF(filename)
  2. pizzaLSorted = sorted(pizzaL, key=operator.attrgetter('count'), reverse=True)
  3. #### initial add start ########
  4. solve(teamL4, pizzaLSorted)
  5. solve(teamL3, pizzaLSorted)
  6. solve(teamL2, pizzaLSorted)
  7. outF( filename.replace('data/','')+'.out', teamL2, teamL3, teamL4 )

My Other HashCode Repos

Team