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 self.basket = []
22
23 def get_position(self):
24 return self.position
25
26 def set_position(self, new_position):
27 self.position = new_position
28
29 def get_distance(self, person):
30 return math.dist(self.position, person.get_position())
31
32
33class Kid(Person):
34
35 CRITICAL_URANIUM_MASS = 20
36
37 def __init__(self, position, initiative):
38 super().__init__(position)
39 self.initiative = initiative
40 self.visited_hosts = []
41
42 def get_initiative(self):
43 return self.initiative
44
45 def add_candy(self, candy):
46 self.basket.append(candy)
47
48 def is_critical(self):
49 uranium_quantity = sum(candy.get_uranium_quantity() for candy in self.basket)
50 return uranium_quantity > Kid.CRITICAL_URANIUM_MASS
51
52 def get_visited_hosts(self):
53 return self.visited_hosts
54
55 def add_visited_host(self, host):
56 self.visited_hosts.append(host)
57
58
59class Host(Person):
60
61 def __init__(self, position, candies):
62 super().__init__(position)
63 self.basket = [Candy(mass, uranium) for mass, uranium in candies]
64
65 def remove_candy(self, candy_removal):
66 if not self.basket:
67 return None
68 candy_to_remove = candy_removal(self.basket)
69 self.basket.remove(candy_to_remove)
70 return candy_to_remove
71
72
73class FluxCapacitor:
74
75 def __init__(self, participants):
76 self.participants = participants
77 self.kids = [participant for participant in self.participants if isinstance(participant, Kid)]
78 self.hosts = [participant for participant in self.participants if isinstance(participant, Host)]
79
80 def candy_to_remove(self, basket):
81 return max(basket, key=lambda candy: candy.get_mass())
82
83 def get_victim(self):
84 victims = ()
85
86 while self.kids:
87 for kid in self.kids:
88 if kid.is_critical():
89 victims.add(kid)
90 self.kids.remove(kid)
91 else:
92 unvisited_hosts = [host for host in self.hosts if host not in kid.get_visited_hosts()]
93 if unvisited_hosts:
94 closest_host = min(unvisited_hosts, key=lambda host: kid.get_distance(host))
95 candy = closest_host.remove_candy(self.candy_to_remove)
96 if candy:
97 kid.add_candy(candy)
98 kid.add_visited_host(closest_host)
99 kid.set_position(closest_host.get_position())
100 else:
101 self.kids.remove(kid)
102 return victims or None
....FE......
======================================================================
ERROR: 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})
File "/tmp/solution.py", line 89, in get_victim
victims.add(kid)
AttributeError: 'tuple' object has no attribute 'add'
======================================================================
FAIL: test_no_candies (test.FluxCapacitorTest)
Test with no candies.
----------------------------------------------------------------------
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 106, in test_no_candies
self.assertEqual(flux_capacitor.get_victim(), None)
File "/tmp/solution.py", line 94, in get_victim
closest_host = min(unvisited_hosts, key=lambda host: kid.get_distance(host))
File "/tmp/solution.py", line 94, in <lambda>
closest_host = min(unvisited_hosts, key=lambda host: kid.get_distance(host))
File "/tmp/solution.py", line 30, in get_distance
return math.dist(self.position, person.get_position())
File "/usr/local/lib/python3.10/dist-packages/timeout_decorator/timeout_decorator.py", line 69, in handler
_raise_exception(timeout_exception, exception_message)
File "/usr/local/lib/python3.10/dist-packages/timeout_decorator/timeout_decorator.py", line 45, in _raise_exception
raise exception()
timeout_decorator.timeout_decorator.TimeoutError: 'Timed Out'
----------------------------------------------------------------------
Ran 12 tests in 0.201s
FAILED (failures=1, errors=1)
f | 1 | import math | f | 1 | import math |
2 | 2 | ||||
3 | 3 | ||||
4 | class Candy: | 4 | class Candy: | ||
n | n | 5 | |||
5 | def __init__(self, mass, uranium): | 6 | def __init__(self, mass, uranium): | ||
6 | self.mass = mass | 7 | self.mass = mass | ||
7 | self.uranium = uranium | 8 | self.uranium = uranium | ||
8 | 9 | ||||
9 | def get_uranium_quantity(self): | 10 | def get_uranium_quantity(self): | ||
10 | return self.mass * self.uranium | 11 | return self.mass * self.uranium | ||
11 | 12 | ||||
12 | def get_mass(self): | 13 | def get_mass(self): | ||
13 | return self.mass | 14 | return self.mass | ||
14 | 15 | ||||
15 | 16 | ||||
16 | class Person: | 17 | class Person: | ||
n | n | 18 | |||
17 | def __init__(self, position): | 19 | def __init__(self, position): | ||
18 | self.position = position | 20 | self.position = position | ||
19 | self.basket = [] | 21 | self.basket = [] | ||
20 | 22 | ||||
21 | def get_position(self): | 23 | def get_position(self): | ||
22 | return self.position | 24 | return self.position | ||
23 | 25 | ||||
24 | def set_position(self, new_position): | 26 | def set_position(self, new_position): | ||
25 | self.position = new_position | 27 | self.position = new_position | ||
26 | 28 | ||||
27 | def get_distance(self, person): | 29 | def get_distance(self, person): | ||
28 | return math.dist(self.position, person.get_position()) | 30 | return math.dist(self.position, person.get_position()) | ||
29 | 31 | ||||
30 | 32 | ||||
31 | class Kid(Person): | 33 | class Kid(Person): | ||
n | n | 34 | |||
35 | CRITICAL_URANIUM_MASS = 20 | ||||
36 | |||||
32 | def __init__(self, position, initiative): | 37 | def __init__(self, position, initiative): | ||
33 | super().__init__(position) | 38 | super().__init__(position) | ||
34 | self.initiative = initiative | 39 | self.initiative = initiative | ||
35 | self.visited_hosts = [] | 40 | self.visited_hosts = [] | ||
36 | 41 | ||||
37 | def get_initiative(self): | 42 | def get_initiative(self): | ||
38 | return self.initiative | 43 | return self.initiative | ||
39 | 44 | ||||
40 | def add_candy(self, candy): | 45 | def add_candy(self, candy): | ||
41 | self.basket.append(candy) | 46 | self.basket.append(candy) | ||
42 | 47 | ||||
43 | def is_critical(self): | 48 | def is_critical(self): | ||
44 | uranium_quantity = sum(candy.get_uranium_quantity() for candy in self.basket) | 49 | uranium_quantity = sum(candy.get_uranium_quantity() for candy in self.basket) | ||
n | 45 | return uranium_quantity > 20 | n | 50 | return uranium_quantity > Kid.CRITICAL_URANIUM_MASS |
46 | 51 | ||||
47 | def get_visited_hosts(self): | 52 | def get_visited_hosts(self): | ||
48 | return self.visited_hosts | 53 | return self.visited_hosts | ||
49 | 54 | ||||
50 | def add_visited_host(self, host): | 55 | def add_visited_host(self, host): | ||
51 | self.visited_hosts.append(host) | 56 | self.visited_hosts.append(host) | ||
52 | 57 | ||||
53 | 58 | ||||
54 | class Host(Person): | 59 | class Host(Person): | ||
n | n | 60 | |||
55 | def __init__(self, position, candies): | 61 | def __init__(self, position, candies): | ||
56 | super().__init__(position) | 62 | super().__init__(position) | ||
57 | self.basket = [Candy(mass, uranium) for mass, uranium in candies] | 63 | self.basket = [Candy(mass, uranium) for mass, uranium in candies] | ||
58 | 64 | ||||
59 | def remove_candy(self, candy_removal): | 65 | def remove_candy(self, candy_removal): | ||
60 | if not self.basket: | 66 | if not self.basket: | ||
61 | return None | 67 | return None | ||
62 | candy_to_remove = candy_removal(self.basket) | 68 | candy_to_remove = candy_removal(self.basket) | ||
63 | self.basket.remove(candy_to_remove) | 69 | self.basket.remove(candy_to_remove) | ||
64 | return candy_to_remove | 70 | return candy_to_remove | ||
65 | 71 | ||||
66 | 72 | ||||
67 | class FluxCapacitor: | 73 | class FluxCapacitor: | ||
n | n | 74 | |||
68 | def __init__(self, participants): | 75 | def __init__(self, participants): | ||
69 | self.participants = participants | 76 | self.participants = participants | ||
n | n | 77 | self.kids = [participant for participant in self.participants if isinstance(participant, Kid)] | ||
78 | self.hosts = [participant for participant in self.participants if isinstance(participant, Host)] | ||||
70 | 79 | ||||
71 | def candy_to_remove(self, basket): | 80 | def candy_to_remove(self, basket): | ||
72 | return max(basket, key=lambda candy: candy.get_mass()) | 81 | return max(basket, key=lambda candy: candy.get_mass()) | ||
73 | 82 | ||||
74 | def get_victim(self): | 83 | def get_victim(self): | ||
n | 75 | kids = [participant for participant in self.participants if isinstance(participant, Kid)] | n | ||
76 | hosts = [participant for participant in self.participants if isinstance(participant, Host)] | ||||
77 | victims = () | 84 | victims = () | ||
78 | 85 | ||||
n | 79 | while kids: | n | 86 | while self.kids: |
80 | for kid in kids: | 87 | for kid in self.kids: | ||
81 | if kid.is_critical(): | 88 | if kid.is_critical(): | ||
82 | victims.add(kid) | 89 | victims.add(kid) | ||
n | 83 | kids.remove(kid) | n | 90 | self.kids.remove(kid) |
84 | else: | 91 | else: | ||
n | 85 | unvisited_hosts = [host for host in hosts if host not in kid.get_visited_hosts()] | n | 92 | unvisited_hosts = [host for host in self.hosts if host not in kid.get_visited_hosts()] |
86 | if unvisited_hosts: | 93 | if unvisited_hosts: | ||
87 | closest_host = min(unvisited_hosts, key=lambda host: kid.get_distance(host)) | 94 | closest_host = min(unvisited_hosts, key=lambda host: kid.get_distance(host)) | ||
88 | candy = closest_host.remove_candy(self.candy_to_remove) | 95 | candy = closest_host.remove_candy(self.candy_to_remove) | ||
89 | if candy: | 96 | if candy: | ||
90 | kid.add_candy(candy) | 97 | kid.add_candy(candy) | ||
91 | kid.add_visited_host(closest_host) | 98 | kid.add_visited_host(closest_host) | ||
92 | kid.set_position(closest_host.get_position()) | 99 | kid.set_position(closest_host.get_position()) | ||
93 | else: | 100 | else: | ||
t | 94 | kids.remove(kid) | t | 101 | self.kids.remove(kid) |
95 | return victims if victims else None | 102 | return victims or None |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|