1import math
2
3
4class Candy:
5
6 def __init__(self, mass, uranium):
7 self.mass = mass
8 self.uranium = uranium
9
10 def get_uranium_quantity(self):
11 return self.mass * self.uranium
12
13 def get_mass(self):
14 return self.mass
15
16
17class Person:
18
19 def __init__(self, position):
20 self.position = position
21
22 def get_position(self):
23 return self.position
24
25 def set_position(self, position):
26 self.position = position
27
28
29class Kid(Person):
30
31 def __init__(self, position, initiative):
32 super().__init__(position)
33 self.initiative = initiative
34 self._basket = []
35 self._visited_hosts = []
36
37 def get_initiative(self):
38 return self.initiative
39
40 def add_candy(self, candy):
41 self._basket.append(candy)
42
43 def is_critical(self):
44 total_uranium = 0.0
45 for candy in self._basket:
46 total_uranium += candy.get_uranium_quantity()
47 return total_uranium > FluxCapacitor.URANIUM_LIMIT
48
49 def visit_host(self,hosts):
50 for host in sorted(hosts, key=lambda x : (math.dist(self.position,x.get_position()), x.position[0], x.position[1])):
51 if host in self._visited_hosts:
52 continue
53 else:
54 candy = host.remove_candy(FluxCapacitor.choose_candy)
55 self.set_position(host.get_position())
56 if candy is not None:
57 self._basket.append(candy)
58 self._visited_hosts.append(host)
59 return True
60 return False
61
62
63class Host(Person):
64
65 def __init__(self, position, candies):
66 super().__init__(position)
67 self.candies = []
68 for candy in candies:
69 self.candies.append(Candy(candy[0], candy[1]))
70
71 def remove_candy(self, remove_func):
72 if not self.candies:
73 return None
74 else:
75 candy = remove_func(self.candies)
76 self.candies.remove(candy)
77 return candy
78
79
80class FluxCapacitor:
81
82 URANIUM_LIMIT = 20
83
84 def __init__(self, participants):
85 self.participants = participants
86
87 @staticmethod
88 def choose_candy(candies):
89 return max(candies, key=lambda x : x.get_mass())
90
91 def get_victim(self):
92 dead_kids = []
93 kids = sorted([kid for kid in self.participants if type(kid) is Kid], key=lambda x: x.initiative, reverse=True)
94 hosts = [host for host in self.participants if type(host) is Host]
95 while not dead_kids and kids:
96 for kid in kids:
97 if kid.visit_host(hosts):
98 if kid.is_critical():
99 dead_kids.append(kid)
100 else:
101 kids.remove(kid)
102 if dead_kids:
103 return dead_kids
104 else:
105 return None
.....F......
======================================================================
FAIL: test_real_case (test.FluxCapacitorTest)
Test with real case.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/timeout_decorator/timeout_decorator.py", line 82, in new_function
return function(*args, **kwargs)
File "/tmp/test.py", line 115, in test_real_case
self.assertEqual(FluxCapacitor({kid1, kid2, host1, host2}).get_victim(), {kid1, kid2})
AssertionError: [<solution.Kid object at 0x7f24603e4610>,[36 chars]670>] != {<solution.Kid object at 0x7f24603e4610>,[36 chars]670>}
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (failures=1)
f | 1 | import math | f | 1 | import math |
2 | 2 | ||||
3 | 3 | ||||
4 | class Candy: | 4 | class Candy: | ||
5 | 5 | ||||
6 | def __init__(self, mass, uranium): | 6 | def __init__(self, mass, uranium): | ||
7 | self.mass = mass | 7 | self.mass = mass | ||
8 | self.uranium = uranium | 8 | self.uranium = uranium | ||
9 | 9 | ||||
10 | def get_uranium_quantity(self): | 10 | def get_uranium_quantity(self): | ||
11 | return self.mass * self.uranium | 11 | return self.mass * self.uranium | ||
12 | 12 | ||||
13 | def get_mass(self): | 13 | def get_mass(self): | ||
14 | return self.mass | 14 | return self.mass | ||
15 | 15 | ||||
16 | 16 | ||||
17 | class Person: | 17 | class Person: | ||
18 | 18 | ||||
19 | def __init__(self, position): | 19 | def __init__(self, position): | ||
20 | self.position = position | 20 | self.position = position | ||
21 | 21 | ||||
22 | def get_position(self): | 22 | def get_position(self): | ||
23 | return self.position | 23 | return self.position | ||
24 | 24 | ||||
25 | def set_position(self, position): | 25 | def set_position(self, position): | ||
26 | self.position = position | 26 | self.position = position | ||
27 | 27 | ||||
28 | 28 | ||||
29 | class Kid(Person): | 29 | class Kid(Person): | ||
30 | 30 | ||||
31 | def __init__(self, position, initiative): | 31 | def __init__(self, position, initiative): | ||
32 | super().__init__(position) | 32 | super().__init__(position) | ||
33 | self.initiative = initiative | 33 | self.initiative = initiative | ||
n | 34 | self.basket = [] | n | 34 | self._basket = [] |
35 | self.visited_hosts = [] | 35 | self._visited_hosts = [] | ||
36 | 36 | ||||
37 | def get_initiative(self): | 37 | def get_initiative(self): | ||
38 | return self.initiative | 38 | return self.initiative | ||
39 | 39 | ||||
40 | def add_candy(self, candy): | 40 | def add_candy(self, candy): | ||
n | 41 | self.basket.append(candy) | n | 41 | self._basket.append(candy) |
42 | 42 | ||||
43 | def is_critical(self): | 43 | def is_critical(self): | ||
44 | total_uranium = 0.0 | 44 | total_uranium = 0.0 | ||
n | 45 | for candy in self.basket: | n | 45 | for candy in self._basket: |
46 | total_uranium += candy.get_uranium_quantity() | 46 | total_uranium += candy.get_uranium_quantity() | ||
n | 47 | if total_uranium > 20.0: | n | 47 | return total_uranium > FluxCapacitor.URANIUM_LIMIT |
48 | return True | ||||
49 | return False | ||||
50 | 48 | ||||
51 | def visit_host(self,hosts): | 49 | def visit_host(self,hosts): | ||
n | 52 | for host in sorted(hosts, key=lambda x : (math.sqrt((x.position[0] - self.position[0])**2 + (x.position[1] - self.position[1])**2), x.position[0], x.position[1])): | n | 50 | for host in sorted(hosts, key=lambda x : (math.dist(self.position,x.get_position()), x.position[0], x.position[1])): |
53 | if host in self.visited_hosts: | 51 | if host in self._visited_hosts: | ||
54 | continue | 52 | continue | ||
55 | else: | 53 | else: | ||
56 | candy = host.remove_candy(FluxCapacitor.choose_candy) | 54 | candy = host.remove_candy(FluxCapacitor.choose_candy) | ||
n | n | 55 | self.set_position(host.get_position()) | ||
57 | if candy is not None: | 56 | if candy is not None: | ||
n | 58 | self.basket.append(candy) | n | 57 | self._basket.append(candy) |
59 | self.visited_hosts.append(host) | 58 | self._visited_hosts.append(host) | ||
60 | return True | 59 | return True | ||
61 | return False | 60 | return False | ||
62 | 61 | ||||
63 | 62 | ||||
64 | class Host(Person): | 63 | class Host(Person): | ||
65 | 64 | ||||
66 | def __init__(self, position, candies): | 65 | def __init__(self, position, candies): | ||
67 | super().__init__(position) | 66 | super().__init__(position) | ||
68 | self.candies = [] | 67 | self.candies = [] | ||
69 | for candy in candies: | 68 | for candy in candies: | ||
70 | self.candies.append(Candy(candy[0], candy[1])) | 69 | self.candies.append(Candy(candy[0], candy[1])) | ||
71 | 70 | ||||
72 | def remove_candy(self, remove_func): | 71 | def remove_candy(self, remove_func): | ||
73 | if not self.candies: | 72 | if not self.candies: | ||
74 | return None | 73 | return None | ||
75 | else: | 74 | else: | ||
76 | candy = remove_func(self.candies) | 75 | candy = remove_func(self.candies) | ||
77 | self.candies.remove(candy) | 76 | self.candies.remove(candy) | ||
78 | return candy | 77 | return candy | ||
79 | 78 | ||||
80 | 79 | ||||
81 | class FluxCapacitor: | 80 | class FluxCapacitor: | ||
82 | 81 | ||||
n | n | 82 | URANIUM_LIMIT = 20 | ||
83 | |||||
83 | def __init__(self, participants): | 84 | def __init__(self, participants): | ||
84 | self.participants = participants | 85 | self.participants = participants | ||
85 | 86 | ||||
86 | @staticmethod | 87 | @staticmethod | ||
87 | def choose_candy(candies): | 88 | def choose_candy(candies): | ||
n | 88 | var = max(candies, key=lambda x : x.get_mass()) | n | 89 | return max(candies, key=lambda x : x.get_mass()) |
89 | return var | ||||
90 | 90 | ||||
91 | def get_victim(self): | 91 | def get_victim(self): | ||
92 | dead_kids = [] | 92 | dead_kids = [] | ||
t | 93 | kids = sorted([kid for kid in self.participants if type(kid) == Kid], key=lambda x: x.initiative, reverse=True) | t | 93 | kids = sorted([kid for kid in self.participants if type(kid) is Kid], key=lambda x: x.initiative, reverse=True) |
94 | hosts = [host for host in self.participants if type(host) == Host] | 94 | hosts = [host for host in self.participants if type(host) is Host] | ||
95 | while not dead_kids and kids: | 95 | while not dead_kids and kids: | ||
96 | for kid in kids: | 96 | for kid in kids: | ||
97 | if kid.visit_host(hosts): | 97 | if kid.visit_host(hosts): | ||
98 | if kid.is_critical(): | 98 | if kid.is_critical(): | ||
99 | dead_kids.append(kid) | 99 | dead_kids.append(kid) | ||
100 | else: | 100 | else: | ||
101 | kids.remove(kid) | 101 | kids.remove(kid) | ||
102 | if dead_kids: | 102 | if dead_kids: | ||
103 | return dead_kids | 103 | return dead_kids | ||
104 | else: | 104 | else: | ||
105 | return None | 105 | return None | ||
106 | 106 |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|