1class Candy:
2 def __init__(self, mass, uranium):
3 self.mass = mass
4 self.uranium = uranium
5
6 def get_uranium_quantity(self):
7 return self.uranium
8
9 def get_mass(self):
10 return self.mass
11
12
13class Person:
14 def __init__(self, position):
15 self.position = position
16
17 def get_position(self):
18 return self.position
19
20 def set_position(self, position):
21 self.position = position
22
23
24class Kid(Person):
25 def __init__(self, position, initiative):
26 self.initiative = initiative
27 self.basket = []
28 self.visited_hosts = []
29 super().__init__(position)
30
31 def get_initiative(self):
32 return self.initiative
33
34 def add_candy(self, candy):
35 self.basket.append(candy)
36
37 def is_critical(self):
38 return sum(candy.get_mass() * candy.get_uranium_quantity() for candy in self.basket) > 20
39
40
41class Host(Person):
42 def __init__(self, position, candies):
43 self.candies = []
44 for candy in candies:
45 self.candies.append(Candy(candy[0], candy[1]))
46 self.kids_at_the_moment = []
47 super().__init__(position)
48
49 def remove_candy(self, pick_func):
50 candy = pick_func(self.candies)
51 if candy is None:
52 return None
53 self.candies.remove(candy)
54 return candy
55
56
57class FluxCapacitor:
58 def __init__(self, participants):
59 self.hosts = []
60 self.kids = []
61 for participant in participants:
62 if isinstance(participant, Host):
63 self.hosts.append(participant)
64 if isinstance(participant, Kid):
65 self.kids.append(participant)
66
67 def _getDist(self, host, kid):
68 x1, y1 = host.get_position()
69 x2, y2 = kid.get_position()
70 return ((x2 - x1)**2 + (y2 - y1)**2)**0.5
71
72 def _get_closest_unvisited_host(self, kid):
73 self.hosts = sorted(self.hosts, key=lambda host: (self._getDist(host, kid), host.get_position()))
74 for host in self.hosts:
75 if host not in kid.visited_hosts:
76 kid.visited_hosts.append(host)
77 kid.position = host.get_position()
78 return host
79 return None
80
81 def _current_round(self):
82 dead_kids = set()
83 for kid in self.kids:
84 host = self._get_closest_unvisited_host(kid)
85 host.kids_at_the_moment.append(kid)
86
87 for host in self.hosts:
88 host.kids_at_the_moment = sorted(host.kids_at_the_moment, key=lambda x: x.get_initiative(), reverse=True)
89 for kid in host.kids_at_the_moment:
90 if host.candies == []:
91 break
92 candy = host.remove_candy(lambda y: max(y, key=lambda x: x.get_mass(), default=None))
93 kid.add_candy(candy)
94 if kid.is_critical():
95 dead_kids.add(kid)
96 host.kids_at_the_moment = []
97 return dead_kids if dead_kids else None
98
99 def get_victim(self):
100 i = 0
101 dead_kids = None
102 while i < len(self.hosts) and dead_kids is None:
103 dead_kids = self._current_round()
104 i += 1
105 return dead_kids
F.....E.....
======================================================================
ERROR: test_basic_usage (test.HostTest)
Test basic usage of Host class.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 69, in test_basic_usage
candy = host.remove_candy(compare_fun)
File "/tmp/solution.py", line 50, in remove_candy
candy = pick_func(self.candies)
File "/tmp/test.py", line 63, in <lambda>
compare_fun = lambda candies: min(candies, key=lambda candy: candy.get_mass())
ValueError: min() arg is an empty sequence
======================================================================
FAIL: test_basic_usage (test.CandyTest)
Test basic usage of Candy class.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 15, in test_basic_usage
self.assertEqual(candy.get_uranium_quantity(), 2.5)
AssertionError: 0.5 != 2.5
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (failures=1, errors=1)
f | 1 | class Candy: | f | 1 | class Candy: |
2 | def __init__(self, mass, uranium): | 2 | def __init__(self, mass, uranium): | ||
3 | self.mass = mass | 3 | self.mass = mass | ||
4 | self.uranium = uranium | 4 | self.uranium = uranium | ||
5 | 5 | ||||
6 | def get_uranium_quantity(self): | 6 | def get_uranium_quantity(self): | ||
7 | return self.uranium | 7 | return self.uranium | ||
8 | 8 | ||||
9 | def get_mass(self): | 9 | def get_mass(self): | ||
10 | return self.mass | 10 | return self.mass | ||
11 | 11 | ||||
12 | 12 | ||||
13 | class Person: | 13 | class Person: | ||
14 | def __init__(self, position): | 14 | def __init__(self, position): | ||
15 | self.position = position | 15 | self.position = position | ||
16 | 16 | ||||
17 | def get_position(self): | 17 | def get_position(self): | ||
18 | return self.position | 18 | return self.position | ||
19 | 19 | ||||
20 | def set_position(self, position): | 20 | def set_position(self, position): | ||
21 | self.position = position | 21 | self.position = position | ||
22 | 22 | ||||
23 | 23 | ||||
24 | class Kid(Person): | 24 | class Kid(Person): | ||
25 | def __init__(self, position, initiative): | 25 | def __init__(self, position, initiative): | ||
26 | self.initiative = initiative | 26 | self.initiative = initiative | ||
27 | self.basket = [] | 27 | self.basket = [] | ||
28 | self.visited_hosts = [] | 28 | self.visited_hosts = [] | ||
29 | super().__init__(position) | 29 | super().__init__(position) | ||
30 | 30 | ||||
n | 31 | def _sum_uranium(self): | n | ||
32 | sum = 0 | ||||
33 | for candy in self.basket: | ||||
34 | sum += candy.get_uranium_quantity() * candy.get_mass() | ||||
35 | return sum | ||||
36 | |||||
37 | def get_initiative(self): | 31 | def get_initiative(self): | ||
38 | return self.initiative | 32 | return self.initiative | ||
39 | 33 | ||||
40 | def add_candy(self, candy): | 34 | def add_candy(self, candy): | ||
41 | self.basket.append(candy) | 35 | self.basket.append(candy) | ||
42 | 36 | ||||
43 | def is_critical(self): | 37 | def is_critical(self): | ||
n | 44 | return self._sum_uranium() > 20 | n | 38 | return sum(candy.get_mass() * candy.get_uranium_quantity() for candy in self.basket) > 20 |
45 | 39 | ||||
46 | 40 | ||||
47 | class Host(Person): | 41 | class Host(Person): | ||
48 | def __init__(self, position, candies): | 42 | def __init__(self, position, candies): | ||
49 | self.candies = [] | 43 | self.candies = [] | ||
50 | for candy in candies: | 44 | for candy in candies: | ||
51 | self.candies.append(Candy(candy[0], candy[1])) | 45 | self.candies.append(Candy(candy[0], candy[1])) | ||
52 | self.kids_at_the_moment = [] | 46 | self.kids_at_the_moment = [] | ||
53 | super().__init__(position) | 47 | super().__init__(position) | ||
54 | 48 | ||||
55 | def remove_candy(self, pick_func): | 49 | def remove_candy(self, pick_func): | ||
56 | candy = pick_func(self.candies) | 50 | candy = pick_func(self.candies) | ||
n | 57 | if (candy == None): | n | 51 | if candy is None: |
58 | return None | 52 | return None | ||
59 | self.candies.remove(candy) | 53 | self.candies.remove(candy) | ||
60 | return candy | 54 | return candy | ||
61 | 55 | ||||
62 | 56 | ||||
63 | class FluxCapacitor: | 57 | class FluxCapacitor: | ||
64 | def __init__(self, participants): | 58 | def __init__(self, participants): | ||
65 | self.hosts = [] | 59 | self.hosts = [] | ||
66 | self.kids = [] | 60 | self.kids = [] | ||
67 | for participant in participants: | 61 | for participant in participants: | ||
68 | if isinstance(participant, Host): | 62 | if isinstance(participant, Host): | ||
69 | self.hosts.append(participant) | 63 | self.hosts.append(participant) | ||
70 | if isinstance(participant, Kid): | 64 | if isinstance(participant, Kid): | ||
71 | self.kids.append(participant) | 65 | self.kids.append(participant) | ||
72 | 66 | ||||
73 | def _getDist(self, host, kid): | 67 | def _getDist(self, host, kid): | ||
74 | x1, y1 = host.get_position() | 68 | x1, y1 = host.get_position() | ||
75 | x2, y2 = kid.get_position() | 69 | x2, y2 = kid.get_position() | ||
76 | return ((x2 - x1)**2 + (y2 - y1)**2)**0.5 | 70 | return ((x2 - x1)**2 + (y2 - y1)**2)**0.5 | ||
77 | 71 | ||||
78 | def _get_closest_unvisited_host(self, kid): | 72 | def _get_closest_unvisited_host(self, kid): | ||
n | 79 | self.hosts = sorted(self.hosts, key=lambda host: ( | n | 73 | self.hosts = sorted(self.hosts, key=lambda host: (self._getDist(host, kid), host.get_position())) |
80 | self._getDist(host, kid), host.get_position())) | ||||
81 | for host in self.hosts: | 74 | for host in self.hosts: | ||
n | 82 | if (host not in kid.visited_hosts): | n | 75 | if host not in kid.visited_hosts: |
83 | kid.visited_hosts.append(host) | 76 | kid.visited_hosts.append(host) | ||
84 | kid.position = host.get_position() | 77 | kid.position = host.get_position() | ||
85 | return host | 78 | return host | ||
86 | return None | 79 | return None | ||
87 | 80 | ||||
88 | def _current_round(self): | 81 | def _current_round(self): | ||
89 | dead_kids = set() | 82 | dead_kids = set() | ||
90 | for kid in self.kids: | 83 | for kid in self.kids: | ||
91 | host = self._get_closest_unvisited_host(kid) | 84 | host = self._get_closest_unvisited_host(kid) | ||
92 | host.kids_at_the_moment.append(kid) | 85 | host.kids_at_the_moment.append(kid) | ||
93 | 86 | ||||
94 | for host in self.hosts: | 87 | for host in self.hosts: | ||
n | 95 | host.kids_at_the_moment = sorted( | n | ||
96 | host.kids_at_the_moment, key=lambda x: x.get_initiative(), reverse=True) | 88 | host.kids_at_the_moment = sorted(host.kids_at_the_moment, key=lambda x: x.get_initiative(), reverse=True) | ||
97 | for kid in host.kids_at_the_moment: | 89 | for kid in host.kids_at_the_moment: | ||
n | 98 | if (host.candies == []): | n | 90 | if host.candies == []: |
99 | break | 91 | break | ||
n | 100 | candy = host.remove_candy(lambda y: max( | n | 92 | candy = host.remove_candy(lambda y: max(y, key=lambda x: x.get_mass(), default=None)) |
101 | y, key=lambda x: x.get_mass(), default=None)) | ||||
102 | kid.add_candy(candy) | 93 | kid.add_candy(candy) | ||
n | 103 | if (kid.is_critical()): | n | 94 | if kid.is_critical(): |
104 | dead_kids.add(kid) | 95 | dead_kids.add(kid) | ||
105 | host.kids_at_the_moment = [] | 96 | host.kids_at_the_moment = [] | ||
n | 106 | if (dead_kids == set()): | n | 97 | return dead_kids if dead_kids else None |
107 | return None | ||||
108 | return dead_kids | ||||
109 | 98 | ||||
110 | def get_victim(self): | 99 | def get_victim(self): | ||
111 | i = 0 | 100 | i = 0 | ||
112 | dead_kids = None | 101 | dead_kids = None | ||
t | 113 | while i < len(self.hosts) and dead_kids == None: | t | 102 | while i < len(self.hosts) and dead_kids is None: |
114 | dead_kids = self._current_round() | 103 | dead_kids = self._current_round() | ||
115 | i += 1 | 104 | i += 1 | ||
116 | return dead_kids | 105 | return dead_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | class Candy: | f | 1 | class Candy: |
2 | def __init__(self, mass, uranium): | 2 | def __init__(self, mass, uranium): | ||
3 | self.mass = mass | 3 | self.mass = mass | ||
4 | self.uranium = uranium | 4 | self.uranium = uranium | ||
5 | 5 | ||||
6 | def get_uranium_quantity(self): | 6 | def get_uranium_quantity(self): | ||
7 | return self.uranium | 7 | return self.uranium | ||
8 | 8 | ||||
9 | def get_mass(self): | 9 | def get_mass(self): | ||
10 | return self.mass | 10 | return self.mass | ||
11 | 11 | ||||
12 | 12 | ||||
13 | class Person: | 13 | class Person: | ||
14 | def __init__(self, position): | 14 | def __init__(self, position): | ||
15 | self.position = position | 15 | self.position = position | ||
16 | 16 | ||||
17 | def get_position(self): | 17 | def get_position(self): | ||
18 | return self.position | 18 | return self.position | ||
19 | 19 | ||||
20 | def set_position(self, position): | 20 | def set_position(self, position): | ||
21 | self.position = position | 21 | self.position = position | ||
22 | 22 | ||||
23 | 23 | ||||
24 | class Kid(Person): | 24 | class Kid(Person): | ||
25 | def __init__(self, position, initiative): | 25 | def __init__(self, position, initiative): | ||
26 | self.initiative = initiative | 26 | self.initiative = initiative | ||
27 | self.basket = [] | 27 | self.basket = [] | ||
28 | self.visited_hosts = [] | 28 | self.visited_hosts = [] | ||
29 | super().__init__(position) | 29 | super().__init__(position) | ||
30 | 30 | ||||
31 | def _sum_uranium(self): | 31 | def _sum_uranium(self): | ||
32 | sum = 0 | 32 | sum = 0 | ||
33 | for candy in self.basket: | 33 | for candy in self.basket: | ||
34 | sum += candy.get_uranium_quantity() * candy.get_mass() | 34 | sum += candy.get_uranium_quantity() * candy.get_mass() | ||
35 | return sum | 35 | return sum | ||
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): | ||
41 | self.basket.append(candy) | 41 | self.basket.append(candy) | ||
42 | 42 | ||||
43 | def is_critical(self): | 43 | def is_critical(self): | ||
44 | return self._sum_uranium() > 20 | 44 | return self._sum_uranium() > 20 | ||
45 | 45 | ||||
46 | 46 | ||||
47 | class Host(Person): | 47 | class Host(Person): | ||
48 | def __init__(self, position, candies): | 48 | def __init__(self, position, candies): | ||
49 | self.candies = [] | 49 | self.candies = [] | ||
50 | for candy in candies: | 50 | for candy in candies: | ||
51 | self.candies.append(Candy(candy[0], candy[1])) | 51 | self.candies.append(Candy(candy[0], candy[1])) | ||
n | 52 | self.kidsAtTheMoment = [] | n | 52 | self.kids_at_the_moment = [] |
53 | super().__init__(position) | 53 | super().__init__(position) | ||
54 | 54 | ||||
55 | def remove_candy(self, pick_func): | 55 | def remove_candy(self, pick_func): | ||
56 | candy = pick_func(self.candies) | 56 | candy = pick_func(self.candies) | ||
57 | if (candy == None): | 57 | if (candy == None): | ||
58 | return None | 58 | return None | ||
59 | self.candies.remove(candy) | 59 | self.candies.remove(candy) | ||
60 | return candy | 60 | return candy | ||
61 | 61 | ||||
62 | 62 | ||||
63 | class FluxCapacitor: | 63 | class FluxCapacitor: | ||
64 | def __init__(self, participants): | 64 | def __init__(self, participants): | ||
65 | self.hosts = [] | 65 | self.hosts = [] | ||
66 | self.kids = [] | 66 | self.kids = [] | ||
67 | for participant in participants: | 67 | for participant in participants: | ||
68 | if isinstance(participant, Host): | 68 | if isinstance(participant, Host): | ||
69 | self.hosts.append(participant) | 69 | self.hosts.append(participant) | ||
70 | if isinstance(participant, Kid): | 70 | if isinstance(participant, Kid): | ||
71 | self.kids.append(participant) | 71 | self.kids.append(participant) | ||
72 | 72 | ||||
73 | def _getDist(self, host, kid): | 73 | def _getDist(self, host, kid): | ||
74 | x1, y1 = host.get_position() | 74 | x1, y1 = host.get_position() | ||
75 | x2, y2 = kid.get_position() | 75 | x2, y2 = kid.get_position() | ||
76 | return ((x2 - x1)**2 + (y2 - y1)**2)**0.5 | 76 | return ((x2 - x1)**2 + (y2 - y1)**2)**0.5 | ||
77 | 77 | ||||
78 | def _get_closest_unvisited_host(self, kid): | 78 | def _get_closest_unvisited_host(self, kid): | ||
79 | self.hosts = sorted(self.hosts, key=lambda host: ( | 79 | self.hosts = sorted(self.hosts, key=lambda host: ( | ||
80 | self._getDist(host, kid), host.get_position())) | 80 | self._getDist(host, kid), host.get_position())) | ||
81 | for host in self.hosts: | 81 | for host in self.hosts: | ||
82 | if (host not in kid.visited_hosts): | 82 | if (host not in kid.visited_hosts): | ||
83 | kid.visited_hosts.append(host) | 83 | kid.visited_hosts.append(host) | ||
84 | kid.position = host.get_position() | 84 | kid.position = host.get_position() | ||
85 | return host | 85 | return host | ||
86 | return None | 86 | return None | ||
87 | 87 | ||||
n | 88 | def _currentRound(self): | n | 88 | def _current_round(self): |
89 | dead_kids = set() | 89 | dead_kids = set() | ||
90 | for kid in self.kids: | 90 | for kid in self.kids: | ||
91 | host = self._get_closest_unvisited_host(kid) | 91 | host = self._get_closest_unvisited_host(kid) | ||
n | 92 | host.kidsAtTheMoment.append(kid) | n | 92 | host.kids_at_the_moment.append(kid) |
93 | 93 | ||||
94 | for host in self.hosts: | 94 | for host in self.hosts: | ||
n | 95 | host.kidsAtTheMoment = sorted( | n | 95 | host.kids_at_the_moment = sorted( |
96 | host.kidsAtTheMoment, key=lambda x: x.get_initiative(), reverse=True) | 96 | host.kids_at_the_moment, key=lambda x: x.get_initiative(), reverse=True) | ||
97 | for kid in host.kidsAtTheMoment: | 97 | for kid in host.kids_at_the_moment: | ||
98 | if (host.candies == []): | 98 | if (host.candies == []): | ||
99 | break | 99 | break | ||
100 | candy = host.remove_candy(lambda y: max( | 100 | candy = host.remove_candy(lambda y: max( | ||
101 | y, key=lambda x: x.get_mass(), default=None)) | 101 | y, key=lambda x: x.get_mass(), default=None)) | ||
102 | kid.add_candy(candy) | 102 | kid.add_candy(candy) | ||
103 | if (kid.is_critical()): | 103 | if (kid.is_critical()): | ||
104 | dead_kids.add(kid) | 104 | dead_kids.add(kid) | ||
n | 105 | host.kidsAtTheMoment = [] | n | 105 | host.kids_at_the_moment = [] |
106 | if (dead_kids == set()): | 106 | if (dead_kids == set()): | ||
107 | return None | 107 | return None | ||
108 | return dead_kids | 108 | return dead_kids | ||
109 | 109 | ||||
110 | def get_victim(self): | 110 | def get_victim(self): | ||
111 | i = 0 | 111 | i = 0 | ||
112 | dead_kids = None | 112 | dead_kids = None | ||
113 | while i < len(self.hosts) and dead_kids == None: | 113 | while i < len(self.hosts) and dead_kids == None: | ||
t | 114 | dead_kids = self._currentRound() | t | 114 | dead_kids = self._current_round() |
115 | i += 1 | 115 | i += 1 | ||
116 | return dead_kids | 116 | return dead_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|