1def max_candy_by_mass(candies: list):
2 """Return the Candy with the most Mass."""
3 return max(candies, key=lambda candy: candy.get_mass())
4
5
6def get_host_with_min_distance(kid, hosts):
7 """Return the Host with the least Distance to the Kid."""
8 return min(hosts,
9 key=(lambda host: (host.get_distance_to_person(kid), host.get_position()[0], host.get_position()[1])))
10
11
12class Candy:
13 """A Class that represents a Candy."""
14
15 def __init__(self, mass: float, uranium: float):
16 self._mass = mass
17 self._uranium = uranium
18
19 def get_mass(self):
20 """Return the Mass of the Candy."""
21 return self._mass
22
23 def get_uranium_quantity(self):
24 """Return the total Amount of Uranium in the Candy."""
25 return self._mass * self._uranium
26
27
28class Person:
29 """A Class that Represents a Person."""
30
31 def __init__(self, position: tuple):
32 self._position = None
33 self.set_position(position)
34 self._basket = []
35
36 def get_position(self):
37 """Return the Position of the Person."""
38 return self._position
39
40 def set_position(self, position: tuple):
41 """Change the Position of the Person."""
42 self._position = position
43
44 def get_distance_to_person(self, person):
45 """Return the Distance from the current Person to the passed in Person."""
46 return ((self._position[0] - person.get_position()[0]) ** 2 + (
47 self._position[1] - person.get_position()[1]) ** 2) ** 0.5
48
49 def is_basket_empty(self):
50 """Return true if the Basket is empty."""
51 return not self._basket
52
53 def __repr__(self):
54 return f'{self._position}, Basket: {len(self._basket)}'
55
56
57class Kid(Person):
58 """A Class that represents a Kid."""
59
60 CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20
61
62 def __init__(self, position: tuple, initiative: int):
63 super().__init__(position)
64 self._initiative = initiative
65
66 def get_initiative(self):
67 """Return the Initiative of the Kid."""
68 return self._initiative
69
70 def add_candy(self, candy: Candy or None):
71 """Add a Candy to the Basket."""
72 if not candy:
73 return
74
75 self._basket.append(candy)
76
77 def is_critical(self):
78 """Return true if the Uranium Amount in the Basket is more than 20g."""
79 return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS
80
81 def get_total_uranium_in_basket(self):
82 """Get the total Amount of Uranium in the Basket."""
83 return sum([candy.get_uranium_quantity() for candy in self._basket])
84
85 def __repr__(self):
86 return (f'{super().__repr__()}, Initiative: {self._initiative},'
87 f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g')
88
89
90class Host(Person):
91 """A Class that represents a Host."""
92
93 def __init__(self, position: tuple, candies: list):
94 super().__init__(position)
95 self._basket = candies[:]
96
97 def remove_candy(self, candy_choosing_function):
98 """Select a Candy from the Basket based on the passed in Function."""
99 if not self._basket:
100 return None
101
102 chosen_candy = candy_choosing_function(self._basket)
103 self._basket.remove(chosen_candy)
104 return chosen_candy or None
105
106
107class FluxCapacitor:
108 """Class that represents a simulation of a Halloween night."""
109
110 def __init__(self, participants: set):
111 self._kids = []
112 self._hosts = []
113 self._hosts_visitation_table = {}
114 self._fill_participants(participants)
115
116 def _fill_participants(self, participants: set):
117 for participant in participants:
118 if type(participant) is Kid:
119 self._kids.append(participant)
120 else:
121 self._hosts.append(participant)
122
123 def get_victim(self):
124 """Simulate a Halloween night and return the first Kids that are critical."""
125 while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()):
126 if critical_kids is None:
127 return None
128
129 return set(critical_kids) or None
130
131 def _have_the_kids_visited_all_hosts(self):
132 """Return true if all the Kids have visited all the Hosts."""
133 return all([len(self._hosts_visitation_table.get(kid, set())) == len(self._hosts) for kid in self._kids])
134
135 def _simulate_one_iteration_of_trick_or_treat(self):
136 """Simulate one cycle of Kids taking Candy from Hosts.
137
138 Return the Kids that are critical after the Cycle or
139 None if the there are no more Kids or Hosts with Candy (The Simulation is over) or
140 an empty List if there are no critical Kids after the Cycle or
141 all the Kids have visited all the Hosts.
142 """
143
144 hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts))
145 none_critical_kids_sorted_by_initiative = sorted(
146 filter(lambda curr_kid: not curr_kid.is_critical(), self._kids),
147 key=lambda curr_kid: curr_kid.get_initiative(), reverse=True
148 )
149
150 if (not none_critical_kids_sorted_by_initiative or
151 not hosts_with_candies or self._have_the_kids_visited_all_hosts()):
152 return None
153
154 critical_kids = []
155 for kid in none_critical_kids_sorted_by_initiative:
156 hosts_not_visited_by_current_kid = list(
157 filter(
158 lambda curr_host: curr_host not in self._hosts_visitation_table.get(kid, set()),
159 hosts_with_candies
160 )
161 )
162
163 if not hosts_not_visited_by_current_kid:
164 continue
165
166 min_dist_host = get_host_with_min_distance(kid, hosts_not_visited_by_current_kid)
167 kid.set_position(min_dist_host.get_position())
168
169 self._hosts_visitation_table[kid] = self._hosts_visitation_table.get(kid, set())
170 self._hosts_visitation_table[kid].add(min_dist_host)
171
172 removed_candy = min_dist_host.remove_candy(max_candy_by_mass)
173 kid.add_candy(removed_candy)
174
175 if kid.is_critical():
176 critical_kids.append(kid)
177
178 return critical_kids
.....EE.....
======================================================================
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 125, in get_victim
while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()):
File "/tmp/solution.py", line 172, in _simulate_one_iteration_of_trick_or_treat
removed_candy = min_dist_host.remove_candy(max_candy_by_mass)
File "/tmp/solution.py", line 102, in remove_candy
chosen_candy = candy_choosing_function(self._basket)
File "/tmp/solution.py", line 3, in max_candy_by_mass
return max(candies, key=lambda candy: candy.get_mass())
File "/tmp/solution.py", line 3, in <lambda>
return max(candies, key=lambda candy: candy.get_mass())
AttributeError: 'tuple' object has no attribute 'get_mass'
======================================================================
ERROR: test_basic_usage (test.HostTest)
Test basic usage of Host class.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 65, in test_basic_usage
candy = host.remove_candy(compare_fun)
File "/tmp/solution.py", line 102, in remove_candy
chosen_candy = candy_choosing_function(self._basket)
File "/tmp/test.py", line 63, in <lambda>
compare_fun = lambda candies: min(candies, key=lambda candy: candy.get_mass())
File "/tmp/test.py", line 63, in <lambda>
compare_fun = lambda candies: min(candies, key=lambda candy: candy.get_mass())
AttributeError: 'tuple' object has no attribute 'get_mass'
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (errors=2)
Филип Филчев
07.11.2023 14:39Благодаря!
|
Георги Кунчев
07.11.2023 09:27Като човек, който винаги качва пръв, както и за старанието да качиш толкова много версии, получаваш едина бонус точка за това домашно.
|
Филип Филчев
02.11.2023 23:00Тези докстрингове в последната функция ми помагат на мен да проследя какво съм написал. Ще ги махна при финалното предаване.
|
Георги Кунчев
02.11.2023 18:20Логически грешки не се показват при ъплоуд. Само учителите ги виждат, докато не се направят всички решения публични
|
Филип Филчев
02.11.2023 17:25Питам дали има тестове, които тестват самото решение, не за компилация. Защото бях качил решението с грешки в логиката и се учудих, че се качи.
|
Георги Кунчев
02.11.2023 09:38Да, за всяко домашно и предизвикателство се пускат тестове при качване, които имат за цел да верифицират сигнатурата на кода ти. С други думи - дали си използвал правилните имена на класове/функции и дали те връщат правилния тип данни.
Ако всичко с теста е наред, направо се качва и се визуализира.
Ако има проблем, ще видиш лога от тестовете, за да се ориентираш какво трябва да се оправи.
Сега тествах и всичко изглежда наред, но ако имаш съмнение, че нещо не е сработило, кажи да погледна.
|
Филип Филчев
01.11.2023 21:40Някакви тестове рънват ли се при качване?
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, | 8 | return min(hosts, | ||
9 | key=(lambda host: (host.get_distance_to_person(kid), host.get_position()[0], host.get_position()[1]))) | 9 | key=(lambda host: (host.get_distance_to_person(kid), host.get_position()[0], host.get_position()[1]))) | ||
10 | 10 | ||||
11 | 11 | ||||
12 | class Candy: | 12 | class Candy: | ||
13 | """A Class that represents a Candy.""" | 13 | """A Class that represents a Candy.""" | ||
14 | 14 | ||||
15 | def __init__(self, mass: float, uranium: float): | 15 | def __init__(self, mass: float, uranium: float): | ||
16 | self._mass = mass | 16 | self._mass = mass | ||
17 | self._uranium = uranium | 17 | self._uranium = uranium | ||
18 | 18 | ||||
19 | def get_mass(self): | 19 | def get_mass(self): | ||
20 | """Return the Mass of the Candy.""" | 20 | """Return the Mass of the Candy.""" | ||
21 | return self._mass | 21 | return self._mass | ||
22 | 22 | ||||
23 | def get_uranium_quantity(self): | 23 | def get_uranium_quantity(self): | ||
24 | """Return the total Amount of Uranium in the Candy.""" | 24 | """Return the total Amount of Uranium in the Candy.""" | ||
25 | return self._mass * self._uranium | 25 | return self._mass * self._uranium | ||
26 | 26 | ||||
27 | 27 | ||||
28 | class Person: | 28 | class Person: | ||
29 | """A Class that Represents a Person.""" | 29 | """A Class that Represents a Person.""" | ||
30 | 30 | ||||
31 | def __init__(self, position: tuple): | 31 | def __init__(self, position: tuple): | ||
32 | self._position = None | 32 | self._position = None | ||
33 | self.set_position(position) | 33 | self.set_position(position) | ||
34 | self._basket = [] | 34 | self._basket = [] | ||
35 | 35 | ||||
36 | def get_position(self): | 36 | def get_position(self): | ||
37 | """Return the Position of the Person.""" | 37 | """Return the Position of the Person.""" | ||
38 | return self._position | 38 | return self._position | ||
39 | 39 | ||||
40 | def set_position(self, position: tuple): | 40 | def set_position(self, position: tuple): | ||
41 | """Change the Position of the Person.""" | 41 | """Change the Position of the Person.""" | ||
42 | self._position = position | 42 | self._position = position | ||
43 | 43 | ||||
44 | def get_distance_to_person(self, person): | 44 | def get_distance_to_person(self, person): | ||
45 | """Return the Distance from the current Person to the passed in Person.""" | 45 | """Return the Distance from the current Person to the passed in Person.""" | ||
46 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 46 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
47 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 47 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
48 | 48 | ||||
49 | def is_basket_empty(self): | 49 | def is_basket_empty(self): | ||
50 | """Return true if the Basket is empty.""" | 50 | """Return true if the Basket is empty.""" | ||
51 | return not self._basket | 51 | return not self._basket | ||
52 | 52 | ||||
53 | def __repr__(self): | 53 | def __repr__(self): | ||
54 | return f'{self._position}, Basket: {len(self._basket)}' | 54 | return f'{self._position}, Basket: {len(self._basket)}' | ||
55 | 55 | ||||
56 | 56 | ||||
57 | class Kid(Person): | 57 | class Kid(Person): | ||
58 | """A Class that represents a Kid.""" | 58 | """A Class that represents a Kid.""" | ||
59 | 59 | ||||
60 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 60 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
61 | 61 | ||||
62 | def __init__(self, position: tuple, initiative: int): | 62 | def __init__(self, position: tuple, initiative: int): | ||
63 | super().__init__(position) | 63 | super().__init__(position) | ||
64 | self._initiative = initiative | 64 | self._initiative = initiative | ||
65 | 65 | ||||
66 | def get_initiative(self): | 66 | def get_initiative(self): | ||
67 | """Return the Initiative of the Kid.""" | 67 | """Return the Initiative of the Kid.""" | ||
68 | return self._initiative | 68 | return self._initiative | ||
69 | 69 | ||||
70 | def add_candy(self, candy: Candy or None): | 70 | def add_candy(self, candy: Candy or None): | ||
71 | """Add a Candy to the Basket.""" | 71 | """Add a Candy to the Basket.""" | ||
72 | if not candy: | 72 | if not candy: | ||
73 | return | 73 | return | ||
74 | 74 | ||||
75 | self._basket.append(candy) | 75 | self._basket.append(candy) | ||
76 | 76 | ||||
77 | def is_critical(self): | 77 | def is_critical(self): | ||
78 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 78 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
79 | return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 79 | return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
80 | 80 | ||||
81 | def get_total_uranium_in_basket(self): | 81 | def get_total_uranium_in_basket(self): | ||
82 | """Get the total Amount of Uranium in the Basket.""" | 82 | """Get the total Amount of Uranium in the Basket.""" | ||
83 | return sum([candy.get_uranium_quantity() for candy in self._basket]) | 83 | return sum([candy.get_uranium_quantity() for candy in self._basket]) | ||
84 | 84 | ||||
85 | def __repr__(self): | 85 | def __repr__(self): | ||
86 | return (f'{super().__repr__()}, Initiative: {self._initiative},' | 86 | return (f'{super().__repr__()}, Initiative: {self._initiative},' | ||
87 | f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g') | 87 | f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g') | ||
88 | 88 | ||||
89 | 89 | ||||
90 | class Host(Person): | 90 | class Host(Person): | ||
91 | """A Class that represents a Host.""" | 91 | """A Class that represents a Host.""" | ||
92 | 92 | ||||
93 | def __init__(self, position: tuple, candies: list): | 93 | def __init__(self, position: tuple, candies: list): | ||
94 | super().__init__(position) | 94 | super().__init__(position) | ||
95 | self._basket = candies[:] | 95 | self._basket = candies[:] | ||
96 | 96 | ||||
97 | def remove_candy(self, candy_choosing_function): | 97 | def remove_candy(self, candy_choosing_function): | ||
98 | """Select a Candy from the Basket based on the passed in Function.""" | 98 | """Select a Candy from the Basket based on the passed in Function.""" | ||
99 | if not self._basket: | 99 | if not self._basket: | ||
100 | return None | 100 | return None | ||
101 | 101 | ||||
102 | chosen_candy = candy_choosing_function(self._basket) | 102 | chosen_candy = candy_choosing_function(self._basket) | ||
103 | self._basket.remove(chosen_candy) | 103 | self._basket.remove(chosen_candy) | ||
104 | return chosen_candy or None | 104 | return chosen_candy or None | ||
105 | 105 | ||||
106 | 106 | ||||
107 | class FluxCapacitor: | 107 | class FluxCapacitor: | ||
108 | """Class that represents a simulation of a Halloween night.""" | 108 | """Class that represents a simulation of a Halloween night.""" | ||
109 | 109 | ||||
110 | def __init__(self, participants: set): | 110 | def __init__(self, participants: set): | ||
111 | self._kids = [] | 111 | self._kids = [] | ||
112 | self._hosts = [] | 112 | self._hosts = [] | ||
113 | self._hosts_visitation_table = {} | 113 | self._hosts_visitation_table = {} | ||
114 | self._fill_participants(participants) | 114 | self._fill_participants(participants) | ||
115 | 115 | ||||
116 | def _fill_participants(self, participants: set): | 116 | def _fill_participants(self, participants: set): | ||
117 | for participant in participants: | 117 | for participant in participants: | ||
118 | if type(participant) is Kid: | 118 | if type(participant) is Kid: | ||
119 | self._kids.append(participant) | 119 | self._kids.append(participant) | ||
120 | else: | 120 | else: | ||
121 | self._hosts.append(participant) | 121 | self._hosts.append(participant) | ||
122 | 122 | ||||
123 | def get_victim(self): | 123 | def get_victim(self): | ||
124 | """Simulate a Halloween night and return the first Kids that are critical.""" | 124 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
125 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | 125 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
126 | if critical_kids is None: | 126 | if critical_kids is None: | ||
127 | return None | 127 | return None | ||
128 | 128 | ||||
129 | return set(critical_kids) or None | 129 | return set(critical_kids) or None | ||
130 | 130 | ||||
131 | def _have_the_kids_visited_all_hosts(self): | 131 | def _have_the_kids_visited_all_hosts(self): | ||
132 | """Return true if all the Kids have visited all the Hosts.""" | 132 | """Return true if all the Kids have visited all the Hosts.""" | ||
n | 133 | return all([self._hosts in self._hosts_visitation_table.get(kid, []) for kid in self._kids]) | n | 133 | return all([len(self._hosts_visitation_table.get(kid, set())) == len(self._hosts) for kid in self._kids]) |
134 | 134 | ||||
135 | def _simulate_one_iteration_of_trick_or_treat(self): | 135 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
136 | """Simulate one cycle of Kids taking Candy from Hosts. | 136 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
137 | 137 | ||||
138 | Return the Kids that are critical after the Cycle or | 138 | Return the Kids that are critical after the Cycle or | ||
139 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 139 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
140 | an empty List if there are no critical Kids after the Cycle or | 140 | an empty List if there are no critical Kids after the Cycle or | ||
141 | all the Kids have visited all the Hosts. | 141 | all the Kids have visited all the Hosts. | ||
142 | """ | 142 | """ | ||
143 | 143 | ||||
144 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | 144 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | ||
145 | none_critical_kids_sorted_by_initiative = sorted( | 145 | none_critical_kids_sorted_by_initiative = sorted( | ||
146 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | 146 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | ||
147 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | 147 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | ||
148 | ) | 148 | ) | ||
149 | 149 | ||||
150 | if (not none_critical_kids_sorted_by_initiative or | 150 | if (not none_critical_kids_sorted_by_initiative or | ||
151 | not hosts_with_candies or self._have_the_kids_visited_all_hosts()): | 151 | not hosts_with_candies or self._have_the_kids_visited_all_hosts()): | ||
152 | return None | 152 | return None | ||
153 | 153 | ||||
154 | critical_kids = [] | 154 | critical_kids = [] | ||
155 | for kid in none_critical_kids_sorted_by_initiative: | 155 | for kid in none_critical_kids_sorted_by_initiative: | ||
156 | hosts_not_visited_by_current_kid = list( | 156 | hosts_not_visited_by_current_kid = list( | ||
157 | filter( | 157 | filter( | ||
158 | lambda curr_host: curr_host not in self._hosts_visitation_table.get(kid, set()), | 158 | lambda curr_host: curr_host not in self._hosts_visitation_table.get(kid, set()), | ||
159 | hosts_with_candies | 159 | hosts_with_candies | ||
160 | ) | 160 | ) | ||
161 | ) | 161 | ) | ||
162 | 162 | ||||
163 | if not hosts_not_visited_by_current_kid: | 163 | if not hosts_not_visited_by_current_kid: | ||
164 | continue | 164 | continue | ||
165 | 165 | ||||
166 | min_dist_host = get_host_with_min_distance(kid, hosts_not_visited_by_current_kid) | 166 | min_dist_host = get_host_with_min_distance(kid, hosts_not_visited_by_current_kid) | ||
167 | kid.set_position(min_dist_host.get_position()) | 167 | kid.set_position(min_dist_host.get_position()) | ||
168 | 168 | ||||
t | 169 | self._hosts_visitation_table[kid] = self._hosts_visitation_table.get(kid, []) | t | 169 | self._hosts_visitation_table[kid] = self._hosts_visitation_table.get(kid, set()) |
170 | self._hosts_visitation_table[kid].append(min_dist_host) | 170 | self._hosts_visitation_table[kid].add(min_dist_host) | ||
171 | 171 | ||||
172 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 172 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
173 | kid.add_candy(removed_candy) | 173 | kid.add_candy(removed_candy) | ||
174 | 174 | ||||
175 | if kid.is_critical(): | 175 | if kid.is_critical(): | ||
176 | critical_kids.append(kid) | 176 | critical_kids.append(kid) | ||
177 | 177 | ||||
178 | return critical_kids | 178 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, | 8 | return min(hosts, | ||
9 | key=(lambda host: (host.get_distance_to_person(kid), host.get_position()[0], host.get_position()[1]))) | 9 | key=(lambda host: (host.get_distance_to_person(kid), host.get_position()[0], host.get_position()[1]))) | ||
10 | 10 | ||||
11 | 11 | ||||
12 | class Candy: | 12 | class Candy: | ||
13 | """A Class that represents a Candy.""" | 13 | """A Class that represents a Candy.""" | ||
14 | 14 | ||||
15 | def __init__(self, mass: float, uranium: float): | 15 | def __init__(self, mass: float, uranium: float): | ||
16 | self._mass = mass | 16 | self._mass = mass | ||
17 | self._uranium = uranium | 17 | self._uranium = uranium | ||
18 | 18 | ||||
19 | def get_mass(self): | 19 | def get_mass(self): | ||
20 | """Return the Mass of the Candy.""" | 20 | """Return the Mass of the Candy.""" | ||
21 | return self._mass | 21 | return self._mass | ||
22 | 22 | ||||
23 | def get_uranium_quantity(self): | 23 | def get_uranium_quantity(self): | ||
24 | """Return the total Amount of Uranium in the Candy.""" | 24 | """Return the total Amount of Uranium in the Candy.""" | ||
25 | return self._mass * self._uranium | 25 | return self._mass * self._uranium | ||
26 | 26 | ||||
27 | 27 | ||||
28 | class Person: | 28 | class Person: | ||
29 | """A Class that Represents a Person.""" | 29 | """A Class that Represents a Person.""" | ||
30 | 30 | ||||
31 | def __init__(self, position: tuple): | 31 | def __init__(self, position: tuple): | ||
32 | self._position = None | 32 | self._position = None | ||
33 | self.set_position(position) | 33 | self.set_position(position) | ||
34 | self._basket = [] | 34 | self._basket = [] | ||
35 | 35 | ||||
36 | def get_position(self): | 36 | def get_position(self): | ||
37 | """Return the Position of the Person.""" | 37 | """Return the Position of the Person.""" | ||
38 | return self._position | 38 | return self._position | ||
39 | 39 | ||||
40 | def set_position(self, position: tuple): | 40 | def set_position(self, position: tuple): | ||
41 | """Change the Position of the Person.""" | 41 | """Change the Position of the Person.""" | ||
42 | self._position = position | 42 | self._position = position | ||
43 | 43 | ||||
44 | def get_distance_to_person(self, person): | 44 | def get_distance_to_person(self, person): | ||
45 | """Return the Distance from the current Person to the passed in Person.""" | 45 | """Return the Distance from the current Person to the passed in Person.""" | ||
46 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 46 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
47 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 47 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
48 | 48 | ||||
49 | def is_basket_empty(self): | 49 | def is_basket_empty(self): | ||
50 | """Return true if the Basket is empty.""" | 50 | """Return true if the Basket is empty.""" | ||
51 | return not self._basket | 51 | return not self._basket | ||
52 | 52 | ||||
53 | def __repr__(self): | 53 | def __repr__(self): | ||
54 | return f'{self._position}, Basket: {len(self._basket)}' | 54 | return f'{self._position}, Basket: {len(self._basket)}' | ||
55 | 55 | ||||
56 | 56 | ||||
57 | class Kid(Person): | 57 | class Kid(Person): | ||
58 | """A Class that represents a Kid.""" | 58 | """A Class that represents a Kid.""" | ||
59 | 59 | ||||
60 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 60 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
61 | 61 | ||||
62 | def __init__(self, position: tuple, initiative: int): | 62 | def __init__(self, position: tuple, initiative: int): | ||
63 | super().__init__(position) | 63 | super().__init__(position) | ||
64 | self._initiative = initiative | 64 | self._initiative = initiative | ||
65 | 65 | ||||
66 | def get_initiative(self): | 66 | def get_initiative(self): | ||
67 | """Return the Initiative of the Kid.""" | 67 | """Return the Initiative of the Kid.""" | ||
68 | return self._initiative | 68 | return self._initiative | ||
69 | 69 | ||||
70 | def add_candy(self, candy: Candy or None): | 70 | def add_candy(self, candy: Candy or None): | ||
71 | """Add a Candy to the Basket.""" | 71 | """Add a Candy to the Basket.""" | ||
72 | if not candy: | 72 | if not candy: | ||
73 | return | 73 | return | ||
74 | 74 | ||||
75 | self._basket.append(candy) | 75 | self._basket.append(candy) | ||
76 | 76 | ||||
77 | def is_critical(self): | 77 | def is_critical(self): | ||
78 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 78 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
79 | return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 79 | return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
80 | 80 | ||||
81 | def get_total_uranium_in_basket(self): | 81 | def get_total_uranium_in_basket(self): | ||
82 | """Get the total Amount of Uranium in the Basket.""" | 82 | """Get the total Amount of Uranium in the Basket.""" | ||
83 | return sum([candy.get_uranium_quantity() for candy in self._basket]) | 83 | return sum([candy.get_uranium_quantity() for candy in self._basket]) | ||
84 | 84 | ||||
85 | def __repr__(self): | 85 | def __repr__(self): | ||
86 | return (f'{super().__repr__()}, Initiative: {self._initiative},' | 86 | return (f'{super().__repr__()}, Initiative: {self._initiative},' | ||
87 | f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g') | 87 | f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g') | ||
88 | 88 | ||||
89 | 89 | ||||
90 | class Host(Person): | 90 | class Host(Person): | ||
91 | """A Class that represents a Host.""" | 91 | """A Class that represents a Host.""" | ||
92 | 92 | ||||
93 | def __init__(self, position: tuple, candies: list): | 93 | def __init__(self, position: tuple, candies: list): | ||
94 | super().__init__(position) | 94 | super().__init__(position) | ||
95 | self._basket = candies[:] | 95 | self._basket = candies[:] | ||
96 | 96 | ||||
97 | def remove_candy(self, candy_choosing_function): | 97 | def remove_candy(self, candy_choosing_function): | ||
98 | """Select a Candy from the Basket based on the passed in Function.""" | 98 | """Select a Candy from the Basket based on the passed in Function.""" | ||
99 | if not self._basket: | 99 | if not self._basket: | ||
100 | return None | 100 | return None | ||
101 | 101 | ||||
102 | chosen_candy = candy_choosing_function(self._basket) | 102 | chosen_candy = candy_choosing_function(self._basket) | ||
103 | self._basket.remove(chosen_candy) | 103 | self._basket.remove(chosen_candy) | ||
104 | return chosen_candy or None | 104 | return chosen_candy or None | ||
105 | 105 | ||||
106 | 106 | ||||
107 | class FluxCapacitor: | 107 | class FluxCapacitor: | ||
108 | """Class that represents a simulation of a Halloween night.""" | 108 | """Class that represents a simulation of a Halloween night.""" | ||
109 | 109 | ||||
110 | def __init__(self, participants: set): | 110 | def __init__(self, participants: set): | ||
111 | self._kids = [] | 111 | self._kids = [] | ||
112 | self._hosts = [] | 112 | self._hosts = [] | ||
113 | self._hosts_visitation_table = {} | 113 | self._hosts_visitation_table = {} | ||
114 | self._fill_participants(participants) | 114 | self._fill_participants(participants) | ||
115 | 115 | ||||
116 | def _fill_participants(self, participants: set): | 116 | def _fill_participants(self, participants: set): | ||
117 | for participant in participants: | 117 | for participant in participants: | ||
118 | if type(participant) is Kid: | 118 | if type(participant) is Kid: | ||
119 | self._kids.append(participant) | 119 | self._kids.append(participant) | ||
120 | else: | 120 | else: | ||
121 | self._hosts.append(participant) | 121 | self._hosts.append(participant) | ||
122 | 122 | ||||
123 | def get_victim(self): | 123 | def get_victim(self): | ||
124 | """Simulate a Halloween night and return the first Kids that are critical.""" | 124 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
125 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | 125 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
126 | if critical_kids is None: | 126 | if critical_kids is None: | ||
127 | return None | 127 | return None | ||
128 | 128 | ||||
129 | return set(critical_kids) or None | 129 | return set(critical_kids) or None | ||
130 | 130 | ||||
131 | def _have_the_kids_visited_all_hosts(self): | 131 | def _have_the_kids_visited_all_hosts(self): | ||
132 | """Return true if all the Kids have visited all the Hosts.""" | 132 | """Return true if all the Kids have visited all the Hosts.""" | ||
n | 133 | return all([len(self._hosts_visitation_table.get(kid, set())) == len(self._hosts) for kid in self._kids]) | n | 133 | return all([self._hosts in self._hosts_visitation_table.get(kid, []) for kid in self._kids]) |
134 | 134 | ||||
135 | def _simulate_one_iteration_of_trick_or_treat(self): | 135 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
136 | """Simulate one cycle of Kids taking Candy from Hosts. | 136 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
137 | 137 | ||||
138 | Return the Kids that are critical after the Cycle or | 138 | Return the Kids that are critical after the Cycle or | ||
139 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 139 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
140 | an empty List if there are no critical Kids after the Cycle or | 140 | an empty List if there are no critical Kids after the Cycle or | ||
141 | all the Kids have visited all the Hosts. | 141 | all the Kids have visited all the Hosts. | ||
142 | """ | 142 | """ | ||
143 | 143 | ||||
144 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | 144 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | ||
145 | none_critical_kids_sorted_by_initiative = sorted( | 145 | none_critical_kids_sorted_by_initiative = sorted( | ||
146 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | 146 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | ||
147 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | 147 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | ||
148 | ) | 148 | ) | ||
149 | 149 | ||||
150 | if (not none_critical_kids_sorted_by_initiative or | 150 | if (not none_critical_kids_sorted_by_initiative or | ||
151 | not hosts_with_candies or self._have_the_kids_visited_all_hosts()): | 151 | not hosts_with_candies or self._have_the_kids_visited_all_hosts()): | ||
152 | return None | 152 | return None | ||
153 | 153 | ||||
154 | critical_kids = [] | 154 | critical_kids = [] | ||
155 | for kid in none_critical_kids_sorted_by_initiative: | 155 | for kid in none_critical_kids_sorted_by_initiative: | ||
156 | hosts_not_visited_by_current_kid = list( | 156 | hosts_not_visited_by_current_kid = list( | ||
157 | filter( | 157 | filter( | ||
158 | lambda curr_host: curr_host not in self._hosts_visitation_table.get(kid, set()), | 158 | lambda curr_host: curr_host not in self._hosts_visitation_table.get(kid, set()), | ||
159 | hosts_with_candies | 159 | hosts_with_candies | ||
160 | ) | 160 | ) | ||
161 | ) | 161 | ) | ||
162 | 162 | ||||
163 | if not hosts_not_visited_by_current_kid: | 163 | if not hosts_not_visited_by_current_kid: | ||
164 | continue | 164 | continue | ||
165 | 165 | ||||
166 | min_dist_host = get_host_with_min_distance(kid, hosts_not_visited_by_current_kid) | 166 | min_dist_host = get_host_with_min_distance(kid, hosts_not_visited_by_current_kid) | ||
167 | kid.set_position(min_dist_host.get_position()) | 167 | kid.set_position(min_dist_host.get_position()) | ||
168 | 168 | ||||
t | 169 | self._hosts_visitation_table[kid] = self._hosts_visitation_table.get(kid, set()) | t | 169 | self._hosts_visitation_table[kid] = self._hosts_visitation_table.get(kid, []) |
170 | self._hosts_visitation_table[kid].add(min_dist_host) | 170 | self._hosts_visitation_table[kid].append(min_dist_host) | ||
171 | 171 | ||||
172 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 172 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
173 | kid.add_candy(removed_candy) | 173 | kid.add_candy(removed_candy) | ||
174 | 174 | ||||
175 | if kid.is_critical(): | 175 | if kid.is_critical(): | ||
176 | critical_kids.append(kid) | 176 | critical_kids.append(kid) | ||
177 | 177 | ||||
178 | return critical_kids | 178 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, | 8 | return min(hosts, | ||
9 | key=(lambda host: (host.get_distance_to_person(kid), host.get_position()[0], host.get_position()[1]))) | 9 | key=(lambda host: (host.get_distance_to_person(kid), host.get_position()[0], host.get_position()[1]))) | ||
10 | 10 | ||||
11 | 11 | ||||
12 | class Candy: | 12 | class Candy: | ||
13 | """A Class that represents a Candy.""" | 13 | """A Class that represents a Candy.""" | ||
14 | 14 | ||||
15 | def __init__(self, mass: float, uranium: float): | 15 | def __init__(self, mass: float, uranium: float): | ||
16 | self._mass = mass | 16 | self._mass = mass | ||
17 | self._uranium = uranium | 17 | self._uranium = uranium | ||
18 | 18 | ||||
19 | def get_mass(self): | 19 | def get_mass(self): | ||
20 | """Return the Mass of the Candy.""" | 20 | """Return the Mass of the Candy.""" | ||
21 | return self._mass | 21 | return self._mass | ||
22 | 22 | ||||
23 | def get_uranium_quantity(self): | 23 | def get_uranium_quantity(self): | ||
24 | """Return the total Amount of Uranium in the Candy.""" | 24 | """Return the total Amount of Uranium in the Candy.""" | ||
25 | return self._mass * self._uranium | 25 | return self._mass * self._uranium | ||
26 | 26 | ||||
27 | 27 | ||||
28 | class Person: | 28 | class Person: | ||
29 | """A Class that Represents a Person.""" | 29 | """A Class that Represents a Person.""" | ||
30 | 30 | ||||
31 | def __init__(self, position: tuple): | 31 | def __init__(self, position: tuple): | ||
32 | self._position = None | 32 | self._position = None | ||
33 | self.set_position(position) | 33 | self.set_position(position) | ||
34 | self._basket = [] | 34 | self._basket = [] | ||
35 | 35 | ||||
36 | def get_position(self): | 36 | def get_position(self): | ||
37 | """Return the Position of the Person.""" | 37 | """Return the Position of the Person.""" | ||
38 | return self._position | 38 | return self._position | ||
39 | 39 | ||||
40 | def set_position(self, position: tuple): | 40 | def set_position(self, position: tuple): | ||
41 | """Change the Position of the Person.""" | 41 | """Change the Position of the Person.""" | ||
42 | self._position = position | 42 | self._position = position | ||
43 | 43 | ||||
44 | def get_distance_to_person(self, person): | 44 | def get_distance_to_person(self, person): | ||
45 | """Return the Distance from the current Person to the passed in Person.""" | 45 | """Return the Distance from the current Person to the passed in Person.""" | ||
46 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 46 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
47 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 47 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
48 | 48 | ||||
49 | def is_basket_empty(self): | 49 | def is_basket_empty(self): | ||
50 | """Return true if the Basket is empty.""" | 50 | """Return true if the Basket is empty.""" | ||
51 | return not self._basket | 51 | return not self._basket | ||
52 | 52 | ||||
53 | def __repr__(self): | 53 | def __repr__(self): | ||
54 | return f'{self._position}, Basket: {len(self._basket)}' | 54 | return f'{self._position}, Basket: {len(self._basket)}' | ||
55 | 55 | ||||
56 | 56 | ||||
57 | class Kid(Person): | 57 | class Kid(Person): | ||
58 | """A Class that represents a Kid.""" | 58 | """A Class that represents a Kid.""" | ||
59 | 59 | ||||
60 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 60 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
61 | 61 | ||||
62 | def __init__(self, position: tuple, initiative: int): | 62 | def __init__(self, position: tuple, initiative: int): | ||
63 | super().__init__(position) | 63 | super().__init__(position) | ||
64 | self._initiative = initiative | 64 | self._initiative = initiative | ||
65 | 65 | ||||
66 | def get_initiative(self): | 66 | def get_initiative(self): | ||
67 | """Return the Initiative of the Kid.""" | 67 | """Return the Initiative of the Kid.""" | ||
68 | return self._initiative | 68 | return self._initiative | ||
69 | 69 | ||||
70 | def add_candy(self, candy: Candy or None): | 70 | def add_candy(self, candy: Candy or None): | ||
71 | """Add a Candy to the Basket.""" | 71 | """Add a Candy to the Basket.""" | ||
72 | if not candy: | 72 | if not candy: | ||
73 | return | 73 | return | ||
74 | 74 | ||||
75 | self._basket.append(candy) | 75 | self._basket.append(candy) | ||
76 | 76 | ||||
77 | def is_critical(self): | 77 | def is_critical(self): | ||
78 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 78 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
79 | return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 79 | return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
80 | 80 | ||||
81 | def get_total_uranium_in_basket(self): | 81 | def get_total_uranium_in_basket(self): | ||
82 | """Get the total Amount of Uranium in the Basket.""" | 82 | """Get the total Amount of Uranium in the Basket.""" | ||
83 | return sum([candy.get_uranium_quantity() for candy in self._basket]) | 83 | return sum([candy.get_uranium_quantity() for candy in self._basket]) | ||
84 | 84 | ||||
85 | def __repr__(self): | 85 | def __repr__(self): | ||
86 | return (f'{super().__repr__()}, Initiative: {self._initiative},' | 86 | return (f'{super().__repr__()}, Initiative: {self._initiative},' | ||
87 | f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g') | 87 | f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g') | ||
88 | 88 | ||||
89 | 89 | ||||
90 | class Host(Person): | 90 | class Host(Person): | ||
91 | """A Class that represents a Host.""" | 91 | """A Class that represents a Host.""" | ||
92 | 92 | ||||
93 | def __init__(self, position: tuple, candies: list): | 93 | def __init__(self, position: tuple, candies: list): | ||
94 | super().__init__(position) | 94 | super().__init__(position) | ||
95 | self._basket = candies[:] | 95 | self._basket = candies[:] | ||
96 | 96 | ||||
97 | def remove_candy(self, candy_choosing_function): | 97 | def remove_candy(self, candy_choosing_function): | ||
98 | """Select a Candy from the Basket based on the passed in Function.""" | 98 | """Select a Candy from the Basket based on the passed in Function.""" | ||
99 | if not self._basket: | 99 | if not self._basket: | ||
100 | return None | 100 | return None | ||
101 | 101 | ||||
102 | chosen_candy = candy_choosing_function(self._basket) | 102 | chosen_candy = candy_choosing_function(self._basket) | ||
103 | self._basket.remove(chosen_candy) | 103 | self._basket.remove(chosen_candy) | ||
104 | return chosen_candy or None | 104 | return chosen_candy or None | ||
105 | 105 | ||||
106 | 106 | ||||
107 | class FluxCapacitor: | 107 | class FluxCapacitor: | ||
108 | """Class that represents a simulation of a Halloween night.""" | 108 | """Class that represents a simulation of a Halloween night.""" | ||
109 | 109 | ||||
110 | def __init__(self, participants: set): | 110 | def __init__(self, participants: set): | ||
111 | self._kids = [] | 111 | self._kids = [] | ||
112 | self._hosts = [] | 112 | self._hosts = [] | ||
113 | self._hosts_visitation_table = {} | 113 | self._hosts_visitation_table = {} | ||
114 | self._fill_participants(participants) | 114 | self._fill_participants(participants) | ||
115 | 115 | ||||
116 | def _fill_participants(self, participants: set): | 116 | def _fill_participants(self, participants: set): | ||
117 | for participant in participants: | 117 | for participant in participants: | ||
118 | if type(participant) is Kid: | 118 | if type(participant) is Kid: | ||
119 | self._kids.append(participant) | 119 | self._kids.append(participant) | ||
120 | else: | 120 | else: | ||
121 | self._hosts.append(participant) | 121 | self._hosts.append(participant) | ||
122 | 122 | ||||
123 | def get_victim(self): | 123 | def get_victim(self): | ||
124 | """Simulate a Halloween night and return the first Kids that are critical.""" | 124 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
125 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | 125 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
126 | if critical_kids is None: | 126 | if critical_kids is None: | ||
127 | return None | 127 | return None | ||
128 | 128 | ||||
129 | return set(critical_kids) or None | 129 | return set(critical_kids) or None | ||
130 | 130 | ||||
131 | def _have_the_kids_visited_all_hosts(self): | 131 | def _have_the_kids_visited_all_hosts(self): | ||
132 | """Return true if all the Kids have visited all the Hosts.""" | 132 | """Return true if all the Kids have visited all the Hosts.""" | ||
133 | return all([len(self._hosts_visitation_table.get(kid, set())) == len(self._hosts) for kid in self._kids]) | 133 | return all([len(self._hosts_visitation_table.get(kid, set())) == len(self._hosts) for kid in self._kids]) | ||
134 | 134 | ||||
135 | def _simulate_one_iteration_of_trick_or_treat(self): | 135 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
136 | """Simulate one cycle of Kids taking Candy from Hosts. | 136 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
137 | 137 | ||||
138 | Return the Kids that are critical after the Cycle or | 138 | Return the Kids that are critical after the Cycle or | ||
139 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 139 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
t | 140 | an empty List if there are no critical Kids after the Cycle. | t | 140 | an empty List if there are no critical Kids after the Cycle or |
141 | all the Kids have visited all the Hosts. | ||||
141 | """ | 142 | """ | ||
142 | 143 | ||||
143 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | 144 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | ||
144 | none_critical_kids_sorted_by_initiative = sorted( | 145 | none_critical_kids_sorted_by_initiative = sorted( | ||
145 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | 146 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | ||
146 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | 147 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | ||
147 | ) | 148 | ) | ||
148 | 149 | ||||
149 | if (not none_critical_kids_sorted_by_initiative or | 150 | if (not none_critical_kids_sorted_by_initiative or | ||
150 | not hosts_with_candies or self._have_the_kids_visited_all_hosts()): | 151 | not hosts_with_candies or self._have_the_kids_visited_all_hosts()): | ||
151 | return None | 152 | return None | ||
152 | 153 | ||||
153 | critical_kids = [] | 154 | critical_kids = [] | ||
154 | for kid in none_critical_kids_sorted_by_initiative: | 155 | for kid in none_critical_kids_sorted_by_initiative: | ||
155 | hosts_not_visited_by_current_kid = list( | 156 | hosts_not_visited_by_current_kid = list( | ||
156 | filter( | 157 | filter( | ||
157 | lambda curr_host: curr_host not in self._hosts_visitation_table.get(kid, set()), | 158 | lambda curr_host: curr_host not in self._hosts_visitation_table.get(kid, set()), | ||
158 | hosts_with_candies | 159 | hosts_with_candies | ||
159 | ) | 160 | ) | ||
160 | ) | 161 | ) | ||
161 | 162 | ||||
162 | if not hosts_not_visited_by_current_kid: | 163 | if not hosts_not_visited_by_current_kid: | ||
163 | continue | 164 | continue | ||
164 | 165 | ||||
165 | min_dist_host = get_host_with_min_distance(kid, hosts_not_visited_by_current_kid) | 166 | min_dist_host = get_host_with_min_distance(kid, hosts_not_visited_by_current_kid) | ||
166 | kid.set_position(min_dist_host.get_position()) | 167 | kid.set_position(min_dist_host.get_position()) | ||
167 | 168 | ||||
168 | self._hosts_visitation_table[kid] = self._hosts_visitation_table.get(kid, set()) | 169 | self._hosts_visitation_table[kid] = self._hosts_visitation_table.get(kid, set()) | ||
169 | self._hosts_visitation_table[kid].add(min_dist_host) | 170 | self._hosts_visitation_table[kid].add(min_dist_host) | ||
170 | 171 | ||||
171 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 172 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
172 | kid.add_candy(removed_candy) | 173 | kid.add_candy(removed_candy) | ||
173 | 174 | ||||
174 | if kid.is_critical(): | 175 | if kid.is_critical(): | ||
175 | critical_kids.append(kid) | 176 | critical_kids.append(kid) | ||
176 | 177 | ||||
177 | return critical_kids | 178 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
n | 8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | n | 8 | return min(hosts, |
9 | key=(lambda host: (host.get_distance_to_person(kid), host.get_position()[0], host.get_position()[1]))) | ||||
9 | 10 | ||||
10 | 11 | ||||
11 | class Candy: | 12 | class Candy: | ||
12 | """A Class that represents a Candy.""" | 13 | """A Class that represents a Candy.""" | ||
13 | 14 | ||||
14 | def __init__(self, mass: float, uranium: float): | 15 | def __init__(self, mass: float, uranium: float): | ||
15 | self._mass = mass | 16 | self._mass = mass | ||
16 | self._uranium = uranium | 17 | self._uranium = uranium | ||
17 | 18 | ||||
18 | def get_mass(self): | 19 | def get_mass(self): | ||
19 | """Return the Mass of the Candy.""" | 20 | """Return the Mass of the Candy.""" | ||
20 | return self._mass | 21 | return self._mass | ||
21 | 22 | ||||
22 | def get_uranium_quantity(self): | 23 | def get_uranium_quantity(self): | ||
23 | """Return the total Amount of Uranium in the Candy.""" | 24 | """Return the total Amount of Uranium in the Candy.""" | ||
24 | return self._mass * self._uranium | 25 | return self._mass * self._uranium | ||
25 | 26 | ||||
26 | 27 | ||||
27 | class Person: | 28 | class Person: | ||
28 | """A Class that Represents a Person.""" | 29 | """A Class that Represents a Person.""" | ||
29 | 30 | ||||
30 | def __init__(self, position: tuple): | 31 | def __init__(self, position: tuple): | ||
31 | self._position = None | 32 | self._position = None | ||
32 | self.set_position(position) | 33 | self.set_position(position) | ||
33 | self._basket = [] | 34 | self._basket = [] | ||
34 | 35 | ||||
35 | def get_position(self): | 36 | def get_position(self): | ||
36 | """Return the Position of the Person.""" | 37 | """Return the Position of the Person.""" | ||
37 | return self._position | 38 | return self._position | ||
38 | 39 | ||||
39 | def set_position(self, position: tuple): | 40 | def set_position(self, position: tuple): | ||
40 | """Change the Position of the Person.""" | 41 | """Change the Position of the Person.""" | ||
41 | self._position = position | 42 | self._position = position | ||
42 | 43 | ||||
43 | def get_distance_to_person(self, person): | 44 | def get_distance_to_person(self, person): | ||
44 | """Return the Distance from the current Person to the passed in Person.""" | 45 | """Return the Distance from the current Person to the passed in Person.""" | ||
45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 46 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 47 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
47 | 48 | ||||
48 | def is_basket_empty(self): | 49 | def is_basket_empty(self): | ||
49 | """Return true if the Basket is empty.""" | 50 | """Return true if the Basket is empty.""" | ||
50 | return not self._basket | 51 | return not self._basket | ||
51 | 52 | ||||
52 | def __repr__(self): | 53 | def __repr__(self): | ||
53 | return f'{self._position}, Basket: {len(self._basket)}' | 54 | return f'{self._position}, Basket: {len(self._basket)}' | ||
54 | 55 | ||||
55 | 56 | ||||
56 | class Kid(Person): | 57 | class Kid(Person): | ||
57 | """A Class that represents a Kid.""" | 58 | """A Class that represents a Kid.""" | ||
58 | 59 | ||||
59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 60 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
60 | 61 | ||||
61 | def __init__(self, position: tuple, initiative: int): | 62 | def __init__(self, position: tuple, initiative: int): | ||
62 | super().__init__(position) | 63 | super().__init__(position) | ||
63 | self._initiative = initiative | 64 | self._initiative = initiative | ||
64 | 65 | ||||
65 | def get_initiative(self): | 66 | def get_initiative(self): | ||
66 | """Return the Initiative of the Kid.""" | 67 | """Return the Initiative of the Kid.""" | ||
67 | return self._initiative | 68 | return self._initiative | ||
68 | 69 | ||||
69 | def add_candy(self, candy: Candy or None): | 70 | def add_candy(self, candy: Candy or None): | ||
70 | """Add a Candy to the Basket.""" | 71 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | 72 | if not candy: | ||
72 | return | 73 | return | ||
73 | 74 | ||||
74 | self._basket.append(candy) | 75 | self._basket.append(candy) | ||
75 | 76 | ||||
76 | def is_critical(self): | 77 | def is_critical(self): | ||
77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 78 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
78 | return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 79 | return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
79 | 80 | ||||
80 | def get_total_uranium_in_basket(self): | 81 | def get_total_uranium_in_basket(self): | ||
81 | """Get the total Amount of Uranium in the Basket.""" | 82 | """Get the total Amount of Uranium in the Basket.""" | ||
82 | return sum([candy.get_uranium_quantity() for candy in self._basket]) | 83 | return sum([candy.get_uranium_quantity() for candy in self._basket]) | ||
83 | 84 | ||||
84 | def __repr__(self): | 85 | def __repr__(self): | ||
85 | return (f'{super().__repr__()}, Initiative: {self._initiative},' | 86 | return (f'{super().__repr__()}, Initiative: {self._initiative},' | ||
86 | f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g') | 87 | f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g') | ||
87 | 88 | ||||
88 | 89 | ||||
89 | class Host(Person): | 90 | class Host(Person): | ||
90 | """A Class that represents a Host.""" | 91 | """A Class that represents a Host.""" | ||
91 | 92 | ||||
92 | def __init__(self, position: tuple, candies: list): | 93 | def __init__(self, position: tuple, candies: list): | ||
93 | super().__init__(position) | 94 | super().__init__(position) | ||
94 | self._basket = candies[:] | 95 | self._basket = candies[:] | ||
95 | 96 | ||||
96 | def remove_candy(self, candy_choosing_function): | 97 | def remove_candy(self, candy_choosing_function): | ||
97 | """Select a Candy from the Basket based on the passed in Function.""" | 98 | """Select a Candy from the Basket based on the passed in Function.""" | ||
98 | if not self._basket: | 99 | if not self._basket: | ||
99 | return None | 100 | return None | ||
100 | 101 | ||||
101 | chosen_candy = candy_choosing_function(self._basket) | 102 | chosen_candy = candy_choosing_function(self._basket) | ||
102 | self._basket.remove(chosen_candy) | 103 | self._basket.remove(chosen_candy) | ||
103 | return chosen_candy or None | 104 | return chosen_candy or None | ||
104 | 105 | ||||
105 | 106 | ||||
106 | class FluxCapacitor: | 107 | class FluxCapacitor: | ||
107 | """Class that represents a simulation of a Halloween night.""" | 108 | """Class that represents a simulation of a Halloween night.""" | ||
108 | 109 | ||||
109 | def __init__(self, participants: set): | 110 | def __init__(self, participants: set): | ||
110 | self._kids = [] | 111 | self._kids = [] | ||
111 | self._hosts = [] | 112 | self._hosts = [] | ||
n | n | 113 | self._hosts_visitation_table = {} | ||
112 | self._fill_participants(participants) | 114 | self._fill_participants(participants) | ||
113 | 115 | ||||
114 | def _fill_participants(self, participants: set): | 116 | def _fill_participants(self, participants: set): | ||
115 | for participant in participants: | 117 | for participant in participants: | ||
116 | if type(participant) is Kid: | 118 | if type(participant) is Kid: | ||
117 | self._kids.append(participant) | 119 | self._kids.append(participant) | ||
118 | else: | 120 | else: | ||
119 | self._hosts.append(participant) | 121 | self._hosts.append(participant) | ||
120 | 122 | ||||
121 | def get_victim(self): | 123 | def get_victim(self): | ||
122 | """Simulate a Halloween night and return the first Kids that are critical.""" | 124 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
123 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | 125 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
124 | if critical_kids is None: | 126 | if critical_kids is None: | ||
125 | return None | 127 | return None | ||
126 | 128 | ||||
127 | return set(critical_kids) or None | 129 | return set(critical_kids) or None | ||
128 | 130 | ||||
n | n | 131 | def _have_the_kids_visited_all_hosts(self): | ||
132 | """Return true if all the Kids have visited all the Hosts.""" | ||||
133 | return all([len(self._hosts_visitation_table.get(kid, set())) == len(self._hosts) for kid in self._kids]) | ||||
134 | |||||
129 | def _simulate_one_iteration_of_trick_or_treat(self): | 135 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
130 | """Simulate one cycle of Kids taking Candy from Hosts. | 136 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
131 | 137 | ||||
132 | Return the Kids that are critical after the Cycle or | 138 | Return the Kids that are critical after the Cycle or | ||
133 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 139 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
134 | an empty List if there are no critical Kids after the Cycle. | 140 | an empty List if there are no critical Kids after the Cycle. | ||
135 | """ | 141 | """ | ||
136 | 142 | ||||
137 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | 143 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | ||
138 | none_critical_kids_sorted_by_initiative = sorted( | 144 | none_critical_kids_sorted_by_initiative = sorted( | ||
139 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | 145 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | ||
140 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | 146 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | ||
141 | ) | 147 | ) | ||
142 | 148 | ||||
n | 143 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | n | 149 | if (not none_critical_kids_sorted_by_initiative or |
150 | not hosts_with_candies or self._have_the_kids_visited_all_hosts()): | ||||
144 | return None | 151 | return None | ||
145 | 152 | ||||
146 | critical_kids = [] | 153 | critical_kids = [] | ||
147 | for kid in none_critical_kids_sorted_by_initiative: | 154 | for kid in none_critical_kids_sorted_by_initiative: | ||
n | n | 155 | hosts_not_visited_by_current_kid = list( | ||
156 | filter( | ||||
157 | lambda curr_host: curr_host not in self._hosts_visitation_table.get(kid, set()), | ||||
158 | hosts_with_candies | ||||
159 | ) | ||||
160 | ) | ||||
161 | |||||
162 | if not hosts_not_visited_by_current_kid: | ||||
163 | continue | ||||
164 | |||||
148 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | 165 | min_dist_host = get_host_with_min_distance(kid, hosts_not_visited_by_current_kid) | ||
149 | kid.set_position(min_dist_host.get_position()) | 166 | kid.set_position(min_dist_host.get_position()) | ||
t | t | 167 | |||
168 | self._hosts_visitation_table[kid] = self._hosts_visitation_table.get(kid, set()) | ||||
169 | self._hosts_visitation_table[kid].add(min_dist_host) | ||||
150 | 170 | ||||
151 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 171 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
152 | kid.add_candy(removed_candy) | 172 | kid.add_candy(removed_candy) | ||
153 | 173 | ||||
154 | if kid.is_critical(): | 174 | if kid.is_critical(): | ||
155 | critical_kids.append(kid) | 175 | critical_kids.append(kid) | ||
156 | 176 | ||||
157 | return critical_kids | 177 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | 8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | ||
9 | 9 | ||||
10 | 10 | ||||
11 | class Candy: | 11 | class Candy: | ||
12 | """A Class that represents a Candy.""" | 12 | """A Class that represents a Candy.""" | ||
13 | 13 | ||||
14 | def __init__(self, mass: float, uranium: float): | 14 | def __init__(self, mass: float, uranium: float): | ||
15 | self._mass = mass | 15 | self._mass = mass | ||
16 | self._uranium = uranium | 16 | self._uranium = uranium | ||
17 | 17 | ||||
18 | def get_mass(self): | 18 | def get_mass(self): | ||
19 | """Return the Mass of the Candy.""" | 19 | """Return the Mass of the Candy.""" | ||
20 | return self._mass | 20 | return self._mass | ||
21 | 21 | ||||
22 | def get_uranium_quantity(self): | 22 | def get_uranium_quantity(self): | ||
23 | """Return the total Amount of Uranium in the Candy.""" | 23 | """Return the total Amount of Uranium in the Candy.""" | ||
24 | return self._mass * self._uranium | 24 | return self._mass * self._uranium | ||
25 | 25 | ||||
26 | 26 | ||||
27 | class Person: | 27 | class Person: | ||
28 | """A Class that Represents a Person.""" | 28 | """A Class that Represents a Person.""" | ||
29 | 29 | ||||
30 | def __init__(self, position: tuple): | 30 | def __init__(self, position: tuple): | ||
31 | self._position = None | 31 | self._position = None | ||
32 | self.set_position(position) | 32 | self.set_position(position) | ||
33 | self._basket = [] | 33 | self._basket = [] | ||
34 | 34 | ||||
35 | def get_position(self): | 35 | def get_position(self): | ||
36 | """Return the Position of the Person.""" | 36 | """Return the Position of the Person.""" | ||
37 | return self._position | 37 | return self._position | ||
38 | 38 | ||||
39 | def set_position(self, position: tuple): | 39 | def set_position(self, position: tuple): | ||
40 | """Change the Position of the Person.""" | 40 | """Change the Position of the Person.""" | ||
41 | self._position = position | 41 | self._position = position | ||
42 | 42 | ||||
43 | def get_distance_to_person(self, person): | 43 | def get_distance_to_person(self, person): | ||
44 | """Return the Distance from the current Person to the passed in Person.""" | 44 | """Return the Distance from the current Person to the passed in Person.""" | ||
45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
47 | 47 | ||||
48 | def is_basket_empty(self): | 48 | def is_basket_empty(self): | ||
49 | """Return true if the Basket is empty.""" | 49 | """Return true if the Basket is empty.""" | ||
50 | return not self._basket | 50 | return not self._basket | ||
51 | 51 | ||||
52 | def __repr__(self): | 52 | def __repr__(self): | ||
n | 53 | return f'{self._position}' | n | 53 | return f'{self._position}, Basket: {len(self._basket)}' |
54 | 54 | ||||
55 | 55 | ||||
56 | class Kid(Person): | 56 | class Kid(Person): | ||
57 | """A Class that represents a Kid.""" | 57 | """A Class that represents a Kid.""" | ||
58 | 58 | ||||
59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
60 | 60 | ||||
61 | def __init__(self, position: tuple, initiative: int): | 61 | def __init__(self, position: tuple, initiative: int): | ||
62 | super().__init__(position) | 62 | super().__init__(position) | ||
63 | self._initiative = initiative | 63 | self._initiative = initiative | ||
64 | 64 | ||||
65 | def get_initiative(self): | 65 | def get_initiative(self): | ||
66 | """Return the Initiative of the Kid.""" | 66 | """Return the Initiative of the Kid.""" | ||
67 | return self._initiative | 67 | return self._initiative | ||
68 | 68 | ||||
69 | def add_candy(self, candy: Candy or None): | 69 | def add_candy(self, candy: Candy or None): | ||
70 | """Add a Candy to the Basket.""" | 70 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | 71 | if not candy: | ||
72 | return | 72 | return | ||
73 | 73 | ||||
74 | self._basket.append(candy) | 74 | self._basket.append(candy) | ||
75 | 75 | ||||
76 | def is_critical(self): | 76 | def is_critical(self): | ||
77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
n | n | 78 | return self.get_total_uranium_in_basket() > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
79 | |||||
80 | def get_total_uranium_in_basket(self): | ||||
81 | """Get the total Amount of Uranium in the Basket.""" | ||||
78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 82 | return sum([candy.get_uranium_quantity() for candy in self._basket]) | ||
79 | 83 | ||||
80 | def __repr__(self): | 84 | def __repr__(self): | ||
t | 81 | return f'{super().__repr__()} : {self._initiative}' | t | 85 | return (f'{super().__repr__()}, Initiative: {self._initiative},' |
86 | f' Total Uranium: {self.get_total_uranium_in_basket():.2f}g') | ||||
82 | 87 | ||||
83 | 88 | ||||
84 | class Host(Person): | 89 | class Host(Person): | ||
85 | """A Class that represents a Host.""" | 90 | """A Class that represents a Host.""" | ||
86 | 91 | ||||
87 | def __init__(self, position: tuple, candies: list): | 92 | def __init__(self, position: tuple, candies: list): | ||
88 | super().__init__(position) | 93 | super().__init__(position) | ||
89 | self._basket = candies[:] | 94 | self._basket = candies[:] | ||
90 | 95 | ||||
91 | def remove_candy(self, candy_choosing_function): | 96 | def remove_candy(self, candy_choosing_function): | ||
92 | """Select a Candy from the Basket based on the passed in Function.""" | 97 | """Select a Candy from the Basket based on the passed in Function.""" | ||
93 | if not self._basket: | 98 | if not self._basket: | ||
94 | return None | 99 | return None | ||
95 | 100 | ||||
96 | chosen_candy = candy_choosing_function(self._basket) | 101 | chosen_candy = candy_choosing_function(self._basket) | ||
97 | self._basket.remove(chosen_candy) | 102 | self._basket.remove(chosen_candy) | ||
98 | return chosen_candy or None | 103 | return chosen_candy or None | ||
99 | 104 | ||||
100 | 105 | ||||
101 | class FluxCapacitor: | 106 | class FluxCapacitor: | ||
102 | """Class that represents a simulation of a Halloween night.""" | 107 | """Class that represents a simulation of a Halloween night.""" | ||
103 | 108 | ||||
104 | def __init__(self, participants: set): | 109 | def __init__(self, participants: set): | ||
105 | self._kids = [] | 110 | self._kids = [] | ||
106 | self._hosts = [] | 111 | self._hosts = [] | ||
107 | self._fill_participants(participants) | 112 | self._fill_participants(participants) | ||
108 | 113 | ||||
109 | def _fill_participants(self, participants: set): | 114 | def _fill_participants(self, participants: set): | ||
110 | for participant in participants: | 115 | for participant in participants: | ||
111 | if type(participant) is Kid: | 116 | if type(participant) is Kid: | ||
112 | self._kids.append(participant) | 117 | self._kids.append(participant) | ||
113 | else: | 118 | else: | ||
114 | self._hosts.append(participant) | 119 | self._hosts.append(participant) | ||
115 | 120 | ||||
116 | def get_victim(self): | 121 | def get_victim(self): | ||
117 | """Simulate a Halloween night and return the first Kids that are critical.""" | 122 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | 123 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
119 | if critical_kids is None: | 124 | if critical_kids is None: | ||
120 | return None | 125 | return None | ||
121 | 126 | ||||
122 | return set(critical_kids) or None | 127 | return set(critical_kids) or None | ||
123 | 128 | ||||
124 | def _simulate_one_iteration_of_trick_or_treat(self): | 129 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
125 | """Simulate one cycle of Kids taking Candy from Hosts. | 130 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
126 | 131 | ||||
127 | Return the Kids that are critical after the Cycle or | 132 | Return the Kids that are critical after the Cycle or | ||
128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 133 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
129 | an empty List if there are no critical Kids after the Cycle. | 134 | an empty List if there are no critical Kids after the Cycle. | ||
130 | """ | 135 | """ | ||
131 | 136 | ||||
132 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | 137 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | ||
133 | none_critical_kids_sorted_by_initiative = sorted( | 138 | none_critical_kids_sorted_by_initiative = sorted( | ||
134 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | 139 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | ||
135 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | 140 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | ||
136 | ) | 141 | ) | ||
137 | 142 | ||||
138 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | 143 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | ||
139 | return None | 144 | return None | ||
140 | 145 | ||||
141 | critical_kids = [] | 146 | critical_kids = [] | ||
142 | for kid in none_critical_kids_sorted_by_initiative: | 147 | for kid in none_critical_kids_sorted_by_initiative: | ||
143 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | 148 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | ||
144 | kid.set_position(min_dist_host.get_position()) | 149 | kid.set_position(min_dist_host.get_position()) | ||
145 | 150 | ||||
146 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 151 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
147 | kid.add_candy(removed_candy) | 152 | kid.add_candy(removed_candy) | ||
148 | 153 | ||||
149 | if kid.is_critical(): | 154 | if kid.is_critical(): | ||
150 | critical_kids.append(kid) | 155 | critical_kids.append(kid) | ||
151 | 156 | ||||
152 | return critical_kids | 157 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | 8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | ||
9 | 9 | ||||
10 | 10 | ||||
11 | class Candy: | 11 | class Candy: | ||
12 | """A Class that represents a Candy.""" | 12 | """A Class that represents a Candy.""" | ||
13 | 13 | ||||
14 | def __init__(self, mass: float, uranium: float): | 14 | def __init__(self, mass: float, uranium: float): | ||
15 | self._mass = mass | 15 | self._mass = mass | ||
16 | self._uranium = uranium | 16 | self._uranium = uranium | ||
17 | 17 | ||||
18 | def get_mass(self): | 18 | def get_mass(self): | ||
19 | """Return the Mass of the Candy.""" | 19 | """Return the Mass of the Candy.""" | ||
20 | return self._mass | 20 | return self._mass | ||
21 | 21 | ||||
22 | def get_uranium_quantity(self): | 22 | def get_uranium_quantity(self): | ||
23 | """Return the total Amount of Uranium in the Candy.""" | 23 | """Return the total Amount of Uranium in the Candy.""" | ||
24 | return self._mass * self._uranium | 24 | return self._mass * self._uranium | ||
25 | 25 | ||||
26 | 26 | ||||
27 | class Person: | 27 | class Person: | ||
28 | """A Class that Represents a Person.""" | 28 | """A Class that Represents a Person.""" | ||
29 | 29 | ||||
30 | def __init__(self, position: tuple): | 30 | def __init__(self, position: tuple): | ||
31 | self._position = None | 31 | self._position = None | ||
32 | self.set_position(position) | 32 | self.set_position(position) | ||
33 | self._basket = [] | 33 | self._basket = [] | ||
34 | 34 | ||||
35 | def get_position(self): | 35 | def get_position(self): | ||
36 | """Return the Position of the Person.""" | 36 | """Return the Position of the Person.""" | ||
37 | return self._position | 37 | return self._position | ||
38 | 38 | ||||
39 | def set_position(self, position: tuple): | 39 | def set_position(self, position: tuple): | ||
40 | """Change the Position of the Person.""" | 40 | """Change the Position of the Person.""" | ||
41 | self._position = position | 41 | self._position = position | ||
42 | 42 | ||||
43 | def get_distance_to_person(self, person): | 43 | def get_distance_to_person(self, person): | ||
44 | """Return the Distance from the current Person to the passed in Person.""" | 44 | """Return the Distance from the current Person to the passed in Person.""" | ||
45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
47 | 47 | ||||
48 | def is_basket_empty(self): | 48 | def is_basket_empty(self): | ||
49 | """Return true if the Basket is empty.""" | 49 | """Return true if the Basket is empty.""" | ||
50 | return not self._basket | 50 | return not self._basket | ||
51 | 51 | ||||
52 | def __repr__(self): | 52 | def __repr__(self): | ||
53 | return f'{self._position}' | 53 | return f'{self._position}' | ||
54 | 54 | ||||
55 | 55 | ||||
56 | class Kid(Person): | 56 | class Kid(Person): | ||
57 | """A Class that represents a Kid.""" | 57 | """A Class that represents a Kid.""" | ||
58 | 58 | ||||
59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
60 | 60 | ||||
61 | def __init__(self, position: tuple, initiative: int): | 61 | def __init__(self, position: tuple, initiative: int): | ||
62 | super().__init__(position) | 62 | super().__init__(position) | ||
63 | self._initiative = initiative | 63 | self._initiative = initiative | ||
64 | 64 | ||||
65 | def get_initiative(self): | 65 | def get_initiative(self): | ||
66 | """Return the Initiative of the Kid.""" | 66 | """Return the Initiative of the Kid.""" | ||
67 | return self._initiative | 67 | return self._initiative | ||
68 | 68 | ||||
69 | def add_candy(self, candy: Candy or None): | 69 | def add_candy(self, candy: Candy or None): | ||
70 | """Add a Candy to the Basket.""" | 70 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | 71 | if not candy: | ||
72 | return | 72 | return | ||
73 | 73 | ||||
74 | self._basket.append(candy) | 74 | self._basket.append(candy) | ||
75 | 75 | ||||
76 | def is_critical(self): | 76 | def is_critical(self): | ||
77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
79 | 79 | ||||
80 | def __repr__(self): | 80 | def __repr__(self): | ||
81 | return f'{super().__repr__()} : {self._initiative}' | 81 | return f'{super().__repr__()} : {self._initiative}' | ||
82 | 82 | ||||
83 | 83 | ||||
84 | class Host(Person): | 84 | class Host(Person): | ||
85 | """A Class that represents a Host.""" | 85 | """A Class that represents a Host.""" | ||
86 | 86 | ||||
87 | def __init__(self, position: tuple, candies: list): | 87 | def __init__(self, position: tuple, candies: list): | ||
88 | super().__init__(position) | 88 | super().__init__(position) | ||
89 | self._basket = candies[:] | 89 | self._basket = candies[:] | ||
90 | 90 | ||||
91 | def remove_candy(self, candy_choosing_function): | 91 | def remove_candy(self, candy_choosing_function): | ||
92 | """Select a Candy from the Basket based on the passed in Function.""" | 92 | """Select a Candy from the Basket based on the passed in Function.""" | ||
93 | if not self._basket: | 93 | if not self._basket: | ||
94 | return None | 94 | return None | ||
95 | 95 | ||||
96 | chosen_candy = candy_choosing_function(self._basket) | 96 | chosen_candy = candy_choosing_function(self._basket) | ||
97 | self._basket.remove(chosen_candy) | 97 | self._basket.remove(chosen_candy) | ||
98 | return chosen_candy or None | 98 | return chosen_candy or None | ||
99 | 99 | ||||
100 | 100 | ||||
101 | class FluxCapacitor: | 101 | class FluxCapacitor: | ||
102 | """Class that represents a simulation of a Halloween night.""" | 102 | """Class that represents a simulation of a Halloween night.""" | ||
103 | 103 | ||||
104 | def __init__(self, participants: set): | 104 | def __init__(self, participants: set): | ||
105 | self._kids = [] | 105 | self._kids = [] | ||
106 | self._hosts = [] | 106 | self._hosts = [] | ||
t | 107 | self.__fill_participants(participants) | t | 107 | self._fill_participants(participants) |
108 | 108 | ||||
109 | def _fill_participants(self, participants: set): | 109 | def _fill_participants(self, participants: set): | ||
110 | for participant in participants: | 110 | for participant in participants: | ||
111 | if type(participant) is Kid: | 111 | if type(participant) is Kid: | ||
112 | self._kids.append(participant) | 112 | self._kids.append(participant) | ||
113 | else: | 113 | else: | ||
114 | self._hosts.append(participant) | 114 | self._hosts.append(participant) | ||
115 | 115 | ||||
116 | def get_victim(self): | 116 | def get_victim(self): | ||
117 | """Simulate a Halloween night and return the first Kids that are critical.""" | 117 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | 118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
119 | if critical_kids is None: | 119 | if critical_kids is None: | ||
120 | return None | 120 | return None | ||
121 | 121 | ||||
122 | return set(critical_kids) or None | 122 | return set(critical_kids) or None | ||
123 | 123 | ||||
124 | def _simulate_one_iteration_of_trick_or_treat(self): | 124 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
125 | """Simulate one cycle of Kids taking Candy from Hosts. | 125 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
126 | 126 | ||||
127 | Return the Kids that are critical after the Cycle or | 127 | Return the Kids that are critical after the Cycle or | ||
128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
129 | an empty List if there are no critical Kids after the Cycle. | 129 | an empty List if there are no critical Kids after the Cycle. | ||
130 | """ | 130 | """ | ||
131 | 131 | ||||
132 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | 132 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | ||
133 | none_critical_kids_sorted_by_initiative = sorted( | 133 | none_critical_kids_sorted_by_initiative = sorted( | ||
134 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | 134 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | ||
135 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | 135 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | ||
136 | ) | 136 | ) | ||
137 | 137 | ||||
138 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | 138 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | ||
139 | return None | 139 | return None | ||
140 | 140 | ||||
141 | critical_kids = [] | 141 | critical_kids = [] | ||
142 | for kid in none_critical_kids_sorted_by_initiative: | 142 | for kid in none_critical_kids_sorted_by_initiative: | ||
143 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | 143 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | ||
144 | kid.set_position(min_dist_host.get_position()) | 144 | kid.set_position(min_dist_host.get_position()) | ||
145 | 145 | ||||
146 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 146 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
147 | kid.add_candy(removed_candy) | 147 | kid.add_candy(removed_candy) | ||
148 | 148 | ||||
149 | if kid.is_critical(): | 149 | if kid.is_critical(): | ||
150 | critical_kids.append(kid) | 150 | critical_kids.append(kid) | ||
151 | 151 | ||||
152 | return critical_kids | 152 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | 8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | ||
9 | 9 | ||||
10 | 10 | ||||
11 | class Candy: | 11 | class Candy: | ||
12 | """A Class that represents a Candy.""" | 12 | """A Class that represents a Candy.""" | ||
13 | 13 | ||||
14 | def __init__(self, mass: float, uranium: float): | 14 | def __init__(self, mass: float, uranium: float): | ||
15 | self._mass = mass | 15 | self._mass = mass | ||
16 | self._uranium = uranium | 16 | self._uranium = uranium | ||
17 | 17 | ||||
18 | def get_mass(self): | 18 | def get_mass(self): | ||
19 | """Return the Mass of the Candy.""" | 19 | """Return the Mass of the Candy.""" | ||
20 | return self._mass | 20 | return self._mass | ||
21 | 21 | ||||
22 | def get_uranium_quantity(self): | 22 | def get_uranium_quantity(self): | ||
23 | """Return the total Amount of Uranium in the Candy.""" | 23 | """Return the total Amount of Uranium in the Candy.""" | ||
24 | return self._mass * self._uranium | 24 | return self._mass * self._uranium | ||
25 | 25 | ||||
26 | 26 | ||||
27 | class Person: | 27 | class Person: | ||
28 | """A Class that Represents a Person.""" | 28 | """A Class that Represents a Person.""" | ||
29 | 29 | ||||
30 | def __init__(self, position: tuple): | 30 | def __init__(self, position: tuple): | ||
31 | self._position = None | 31 | self._position = None | ||
32 | self.set_position(position) | 32 | self.set_position(position) | ||
33 | self._basket = [] | 33 | self._basket = [] | ||
34 | 34 | ||||
35 | def get_position(self): | 35 | def get_position(self): | ||
36 | """Return the Position of the Person.""" | 36 | """Return the Position of the Person.""" | ||
37 | return self._position | 37 | return self._position | ||
38 | 38 | ||||
39 | def set_position(self, position: tuple): | 39 | def set_position(self, position: tuple): | ||
40 | """Change the Position of the Person.""" | 40 | """Change the Position of the Person.""" | ||
41 | self._position = position | 41 | self._position = position | ||
42 | 42 | ||||
43 | def get_distance_to_person(self, person): | 43 | def get_distance_to_person(self, person): | ||
44 | """Return the Distance from the current Person to the passed in Person.""" | 44 | """Return the Distance from the current Person to the passed in Person.""" | ||
45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
47 | 47 | ||||
48 | def is_basket_empty(self): | 48 | def is_basket_empty(self): | ||
49 | """Return true if the Basket is empty.""" | 49 | """Return true if the Basket is empty.""" | ||
50 | return not self._basket | 50 | return not self._basket | ||
51 | 51 | ||||
52 | def __repr__(self): | 52 | def __repr__(self): | ||
53 | return f'{self._position}' | 53 | return f'{self._position}' | ||
54 | 54 | ||||
55 | 55 | ||||
56 | class Kid(Person): | 56 | class Kid(Person): | ||
57 | """A Class that represents a Kid.""" | 57 | """A Class that represents a Kid.""" | ||
58 | 58 | ||||
59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
60 | 60 | ||||
61 | def __init__(self, position: tuple, initiative: int): | 61 | def __init__(self, position: tuple, initiative: int): | ||
62 | super().__init__(position) | 62 | super().__init__(position) | ||
63 | self._initiative = initiative | 63 | self._initiative = initiative | ||
64 | 64 | ||||
65 | def get_initiative(self): | 65 | def get_initiative(self): | ||
66 | """Return the Initiative of the Kid.""" | 66 | """Return the Initiative of the Kid.""" | ||
67 | return self._initiative | 67 | return self._initiative | ||
68 | 68 | ||||
69 | def add_candy(self, candy: Candy or None): | 69 | def add_candy(self, candy: Candy or None): | ||
70 | """Add a Candy to the Basket.""" | 70 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | 71 | if not candy: | ||
72 | return | 72 | return | ||
73 | 73 | ||||
74 | self._basket.append(candy) | 74 | self._basket.append(candy) | ||
75 | 75 | ||||
76 | def is_critical(self): | 76 | def is_critical(self): | ||
77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
79 | 79 | ||||
80 | def __repr__(self): | 80 | def __repr__(self): | ||
81 | return f'{super().__repr__()} : {self._initiative}' | 81 | return f'{super().__repr__()} : {self._initiative}' | ||
82 | 82 | ||||
83 | 83 | ||||
84 | class Host(Person): | 84 | class Host(Person): | ||
85 | """A Class that represents a Host.""" | 85 | """A Class that represents a Host.""" | ||
86 | 86 | ||||
87 | def __init__(self, position: tuple, candies: list): | 87 | def __init__(self, position: tuple, candies: list): | ||
88 | super().__init__(position) | 88 | super().__init__(position) | ||
89 | self._basket = candies[:] | 89 | self._basket = candies[:] | ||
90 | 90 | ||||
91 | def remove_candy(self, candy_choosing_function): | 91 | def remove_candy(self, candy_choosing_function): | ||
92 | """Select a Candy from the Basket based on the passed in Function.""" | 92 | """Select a Candy from the Basket based on the passed in Function.""" | ||
93 | if not self._basket: | 93 | if not self._basket: | ||
94 | return None | 94 | return None | ||
95 | 95 | ||||
96 | chosen_candy = candy_choosing_function(self._basket) | 96 | chosen_candy = candy_choosing_function(self._basket) | ||
97 | self._basket.remove(chosen_candy) | 97 | self._basket.remove(chosen_candy) | ||
98 | return chosen_candy or None | 98 | return chosen_candy or None | ||
99 | 99 | ||||
100 | 100 | ||||
101 | class FluxCapacitor: | 101 | class FluxCapacitor: | ||
102 | """Class that represents a simulation of a Halloween night.""" | 102 | """Class that represents a simulation of a Halloween night.""" | ||
103 | 103 | ||||
104 | def __init__(self, participants: set): | 104 | def __init__(self, participants: set): | ||
105 | self._kids = [] | 105 | self._kids = [] | ||
106 | self._hosts = [] | 106 | self._hosts = [] | ||
107 | self.__fill_participants(participants) | 107 | self.__fill_participants(participants) | ||
108 | 108 | ||||
n | 109 | def __fill_participants(self, participants: set): | n | 109 | def _fill_participants(self, participants: set): |
110 | for participant in participants: | 110 | for participant in participants: | ||
111 | if type(participant) is Kid: | 111 | if type(participant) is Kid: | ||
112 | self._kids.append(participant) | 112 | self._kids.append(participant) | ||
113 | else: | 113 | else: | ||
114 | self._hosts.append(participant) | 114 | self._hosts.append(participant) | ||
115 | 115 | ||||
116 | def get_victim(self): | 116 | def get_victim(self): | ||
117 | """Simulate a Halloween night and return the first Kids that are critical.""" | 117 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | 118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
119 | if critical_kids is None: | 119 | if critical_kids is None: | ||
120 | return None | 120 | return None | ||
121 | 121 | ||||
122 | return set(critical_kids) or None | 122 | return set(critical_kids) or None | ||
123 | 123 | ||||
124 | def _simulate_one_iteration_of_trick_or_treat(self): | 124 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
125 | """Simulate one cycle of Kids taking Candy from Hosts. | 125 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
126 | 126 | ||||
127 | Return the Kids that are critical after the Cycle or | 127 | Return the Kids that are critical after the Cycle or | ||
128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
129 | an empty List if there are no critical Kids after the Cycle. | 129 | an empty List if there are no critical Kids after the Cycle. | ||
130 | """ | 130 | """ | ||
131 | 131 | ||||
132 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | 132 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | ||
133 | none_critical_kids_sorted_by_initiative = sorted( | 133 | none_critical_kids_sorted_by_initiative = sorted( | ||
134 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | 134 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | ||
135 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | 135 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | ||
136 | ) | 136 | ) | ||
137 | 137 | ||||
138 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | 138 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | ||
139 | return None | 139 | return None | ||
140 | 140 | ||||
141 | critical_kids = [] | 141 | critical_kids = [] | ||
142 | for kid in none_critical_kids_sorted_by_initiative: | 142 | for kid in none_critical_kids_sorted_by_initiative: | ||
143 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | 143 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | ||
t | t | 144 | kid.set_position(min_dist_host.get_position()) | ||
145 | |||||
144 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 146 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
145 | kid.add_candy(removed_candy) | 147 | kid.add_candy(removed_candy) | ||
146 | 148 | ||||
147 | if kid.is_critical(): | 149 | if kid.is_critical(): | ||
148 | critical_kids.append(kid) | 150 | critical_kids.append(kid) | ||
149 | 151 | ||||
150 | return critical_kids | 152 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | 8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | ||
9 | 9 | ||||
10 | 10 | ||||
11 | class Candy: | 11 | class Candy: | ||
12 | """A Class that represents a Candy.""" | 12 | """A Class that represents a Candy.""" | ||
13 | 13 | ||||
14 | def __init__(self, mass: float, uranium: float): | 14 | def __init__(self, mass: float, uranium: float): | ||
15 | self._mass = mass | 15 | self._mass = mass | ||
16 | self._uranium = uranium | 16 | self._uranium = uranium | ||
17 | 17 | ||||
18 | def get_mass(self): | 18 | def get_mass(self): | ||
19 | """Return the Mass of the Candy.""" | 19 | """Return the Mass of the Candy.""" | ||
20 | return self._mass | 20 | return self._mass | ||
21 | 21 | ||||
22 | def get_uranium_quantity(self): | 22 | def get_uranium_quantity(self): | ||
23 | """Return the total Amount of Uranium in the Candy.""" | 23 | """Return the total Amount of Uranium in the Candy.""" | ||
24 | return self._mass * self._uranium | 24 | return self._mass * self._uranium | ||
25 | 25 | ||||
26 | 26 | ||||
27 | class Person: | 27 | class Person: | ||
28 | """A Class that Represents a Person.""" | 28 | """A Class that Represents a Person.""" | ||
29 | 29 | ||||
30 | def __init__(self, position: tuple): | 30 | def __init__(self, position: tuple): | ||
31 | self._position = None | 31 | self._position = None | ||
32 | self.set_position(position) | 32 | self.set_position(position) | ||
33 | self._basket = [] | 33 | self._basket = [] | ||
34 | 34 | ||||
35 | def get_position(self): | 35 | def get_position(self): | ||
36 | """Return the Position of the Person.""" | 36 | """Return the Position of the Person.""" | ||
37 | return self._position | 37 | return self._position | ||
38 | 38 | ||||
39 | def set_position(self, position: tuple): | 39 | def set_position(self, position: tuple): | ||
40 | """Change the Position of the Person.""" | 40 | """Change the Position of the Person.""" | ||
41 | self._position = position | 41 | self._position = position | ||
42 | 42 | ||||
43 | def get_distance_to_person(self, person): | 43 | def get_distance_to_person(self, person): | ||
44 | """Return the Distance from the current Person to the passed in Person.""" | 44 | """Return the Distance from the current Person to the passed in Person.""" | ||
45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
47 | 47 | ||||
48 | def is_basket_empty(self): | 48 | def is_basket_empty(self): | ||
49 | """Return true if the Basket is empty.""" | 49 | """Return true if the Basket is empty.""" | ||
50 | return not self._basket | 50 | return not self._basket | ||
51 | 51 | ||||
52 | def __repr__(self): | 52 | def __repr__(self): | ||
53 | return f'{self._position}' | 53 | return f'{self._position}' | ||
54 | 54 | ||||
55 | 55 | ||||
56 | class Kid(Person): | 56 | class Kid(Person): | ||
57 | """A Class that represents a Kid.""" | 57 | """A Class that represents a Kid.""" | ||
58 | 58 | ||||
59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
60 | 60 | ||||
61 | def __init__(self, position: tuple, initiative: int): | 61 | def __init__(self, position: tuple, initiative: int): | ||
62 | super().__init__(position) | 62 | super().__init__(position) | ||
63 | self._initiative = initiative | 63 | self._initiative = initiative | ||
64 | 64 | ||||
65 | def get_initiative(self): | 65 | def get_initiative(self): | ||
66 | """Return the Initiative of the Kid.""" | 66 | """Return the Initiative of the Kid.""" | ||
67 | return self._initiative | 67 | return self._initiative | ||
68 | 68 | ||||
69 | def add_candy(self, candy: Candy or None): | 69 | def add_candy(self, candy: Candy or None): | ||
70 | """Add a Candy to the Basket.""" | 70 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | 71 | if not candy: | ||
72 | return | 72 | return | ||
73 | 73 | ||||
74 | self._basket.append(candy) | 74 | self._basket.append(candy) | ||
75 | 75 | ||||
76 | def is_critical(self): | 76 | def is_critical(self): | ||
77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
79 | 79 | ||||
80 | def __repr__(self): | 80 | def __repr__(self): | ||
81 | return f'{super().__repr__()} : {self._initiative}' | 81 | return f'{super().__repr__()} : {self._initiative}' | ||
82 | 82 | ||||
83 | 83 | ||||
84 | class Host(Person): | 84 | class Host(Person): | ||
85 | """A Class that represents a Host.""" | 85 | """A Class that represents a Host.""" | ||
86 | 86 | ||||
87 | def __init__(self, position: tuple, candies: list): | 87 | def __init__(self, position: tuple, candies: list): | ||
88 | super().__init__(position) | 88 | super().__init__(position) | ||
89 | self._basket = candies[:] | 89 | self._basket = candies[:] | ||
90 | 90 | ||||
91 | def remove_candy(self, candy_choosing_function): | 91 | def remove_candy(self, candy_choosing_function): | ||
92 | """Select a Candy from the Basket based on the passed in Function.""" | 92 | """Select a Candy from the Basket based on the passed in Function.""" | ||
93 | if not self._basket: | 93 | if not self._basket: | ||
94 | return None | 94 | return None | ||
95 | 95 | ||||
96 | chosen_candy = candy_choosing_function(self._basket) | 96 | chosen_candy = candy_choosing_function(self._basket) | ||
97 | self._basket.remove(chosen_candy) | 97 | self._basket.remove(chosen_candy) | ||
98 | return chosen_candy or None | 98 | return chosen_candy or None | ||
99 | 99 | ||||
100 | 100 | ||||
101 | class FluxCapacitor: | 101 | class FluxCapacitor: | ||
102 | """Class that represents a simulation of a Halloween night.""" | 102 | """Class that represents a simulation of a Halloween night.""" | ||
103 | 103 | ||||
104 | def __init__(self, participants: set): | 104 | def __init__(self, participants: set): | ||
105 | self._kids = [] | 105 | self._kids = [] | ||
106 | self._hosts = [] | 106 | self._hosts = [] | ||
107 | self.__fill_participants(participants) | 107 | self.__fill_participants(participants) | ||
108 | 108 | ||||
109 | def __fill_participants(self, participants: set): | 109 | def __fill_participants(self, participants: set): | ||
110 | for participant in participants: | 110 | for participant in participants: | ||
111 | if type(participant) is Kid: | 111 | if type(participant) is Kid: | ||
112 | self._kids.append(participant) | 112 | self._kids.append(participant) | ||
113 | else: | 113 | else: | ||
114 | self._hosts.append(participant) | 114 | self._hosts.append(participant) | ||
115 | 115 | ||||
116 | def get_victim(self): | 116 | def get_victim(self): | ||
117 | """Simulate a Halloween night and return the first Kids that are critical.""" | 117 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | 118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
119 | if critical_kids is None: | 119 | if critical_kids is None: | ||
120 | return None | 120 | return None | ||
121 | 121 | ||||
122 | return set(critical_kids) or None | 122 | return set(critical_kids) or None | ||
123 | 123 | ||||
124 | def _simulate_one_iteration_of_trick_or_treat(self): | 124 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
125 | """Simulate one cycle of Kids taking Candy from Hosts. | 125 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
126 | 126 | ||||
127 | Return the Kids that are critical after the Cycle or | 127 | Return the Kids that are critical after the Cycle or | ||
128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
129 | an empty List if there are no critical Kids after the Cycle. | 129 | an empty List if there are no critical Kids after the Cycle. | ||
130 | """ | 130 | """ | ||
131 | 131 | ||||
132 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | 132 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | ||
n | 133 | none_critical_kids_sorted_by_initiative = list(filter(lambda curr_kid: not curr_kid.is_critical(), self._kids)) | n | 133 | none_critical_kids_sorted_by_initiative = sorted( |
134 | filter(lambda curr_kid: not curr_kid.is_critical(), self._kids), | ||||
135 | key=lambda curr_kid: curr_kid.get_initiative(), reverse=True | ||||
136 | ) | ||||
134 | 137 | ||||
135 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | 138 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | ||
136 | return None | 139 | return None | ||
n | 137 | n | |||
138 | none_critical_kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||||
139 | 140 | ||||
140 | critical_kids = [] | 141 | critical_kids = [] | ||
141 | for kid in none_critical_kids_sorted_by_initiative: | 142 | for kid in none_critical_kids_sorted_by_initiative: | ||
142 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | 143 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | ||
143 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 144 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
t | 144 | t | |||
145 | kid.add_candy(removed_candy) | 145 | kid.add_candy(removed_candy) | ||
146 | 146 | ||||
147 | if kid.is_critical(): | 147 | if kid.is_critical(): | ||
148 | critical_kids.append(kid) | 148 | critical_kids.append(kid) | ||
149 | 149 | ||||
150 | return critical_kids | 150 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | 8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | ||
9 | 9 | ||||
10 | 10 | ||||
11 | class Candy: | 11 | class Candy: | ||
12 | """A Class that represents a Candy.""" | 12 | """A Class that represents a Candy.""" | ||
13 | 13 | ||||
14 | def __init__(self, mass: float, uranium: float): | 14 | def __init__(self, mass: float, uranium: float): | ||
15 | self._mass = mass | 15 | self._mass = mass | ||
16 | self._uranium = uranium | 16 | self._uranium = uranium | ||
17 | 17 | ||||
18 | def get_mass(self): | 18 | def get_mass(self): | ||
19 | """Return the Mass of the Candy.""" | 19 | """Return the Mass of the Candy.""" | ||
20 | return self._mass | 20 | return self._mass | ||
21 | 21 | ||||
22 | def get_uranium_quantity(self): | 22 | def get_uranium_quantity(self): | ||
23 | """Return the total Amount of Uranium in the Candy.""" | 23 | """Return the total Amount of Uranium in the Candy.""" | ||
24 | return self._mass * self._uranium | 24 | return self._mass * self._uranium | ||
25 | 25 | ||||
26 | 26 | ||||
27 | class Person: | 27 | class Person: | ||
28 | """A Class that Represents a Person.""" | 28 | """A Class that Represents a Person.""" | ||
29 | 29 | ||||
30 | def __init__(self, position: tuple): | 30 | def __init__(self, position: tuple): | ||
31 | self._position = None | 31 | self._position = None | ||
32 | self.set_position(position) | 32 | self.set_position(position) | ||
33 | self._basket = [] | 33 | self._basket = [] | ||
34 | 34 | ||||
35 | def get_position(self): | 35 | def get_position(self): | ||
36 | """Return the Position of the Person.""" | 36 | """Return the Position of the Person.""" | ||
37 | return self._position | 37 | return self._position | ||
38 | 38 | ||||
39 | def set_position(self, position: tuple): | 39 | def set_position(self, position: tuple): | ||
40 | """Change the Position of the Person.""" | 40 | """Change the Position of the Person.""" | ||
41 | self._position = position | 41 | self._position = position | ||
42 | 42 | ||||
43 | def get_distance_to_person(self, person): | 43 | def get_distance_to_person(self, person): | ||
44 | """Return the Distance from the current Person to the passed in Person.""" | 44 | """Return the Distance from the current Person to the passed in Person.""" | ||
45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
47 | 47 | ||||
48 | def is_basket_empty(self): | 48 | def is_basket_empty(self): | ||
49 | """Return true if the Basket is empty.""" | 49 | """Return true if the Basket is empty.""" | ||
50 | return not self._basket | 50 | return not self._basket | ||
51 | 51 | ||||
52 | def __repr__(self): | 52 | def __repr__(self): | ||
53 | return f'{self._position}' | 53 | return f'{self._position}' | ||
54 | 54 | ||||
55 | 55 | ||||
56 | class Kid(Person): | 56 | class Kid(Person): | ||
57 | """A Class that represents a Kid.""" | 57 | """A Class that represents a Kid.""" | ||
58 | 58 | ||||
59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
60 | 60 | ||||
61 | def __init__(self, position: tuple, initiative: int): | 61 | def __init__(self, position: tuple, initiative: int): | ||
62 | super().__init__(position) | 62 | super().__init__(position) | ||
63 | self._initiative = initiative | 63 | self._initiative = initiative | ||
64 | 64 | ||||
65 | def get_initiative(self): | 65 | def get_initiative(self): | ||
66 | """Return the Initiative of the Kid.""" | 66 | """Return the Initiative of the Kid.""" | ||
67 | return self._initiative | 67 | return self._initiative | ||
68 | 68 | ||||
69 | def add_candy(self, candy: Candy or None): | 69 | def add_candy(self, candy: Candy or None): | ||
70 | """Add a Candy to the Basket.""" | 70 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | 71 | if not candy: | ||
72 | return | 72 | return | ||
73 | 73 | ||||
74 | self._basket.append(candy) | 74 | self._basket.append(candy) | ||
75 | 75 | ||||
76 | def is_critical(self): | 76 | def is_critical(self): | ||
77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
79 | 79 | ||||
80 | def __repr__(self): | 80 | def __repr__(self): | ||
81 | return f'{super().__repr__()} : {self._initiative}' | 81 | return f'{super().__repr__()} : {self._initiative}' | ||
82 | 82 | ||||
83 | 83 | ||||
84 | class Host(Person): | 84 | class Host(Person): | ||
85 | """A Class that represents a Host.""" | 85 | """A Class that represents a Host.""" | ||
86 | 86 | ||||
87 | def __init__(self, position: tuple, candies: list): | 87 | def __init__(self, position: tuple, candies: list): | ||
88 | super().__init__(position) | 88 | super().__init__(position) | ||
89 | self._basket = candies[:] | 89 | self._basket = candies[:] | ||
90 | 90 | ||||
91 | def remove_candy(self, candy_choosing_function): | 91 | def remove_candy(self, candy_choosing_function): | ||
92 | """Select a Candy from the Basket based on the passed in Function.""" | 92 | """Select a Candy from the Basket based on the passed in Function.""" | ||
93 | if not self._basket: | 93 | if not self._basket: | ||
94 | return None | 94 | return None | ||
95 | 95 | ||||
96 | chosen_candy = candy_choosing_function(self._basket) | 96 | chosen_candy = candy_choosing_function(self._basket) | ||
97 | self._basket.remove(chosen_candy) | 97 | self._basket.remove(chosen_candy) | ||
98 | return chosen_candy or None | 98 | return chosen_candy or None | ||
99 | 99 | ||||
100 | 100 | ||||
101 | class FluxCapacitor: | 101 | class FluxCapacitor: | ||
102 | """Class that represents a simulation of a Halloween night.""" | 102 | """Class that represents a simulation of a Halloween night.""" | ||
103 | 103 | ||||
104 | def __init__(self, participants: set): | 104 | def __init__(self, participants: set): | ||
105 | self._kids = [] | 105 | self._kids = [] | ||
106 | self._hosts = [] | 106 | self._hosts = [] | ||
107 | self.__fill_participants(participants) | 107 | self.__fill_participants(participants) | ||
108 | 108 | ||||
109 | def __fill_participants(self, participants: set): | 109 | def __fill_participants(self, participants: set): | ||
110 | for participant in participants: | 110 | for participant in participants: | ||
111 | if type(participant) is Kid: | 111 | if type(participant) is Kid: | ||
112 | self._kids.append(participant) | 112 | self._kids.append(participant) | ||
113 | else: | 113 | else: | ||
114 | self._hosts.append(participant) | 114 | self._hosts.append(participant) | ||
115 | 115 | ||||
116 | def get_victim(self): | 116 | def get_victim(self): | ||
117 | """Simulate a Halloween night and return the first Kids that are critical.""" | 117 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | 118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
119 | if critical_kids is None: | 119 | if critical_kids is None: | ||
120 | return None | 120 | return None | ||
121 | 121 | ||||
122 | return set(critical_kids) or None | 122 | return set(critical_kids) or None | ||
123 | 123 | ||||
124 | def _simulate_one_iteration_of_trick_or_treat(self): | 124 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
125 | """Simulate one cycle of Kids taking Candy from Hosts. | 125 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
126 | 126 | ||||
127 | Return the Kids that are critical after the Cycle or | 127 | Return the Kids that are critical after the Cycle or | ||
128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
129 | an empty List if there are no critical Kids after the Cycle. | 129 | an empty List if there are no critical Kids after the Cycle. | ||
130 | """ | 130 | """ | ||
131 | 131 | ||||
n | 132 | """Filter out Hosts with no Candies.""" | n | ||
133 | hosts_with_candies = filter(lambda curr_host: curr_host.is_basket_empty(), self._hosts) | 132 | hosts_with_candies = list(filter(lambda curr_host: not curr_host.is_basket_empty(), self._hosts)) | ||
134 | """Filter out critical Kids.""" | ||||
135 | none_critical_kids_sorted_by_initiative = list(filter(lambda curr_kid: not curr_kid.is_critical(), self._kids)) | 133 | none_critical_kids_sorted_by_initiative = list(filter(lambda curr_kid: not curr_kid.is_critical(), self._kids)) | ||
136 | 134 | ||||
n | 137 | """If any are empty, return None. The Simulation is over.""" | n | ||
138 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | 135 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | ||
139 | return None | 136 | return None | ||
140 | 137 | ||||
t | 141 | """Sort the Kids by Initiative.""" | t | ||
142 | none_critical_kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | 138 | none_critical_kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||
143 | 139 | ||||
144 | critical_kids = [] | 140 | critical_kids = [] | ||
145 | for kid in none_critical_kids_sorted_by_initiative: | 141 | for kid in none_critical_kids_sorted_by_initiative: | ||
146 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | 142 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | ||
147 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 143 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
148 | 144 | ||||
149 | kid.add_candy(removed_candy) | 145 | kid.add_candy(removed_candy) | ||
150 | 146 | ||||
151 | if kid.is_critical(): | 147 | if kid.is_critical(): | ||
152 | critical_kids.append(kid) | 148 | critical_kids.append(kid) | ||
153 | 149 | ||||
154 | return critical_kids | 150 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | 8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | ||
9 | 9 | ||||
10 | 10 | ||||
11 | class Candy: | 11 | class Candy: | ||
12 | """A Class that represents a Candy.""" | 12 | """A Class that represents a Candy.""" | ||
13 | 13 | ||||
14 | def __init__(self, mass: float, uranium: float): | 14 | def __init__(self, mass: float, uranium: float): | ||
15 | self._mass = mass | 15 | self._mass = mass | ||
16 | self._uranium = uranium | 16 | self._uranium = uranium | ||
17 | 17 | ||||
18 | def get_mass(self): | 18 | def get_mass(self): | ||
19 | """Return the Mass of the Candy.""" | 19 | """Return the Mass of the Candy.""" | ||
20 | return self._mass | 20 | return self._mass | ||
21 | 21 | ||||
22 | def get_uranium_quantity(self): | 22 | def get_uranium_quantity(self): | ||
23 | """Return the total Amount of Uranium in the Candy.""" | 23 | """Return the total Amount of Uranium in the Candy.""" | ||
24 | return self._mass * self._uranium | 24 | return self._mass * self._uranium | ||
25 | 25 | ||||
26 | 26 | ||||
27 | class Person: | 27 | class Person: | ||
28 | """A Class that Represents a Person.""" | 28 | """A Class that Represents a Person.""" | ||
29 | 29 | ||||
30 | def __init__(self, position: tuple): | 30 | def __init__(self, position: tuple): | ||
31 | self._position = None | 31 | self._position = None | ||
32 | self.set_position(position) | 32 | self.set_position(position) | ||
33 | self._basket = [] | 33 | self._basket = [] | ||
34 | 34 | ||||
35 | def get_position(self): | 35 | def get_position(self): | ||
36 | """Return the Position of the Person.""" | 36 | """Return the Position of the Person.""" | ||
37 | return self._position | 37 | return self._position | ||
38 | 38 | ||||
39 | def set_position(self, position: tuple): | 39 | def set_position(self, position: tuple): | ||
40 | """Change the Position of the Person.""" | 40 | """Change the Position of the Person.""" | ||
41 | self._position = position | 41 | self._position = position | ||
42 | 42 | ||||
43 | def get_distance_to_person(self, person): | 43 | def get_distance_to_person(self, person): | ||
44 | """Return the Distance from the current Person to the passed in Person.""" | 44 | """Return the Distance from the current Person to the passed in Person.""" | ||
45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
47 | 47 | ||||
48 | def is_basket_empty(self): | 48 | def is_basket_empty(self): | ||
49 | """Return true if the Basket is empty.""" | 49 | """Return true if the Basket is empty.""" | ||
50 | return not self._basket | 50 | return not self._basket | ||
51 | 51 | ||||
52 | def __repr__(self): | 52 | def __repr__(self): | ||
53 | return f'{self._position}' | 53 | return f'{self._position}' | ||
54 | 54 | ||||
55 | 55 | ||||
56 | class Kid(Person): | 56 | class Kid(Person): | ||
57 | """A Class that represents a Kid.""" | 57 | """A Class that represents a Kid.""" | ||
58 | 58 | ||||
59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
60 | 60 | ||||
61 | def __init__(self, position: tuple, initiative: int): | 61 | def __init__(self, position: tuple, initiative: int): | ||
62 | super().__init__(position) | 62 | super().__init__(position) | ||
63 | self._initiative = initiative | 63 | self._initiative = initiative | ||
64 | 64 | ||||
65 | def get_initiative(self): | 65 | def get_initiative(self): | ||
66 | """Return the Initiative of the Kid.""" | 66 | """Return the Initiative of the Kid.""" | ||
67 | return self._initiative | 67 | return self._initiative | ||
68 | 68 | ||||
69 | def add_candy(self, candy: Candy or None): | 69 | def add_candy(self, candy: Candy or None): | ||
70 | """Add a Candy to the Basket.""" | 70 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | 71 | if not candy: | ||
72 | return | 72 | return | ||
73 | 73 | ||||
74 | self._basket.append(candy) | 74 | self._basket.append(candy) | ||
75 | 75 | ||||
76 | def is_critical(self): | 76 | def is_critical(self): | ||
77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
79 | 79 | ||||
80 | def __repr__(self): | 80 | def __repr__(self): | ||
81 | return f'{super().__repr__()} : {self._initiative}' | 81 | return f'{super().__repr__()} : {self._initiative}' | ||
82 | 82 | ||||
83 | 83 | ||||
84 | class Host(Person): | 84 | class Host(Person): | ||
85 | """A Class that represents a Host.""" | 85 | """A Class that represents a Host.""" | ||
86 | 86 | ||||
87 | def __init__(self, position: tuple, candies: list): | 87 | def __init__(self, position: tuple, candies: list): | ||
88 | super().__init__(position) | 88 | super().__init__(position) | ||
89 | self._basket = candies[:] | 89 | self._basket = candies[:] | ||
90 | 90 | ||||
91 | def remove_candy(self, candy_choosing_function): | 91 | def remove_candy(self, candy_choosing_function): | ||
92 | """Select a Candy from the Basket based on the passed in Function.""" | 92 | """Select a Candy from the Basket based on the passed in Function.""" | ||
93 | if not self._basket: | 93 | if not self._basket: | ||
94 | return None | 94 | return None | ||
95 | 95 | ||||
96 | chosen_candy = candy_choosing_function(self._basket) | 96 | chosen_candy = candy_choosing_function(self._basket) | ||
97 | self._basket.remove(chosen_candy) | 97 | self._basket.remove(chosen_candy) | ||
98 | return chosen_candy or None | 98 | return chosen_candy or None | ||
99 | 99 | ||||
100 | 100 | ||||
101 | class FluxCapacitor: | 101 | class FluxCapacitor: | ||
102 | """Class that represents a simulation of a Halloween night.""" | 102 | """Class that represents a simulation of a Halloween night.""" | ||
103 | 103 | ||||
104 | def __init__(self, participants: set): | 104 | def __init__(self, participants: set): | ||
105 | self._kids = [] | 105 | self._kids = [] | ||
106 | self._hosts = [] | 106 | self._hosts = [] | ||
107 | self.__fill_participants(participants) | 107 | self.__fill_participants(participants) | ||
108 | 108 | ||||
109 | def __fill_participants(self, participants: set): | 109 | def __fill_participants(self, participants: set): | ||
110 | for participant in participants: | 110 | for participant in participants: | ||
111 | if type(participant) is Kid: | 111 | if type(participant) is Kid: | ||
112 | self._kids.append(participant) | 112 | self._kids.append(participant) | ||
113 | else: | 113 | else: | ||
114 | self._hosts.append(participant) | 114 | self._hosts.append(participant) | ||
115 | 115 | ||||
116 | def get_victim(self): | 116 | def get_victim(self): | ||
117 | """Simulate a Halloween night and return the first Kids that are critical.""" | 117 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
n | 118 | while True: | n | ||
119 | critical_kids = self._simulate_one_iteration_of_trick_or_treat() | 118 | while not (critical_kids := self._simulate_one_iteration_of_trick_or_treat()): | ||
120 | |||||
121 | if critical_kids is None: | 119 | if critical_kids is None: | ||
122 | return None | 120 | return None | ||
t | 123 | elif critical_kids: | t | ||
124 | break | ||||
125 | 121 | ||||
126 | return set(critical_kids) or None | 122 | return set(critical_kids) or None | ||
127 | 123 | ||||
128 | def _simulate_one_iteration_of_trick_or_treat(self): | 124 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
129 | """Simulate one cycle of Kids taking Candy from Hosts. | 125 | """Simulate one cycle of Kids taking Candy from Hosts. | ||
130 | 126 | ||||
131 | Return the Kids that are critical after the Cycle or | 127 | Return the Kids that are critical after the Cycle or | ||
132 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | 128 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||
133 | an empty List if there are no critical Kids after the Cycle. | 129 | an empty List if there are no critical Kids after the Cycle. | ||
134 | """ | 130 | """ | ||
135 | 131 | ||||
136 | """Filter out Hosts with no Candies.""" | 132 | """Filter out Hosts with no Candies.""" | ||
137 | hosts_with_candies = filter(lambda curr_host: curr_host.is_basket_empty(), self._hosts) | 133 | hosts_with_candies = filter(lambda curr_host: curr_host.is_basket_empty(), self._hosts) | ||
138 | """Filter out critical Kids.""" | 134 | """Filter out critical Kids.""" | ||
139 | none_critical_kids_sorted_by_initiative = list(filter(lambda curr_kid: not curr_kid.is_critical(), self._kids)) | 135 | none_critical_kids_sorted_by_initiative = list(filter(lambda curr_kid: not curr_kid.is_critical(), self._kids)) | ||
140 | 136 | ||||
141 | """If any are empty, return None. The Simulation is over.""" | 137 | """If any are empty, return None. The Simulation is over.""" | ||
142 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | 138 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | ||
143 | return None | 139 | return None | ||
144 | 140 | ||||
145 | """Sort the Kids by Initiative.""" | 141 | """Sort the Kids by Initiative.""" | ||
146 | none_critical_kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | 142 | none_critical_kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||
147 | 143 | ||||
148 | critical_kids = [] | 144 | critical_kids = [] | ||
149 | for kid in none_critical_kids_sorted_by_initiative: | 145 | for kid in none_critical_kids_sorted_by_initiative: | ||
150 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | 146 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | ||
151 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 147 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
152 | 148 | ||||
153 | kid.add_candy(removed_candy) | 149 | kid.add_candy(removed_candy) | ||
154 | 150 | ||||
155 | if kid.is_critical(): | 151 | if kid.is_critical(): | ||
156 | critical_kids.append(kid) | 152 | critical_kids.append(kid) | ||
157 | 153 | ||||
158 | return critical_kids | 154 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | 8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | ||
9 | 9 | ||||
10 | 10 | ||||
11 | class Candy: | 11 | class Candy: | ||
12 | """A Class that represents a Candy.""" | 12 | """A Class that represents a Candy.""" | ||
13 | 13 | ||||
14 | def __init__(self, mass: float, uranium: float): | 14 | def __init__(self, mass: float, uranium: float): | ||
15 | self._mass = mass | 15 | self._mass = mass | ||
16 | self._uranium = uranium | 16 | self._uranium = uranium | ||
17 | 17 | ||||
18 | def get_mass(self): | 18 | def get_mass(self): | ||
19 | """Return the Mass of the Candy.""" | 19 | """Return the Mass of the Candy.""" | ||
20 | return self._mass | 20 | return self._mass | ||
21 | 21 | ||||
22 | def get_uranium_quantity(self): | 22 | def get_uranium_quantity(self): | ||
23 | """Return the total Amount of Uranium in the Candy.""" | 23 | """Return the total Amount of Uranium in the Candy.""" | ||
24 | return self._mass * self._uranium | 24 | return self._mass * self._uranium | ||
25 | 25 | ||||
26 | 26 | ||||
27 | class Person: | 27 | class Person: | ||
28 | """A Class that Represents a Person.""" | 28 | """A Class that Represents a Person.""" | ||
29 | 29 | ||||
30 | def __init__(self, position: tuple): | 30 | def __init__(self, position: tuple): | ||
31 | self._position = None | 31 | self._position = None | ||
32 | self.set_position(position) | 32 | self.set_position(position) | ||
33 | self._basket = [] | 33 | self._basket = [] | ||
34 | 34 | ||||
35 | def get_position(self): | 35 | def get_position(self): | ||
36 | """Return the Position of the Person.""" | 36 | """Return the Position of the Person.""" | ||
37 | return self._position | 37 | return self._position | ||
38 | 38 | ||||
39 | def set_position(self, position: tuple): | 39 | def set_position(self, position: tuple): | ||
40 | """Change the Position of the Person.""" | 40 | """Change the Position of the Person.""" | ||
41 | self._position = position | 41 | self._position = position | ||
42 | 42 | ||||
43 | def get_distance_to_person(self, person): | 43 | def get_distance_to_person(self, person): | ||
44 | """Return the Distance from the current Person to the passed in Person.""" | 44 | """Return the Distance from the current Person to the passed in Person.""" | ||
45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
47 | 47 | ||||
48 | def is_basket_empty(self): | 48 | def is_basket_empty(self): | ||
49 | """Return true if the Basket is empty.""" | 49 | """Return true if the Basket is empty.""" | ||
50 | return not self._basket | 50 | return not self._basket | ||
51 | 51 | ||||
52 | def __repr__(self): | 52 | def __repr__(self): | ||
53 | return f'{self._position}' | 53 | return f'{self._position}' | ||
54 | 54 | ||||
55 | 55 | ||||
56 | class Kid(Person): | 56 | class Kid(Person): | ||
57 | """A Class that represents a Kid.""" | 57 | """A Class that represents a Kid.""" | ||
58 | 58 | ||||
59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
60 | 60 | ||||
61 | def __init__(self, position: tuple, initiative: int): | 61 | def __init__(self, position: tuple, initiative: int): | ||
62 | super().__init__(position) | 62 | super().__init__(position) | ||
63 | self._initiative = initiative | 63 | self._initiative = initiative | ||
64 | 64 | ||||
65 | def get_initiative(self): | 65 | def get_initiative(self): | ||
66 | """Return the Initiative of the Kid.""" | 66 | """Return the Initiative of the Kid.""" | ||
67 | return self._initiative | 67 | return self._initiative | ||
68 | 68 | ||||
69 | def add_candy(self, candy: Candy or None): | 69 | def add_candy(self, candy: Candy or None): | ||
70 | """Add a Candy to the Basket.""" | 70 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | 71 | if not candy: | ||
72 | return | 72 | return | ||
73 | 73 | ||||
74 | self._basket.append(candy) | 74 | self._basket.append(candy) | ||
75 | 75 | ||||
76 | def is_critical(self): | 76 | def is_critical(self): | ||
77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
79 | 79 | ||||
80 | def __repr__(self): | 80 | def __repr__(self): | ||
81 | return f'{super().__repr__()} : {self._initiative}' | 81 | return f'{super().__repr__()} : {self._initiative}' | ||
82 | 82 | ||||
83 | 83 | ||||
84 | class Host(Person): | 84 | class Host(Person): | ||
85 | """A Class that represents a Host.""" | 85 | """A Class that represents a Host.""" | ||
86 | 86 | ||||
87 | def __init__(self, position: tuple, candies: list): | 87 | def __init__(self, position: tuple, candies: list): | ||
88 | super().__init__(position) | 88 | super().__init__(position) | ||
89 | self._basket = candies[:] | 89 | self._basket = candies[:] | ||
90 | 90 | ||||
91 | def remove_candy(self, candy_choosing_function): | 91 | def remove_candy(self, candy_choosing_function): | ||
92 | """Select a Candy from the Basket based on the passed in Function.""" | 92 | """Select a Candy from the Basket based on the passed in Function.""" | ||
93 | if not self._basket: | 93 | if not self._basket: | ||
94 | return None | 94 | return None | ||
95 | 95 | ||||
96 | chosen_candy = candy_choosing_function(self._basket) | 96 | chosen_candy = candy_choosing_function(self._basket) | ||
97 | self._basket.remove(chosen_candy) | 97 | self._basket.remove(chosen_candy) | ||
98 | return chosen_candy or None | 98 | return chosen_candy or None | ||
99 | 99 | ||||
100 | 100 | ||||
101 | class FluxCapacitor: | 101 | class FluxCapacitor: | ||
102 | """Class that represents a simulation of a Halloween night.""" | 102 | """Class that represents a simulation of a Halloween night.""" | ||
103 | 103 | ||||
104 | def __init__(self, participants: set): | 104 | def __init__(self, participants: set): | ||
105 | self._kids = [] | 105 | self._kids = [] | ||
106 | self._hosts = [] | 106 | self._hosts = [] | ||
107 | self.__fill_participants(participants) | 107 | self.__fill_participants(participants) | ||
108 | 108 | ||||
109 | def __fill_participants(self, participants: set): | 109 | def __fill_participants(self, participants: set): | ||
110 | for participant in participants: | 110 | for participant in participants: | ||
111 | if type(participant) is Kid: | 111 | if type(participant) is Kid: | ||
112 | self._kids.append(participant) | 112 | self._kids.append(participant) | ||
113 | else: | 113 | else: | ||
114 | self._hosts.append(participant) | 114 | self._hosts.append(participant) | ||
115 | 115 | ||||
116 | def get_victim(self): | 116 | def get_victim(self): | ||
117 | """Simulate a Halloween night and return the first Kids that are critical.""" | 117 | """Simulate a Halloween night and return the first Kids that are critical.""" | ||
118 | while True: | 118 | while True: | ||
119 | critical_kids = self._simulate_one_iteration_of_trick_or_treat() | 119 | critical_kids = self._simulate_one_iteration_of_trick_or_treat() | ||
120 | 120 | ||||
121 | if critical_kids is None: | 121 | if critical_kids is None: | ||
122 | return None | 122 | return None | ||
123 | elif critical_kids: | 123 | elif critical_kids: | ||
124 | break | 124 | break | ||
125 | 125 | ||||
126 | return set(critical_kids) or None | 126 | return set(critical_kids) or None | ||
127 | 127 | ||||
128 | def _simulate_one_iteration_of_trick_or_treat(self): | 128 | def _simulate_one_iteration_of_trick_or_treat(self): | ||
t | 129 | """Simulate one cycle of Kids taking Candy from Hosts and return the Critical Kids after the cycle.""" | t | 129 | """Simulate one cycle of Kids taking Candy from Hosts. |
130 | |||||
131 | Return the Kids that are critical after the Cycle or | ||||
132 | None if the there are no more Kids or Hosts with Candy (The Simulation is over) or | ||||
133 | an empty List if there are no critical Kids after the Cycle. | ||||
134 | """ | ||||
130 | 135 | ||||
131 | """Filter out Hosts with no Candies.""" | 136 | """Filter out Hosts with no Candies.""" | ||
132 | hosts_with_candies = filter(lambda curr_host: curr_host.is_basket_empty(), self._hosts) | 137 | hosts_with_candies = filter(lambda curr_host: curr_host.is_basket_empty(), self._hosts) | ||
133 | """Filter out critical Kids.""" | 138 | """Filter out critical Kids.""" | ||
134 | none_critical_kids_sorted_by_initiative = list(filter(lambda curr_kid: not curr_kid.is_critical(), self._kids)) | 139 | none_critical_kids_sorted_by_initiative = list(filter(lambda curr_kid: not curr_kid.is_critical(), self._kids)) | ||
135 | 140 | ||||
136 | """If any are empty, return None. The Simulation is over.""" | 141 | """If any are empty, return None. The Simulation is over.""" | ||
137 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | 142 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | ||
138 | return None | 143 | return None | ||
139 | 144 | ||||
140 | """Sort the Kids by Initiative.""" | 145 | """Sort the Kids by Initiative.""" | ||
141 | none_critical_kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | 146 | none_critical_kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||
142 | 147 | ||||
143 | critical_kids = [] | 148 | critical_kids = [] | ||
144 | for kid in none_critical_kids_sorted_by_initiative: | 149 | for kid in none_critical_kids_sorted_by_initiative: | ||
145 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | 150 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | ||
146 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 151 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
147 | 152 | ||||
148 | kid.add_candy(removed_candy) | 153 | kid.add_candy(removed_candy) | ||
149 | 154 | ||||
150 | if kid.is_critical(): | 155 | if kid.is_critical(): | ||
151 | critical_kids.append(kid) | 156 | critical_kids.append(kid) | ||
152 | 157 | ||||
153 | return critical_kids | 158 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass(candies: list): | f | 1 | def max_candy_by_mass(candies: list): |
2 | """Return the Candy with the most Mass.""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | def get_host_with_min_distance(kid, hosts): | 6 | def get_host_with_min_distance(kid, hosts): | ||
7 | """Return the Host with the least Distance to the Kid.""" | 7 | """Return the Host with the least Distance to the Kid.""" | ||
8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | 8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | ||
9 | 9 | ||||
10 | 10 | ||||
11 | class Candy: | 11 | class Candy: | ||
12 | """A Class that represents a Candy.""" | 12 | """A Class that represents a Candy.""" | ||
13 | 13 | ||||
14 | def __init__(self, mass: float, uranium: float): | 14 | def __init__(self, mass: float, uranium: float): | ||
15 | self._mass = mass | 15 | self._mass = mass | ||
16 | self._uranium = uranium | 16 | self._uranium = uranium | ||
17 | 17 | ||||
18 | def get_mass(self): | 18 | def get_mass(self): | ||
19 | """Return the Mass of the Candy.""" | 19 | """Return the Mass of the Candy.""" | ||
20 | return self._mass | 20 | return self._mass | ||
21 | 21 | ||||
22 | def get_uranium_quantity(self): | 22 | def get_uranium_quantity(self): | ||
23 | """Return the total Amount of Uranium in the Candy.""" | 23 | """Return the total Amount of Uranium in the Candy.""" | ||
24 | return self._mass * self._uranium | 24 | return self._mass * self._uranium | ||
25 | 25 | ||||
26 | 26 | ||||
27 | class Person: | 27 | class Person: | ||
28 | """A Class that Represents a Person.""" | 28 | """A Class that Represents a Person.""" | ||
29 | 29 | ||||
30 | def __init__(self, position: tuple): | 30 | def __init__(self, position: tuple): | ||
31 | self._position = None | 31 | self._position = None | ||
32 | self.set_position(position) | 32 | self.set_position(position) | ||
33 | self._basket = [] | 33 | self._basket = [] | ||
34 | 34 | ||||
35 | def get_position(self): | 35 | def get_position(self): | ||
36 | """Return the Position of the Person.""" | 36 | """Return the Position of the Person.""" | ||
37 | return self._position | 37 | return self._position | ||
38 | 38 | ||||
39 | def set_position(self, position: tuple): | 39 | def set_position(self, position: tuple): | ||
40 | """Change the Position of the Person.""" | 40 | """Change the Position of the Person.""" | ||
41 | self._position = position | 41 | self._position = position | ||
42 | 42 | ||||
43 | def get_distance_to_person(self, person): | 43 | def get_distance_to_person(self, person): | ||
44 | """Return the Distance from the current Person to the passed in Person.""" | 44 | """Return the Distance from the current Person to the passed in Person.""" | ||
45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
47 | 47 | ||||
n | 48 | def get_basket(self): | n | 48 | def is_basket_empty(self): |
49 | """Return the Basket of the Person.""" | 49 | """Return true if the Basket is empty.""" | ||
50 | return self._basket | 50 | return not self._basket | ||
51 | 51 | ||||
52 | def __repr__(self): | 52 | def __repr__(self): | ||
53 | return f'{self._position}' | 53 | return f'{self._position}' | ||
54 | 54 | ||||
55 | 55 | ||||
56 | class Kid(Person): | 56 | class Kid(Person): | ||
57 | """A Class that represents a Kid.""" | 57 | """A Class that represents a Kid.""" | ||
58 | 58 | ||||
59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
60 | 60 | ||||
61 | def __init__(self, position: tuple, initiative: int): | 61 | def __init__(self, position: tuple, initiative: int): | ||
62 | super().__init__(position) | 62 | super().__init__(position) | ||
63 | self._initiative = initiative | 63 | self._initiative = initiative | ||
64 | 64 | ||||
65 | def get_initiative(self): | 65 | def get_initiative(self): | ||
66 | """Return the Initiative of the Kid.""" | 66 | """Return the Initiative of the Kid.""" | ||
67 | return self._initiative | 67 | return self._initiative | ||
68 | 68 | ||||
69 | def add_candy(self, candy: Candy or None): | 69 | def add_candy(self, candy: Candy or None): | ||
70 | """Add a Candy to the Basket.""" | 70 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | 71 | if not candy: | ||
72 | return | 72 | return | ||
73 | 73 | ||||
74 | self._basket.append(candy) | 74 | self._basket.append(candy) | ||
75 | 75 | ||||
76 | def is_critical(self): | 76 | def is_critical(self): | ||
77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | 77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" | ||
78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
79 | 79 | ||||
80 | def __repr__(self): | 80 | def __repr__(self): | ||
81 | return f'{super().__repr__()} : {self._initiative}' | 81 | return f'{super().__repr__()} : {self._initiative}' | ||
82 | 82 | ||||
83 | 83 | ||||
84 | class Host(Person): | 84 | class Host(Person): | ||
85 | """A Class that represents a Host.""" | 85 | """A Class that represents a Host.""" | ||
86 | 86 | ||||
87 | def __init__(self, position: tuple, candies: list): | 87 | def __init__(self, position: tuple, candies: list): | ||
88 | super().__init__(position) | 88 | super().__init__(position) | ||
89 | self._basket = candies[:] | 89 | self._basket = candies[:] | ||
90 | 90 | ||||
91 | def remove_candy(self, candy_choosing_function): | 91 | def remove_candy(self, candy_choosing_function): | ||
92 | """Select a Candy from the Basket based on the passed in Function.""" | 92 | """Select a Candy from the Basket based on the passed in Function.""" | ||
93 | if not self._basket: | 93 | if not self._basket: | ||
94 | return None | 94 | return None | ||
95 | 95 | ||||
96 | chosen_candy = candy_choosing_function(self._basket) | 96 | chosen_candy = candy_choosing_function(self._basket) | ||
97 | self._basket.remove(chosen_candy) | 97 | self._basket.remove(chosen_candy) | ||
98 | return chosen_candy or None | 98 | return chosen_candy or None | ||
99 | 99 | ||||
100 | 100 | ||||
101 | class FluxCapacitor: | 101 | class FluxCapacitor: | ||
102 | """Class that represents a simulation of a Halloween night.""" | 102 | """Class that represents a simulation of a Halloween night.""" | ||
103 | 103 | ||||
104 | def __init__(self, participants: set): | 104 | def __init__(self, participants: set): | ||
105 | self._kids = [] | 105 | self._kids = [] | ||
106 | self._hosts = [] | 106 | self._hosts = [] | ||
107 | self.__fill_participants(participants) | 107 | self.__fill_participants(participants) | ||
n | 108 | self._all_critical_kids = [] | n | ||
109 | 108 | ||||
110 | def __fill_participants(self, participants: set): | 109 | def __fill_participants(self, participants: set): | ||
111 | for participant in participants: | 110 | for participant in participants: | ||
112 | if type(participant) is Kid: | 111 | if type(participant) is Kid: | ||
113 | self._kids.append(participant) | 112 | self._kids.append(participant) | ||
114 | else: | 113 | else: | ||
115 | self._hosts.append(participant) | 114 | self._hosts.append(participant) | ||
116 | 115 | ||||
117 | def get_victim(self): | 116 | def get_victim(self): | ||
n | 118 | """Simulate a Halloween night and return the Kids who have the most Uranium.""" | n | 117 | """Simulate a Halloween night and return the first Kids that are critical.""" |
119 | hosts_with_candies = filter(lambda x: not not x.get_basket(), self._hosts) | 118 | while True: | ||
119 | critical_kids = self._simulate_one_iteration_of_trick_or_treat() | ||||
120 | 120 | ||||
n | 121 | kids_sorted_by_initiative = self._kids[:] | n | 121 | if critical_kids is None: |
122 | return None | ||||
123 | elif critical_kids: | ||||
124 | break | ||||
125 | |||||
126 | return set(critical_kids) or None | ||||
127 | |||||
128 | def _simulate_one_iteration_of_trick_or_treat(self): | ||||
129 | """Simulate one cycle of Kids taking Candy from Hosts and return the Critical Kids after the cycle.""" | ||||
130 | |||||
131 | """Filter out Hosts with no Candies.""" | ||||
132 | hosts_with_candies = filter(lambda curr_host: curr_host.is_basket_empty(), self._hosts) | ||||
133 | """Filter out critical Kids.""" | ||||
134 | none_critical_kids_sorted_by_initiative = list(filter(lambda curr_kid: not curr_kid.is_critical(), self._kids)) | ||||
135 | |||||
136 | """If any are empty, return None. The Simulation is over.""" | ||||
137 | if not none_critical_kids_sorted_by_initiative or not hosts_with_candies: | ||||
138 | return None | ||||
139 | |||||
140 | """Sort the Kids by Initiative.""" | ||||
122 | kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | 141 | none_critical_kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||
123 | 142 | ||||
124 | critical_kids = [] | 143 | critical_kids = [] | ||
n | 125 | for kid in kids_sorted_by_initiative: | n | 144 | for kid in none_critical_kids_sorted_by_initiative: |
126 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | 145 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | ||
127 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | 146 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
128 | 147 | ||||
129 | kid.add_candy(removed_candy) | 148 | kid.add_candy(removed_candy) | ||
130 | 149 | ||||
131 | if kid.is_critical(): | 150 | if kid.is_critical(): | ||
132 | critical_kids.append(kid) | 151 | critical_kids.append(kid) | ||
133 | 152 | ||||
t | 134 | self._all_critical_kids.extend(critical_kids) | t | ||
135 | |||||
136 | return self._all_critical_kids or None | 153 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
n | 1 | def max_candy_by_mass_lambda(): | n | 1 | def max_candy_by_mass(candies: list): |
2 | """Return a Lambda Function that returns the Candy with the most Mass""" | 2 | """Return the Candy with the most Mass.""" | ||
3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | 3 | return max(candies, key=lambda candy: candy.get_mass()) | ||
4 | |||||
5 | |||||
6 | def get_host_with_min_distance(kid, hosts): | ||||
7 | """Return the Host with the least Distance to the Kid.""" | ||||
8 | return min(hosts, key=lambda host: host.get_distance_to_person(kid)) | ||||
4 | 9 | ||||
5 | 10 | ||||
6 | class Candy: | 11 | class Candy: | ||
n | 7 | """A Class that represents a Candy""" | n | 12 | """A Class that represents a Candy.""" |
8 | 13 | ||||
9 | def __init__(self, mass: float, uranium: float): | 14 | def __init__(self, mass: float, uranium: float): | ||
10 | self._mass = mass | 15 | self._mass = mass | ||
11 | self._uranium = uranium | 16 | self._uranium = uranium | ||
12 | 17 | ||||
13 | def get_mass(self): | 18 | def get_mass(self): | ||
n | 14 | """Return the Mass of the Candy""" | n | 19 | """Return the Mass of the Candy.""" |
15 | return self._mass | 20 | return self._mass | ||
16 | 21 | ||||
17 | def get_uranium_quantity(self): | 22 | def get_uranium_quantity(self): | ||
n | 18 | """Return the total Amount of Uranium in the Candy""" | n | 23 | """Return the total Amount of Uranium in the Candy.""" |
19 | return self._mass * self._uranium | 24 | return self._mass * self._uranium | ||
20 | 25 | ||||
21 | 26 | ||||
22 | class Person: | 27 | class Person: | ||
n | 23 | """A Class that Represents a Person""" | n | 28 | """A Class that Represents a Person.""" |
24 | 29 | ||||
25 | def __init__(self, position: tuple): | 30 | def __init__(self, position: tuple): | ||
26 | self._position = None | 31 | self._position = None | ||
27 | self.set_position(position) | 32 | self.set_position(position) | ||
28 | self._basket = [] | 33 | self._basket = [] | ||
29 | 34 | ||||
30 | def get_position(self): | 35 | def get_position(self): | ||
n | 31 | """Return the Position of the Person""" | n | 36 | """Return the Position of the Person.""" |
32 | return self._position | 37 | return self._position | ||
33 | 38 | ||||
34 | def set_position(self, position: tuple): | 39 | def set_position(self, position: tuple): | ||
n | 35 | """Change the Position of the Person""" | n | 40 | """Change the Position of the Person.""" |
36 | self._position = position | 41 | self._position = position | ||
37 | 42 | ||||
38 | def get_distance_to_person(self, person): | 43 | def get_distance_to_person(self, person): | ||
n | 39 | """Return the Distance from the current Person to the passed in Person""" | n | 44 | """Return the Distance from the current Person to the passed in Person.""" |
40 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 45 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
41 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 46 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
n | n | 47 | |||
48 | def get_basket(self): | ||||
49 | """Return the Basket of the Person.""" | ||||
50 | return self._basket | ||||
42 | 51 | ||||
43 | def __repr__(self): | 52 | def __repr__(self): | ||
44 | return f'{self._position}' | 53 | return f'{self._position}' | ||
45 | 54 | ||||
n | 46 | def __getitem__(self, item): | n | ||
47 | if isinstance(item, Person): | ||||
48 | return self.get_distance_to_person(item) | ||||
49 | |||||
50 | return self._position[item] | ||||
51 | |||||
52 | 55 | ||||
53 | class Kid(Person): | 56 | class Kid(Person): | ||
n | 54 | """A Class that represents a Kid""" | n | 57 | """A Class that represents a Kid.""" |
55 | 58 | ||||
56 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 59 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
57 | 60 | ||||
58 | def __init__(self, position: tuple, initiative: int): | 61 | def __init__(self, position: tuple, initiative: int): | ||
59 | super().__init__(position) | 62 | super().__init__(position) | ||
60 | self._initiative = initiative | 63 | self._initiative = initiative | ||
61 | 64 | ||||
62 | def get_initiative(self): | 65 | def get_initiative(self): | ||
n | 63 | """Return the Initiative of the Kid""" | n | 66 | """Return the Initiative of the Kid.""" |
64 | return self._initiative | 67 | return self._initiative | ||
65 | 68 | ||||
n | 66 | def add_candy(self, candy: Candy): | n | 69 | def add_candy(self, candy: Candy or None): |
67 | """Add a Candy to the Basket""" | 70 | """Add a Candy to the Basket.""" | ||
71 | if not candy: | ||||
72 | return | ||||
73 | |||||
68 | self._basket.append(candy) | 74 | self._basket.append(candy) | ||
69 | 75 | ||||
70 | def is_critical(self): | 76 | def is_critical(self): | ||
n | 71 | """Return true if the Uranium Amount in the Basket is more than 20g""" | n | 77 | """Return true if the Uranium Amount in the Basket is more than 20g.""" |
72 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 78 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
73 | 79 | ||||
74 | def __repr__(self): | 80 | def __repr__(self): | ||
75 | return f'{super().__repr__()} : {self._initiative}' | 81 | return f'{super().__repr__()} : {self._initiative}' | ||
76 | 82 | ||||
77 | 83 | ||||
78 | class Host(Person): | 84 | class Host(Person): | ||
n | 79 | """A Class that represents a Host""" | n | 85 | """A Class that represents a Host.""" |
80 | 86 | ||||
81 | def __init__(self, position: tuple, candies: list): | 87 | def __init__(self, position: tuple, candies: list): | ||
82 | super().__init__(position) | 88 | super().__init__(position) | ||
83 | self._basket = candies[:] | 89 | self._basket = candies[:] | ||
84 | 90 | ||||
85 | def remove_candy(self, candy_choosing_function): | 91 | def remove_candy(self, candy_choosing_function): | ||
n | 86 | """Select a Candy from the Basket based on the passed in Function""" | n | 92 | """Select a Candy from the Basket based on the passed in Function.""" |
87 | if not self._basket: | 93 | if not self._basket: | ||
88 | return None | 94 | return None | ||
89 | 95 | ||||
90 | chosen_candy = candy_choosing_function(self._basket) | 96 | chosen_candy = candy_choosing_function(self._basket) | ||
n | 91 | n | |||
92 | self._basket.remove(chosen_candy) | 97 | self._basket.remove(chosen_candy) | ||
n | 93 | n | |||
94 | return chosen_candy if chosen_candy else None | 98 | return chosen_candy or None | ||
95 | 99 | ||||
96 | 100 | ||||
97 | class FluxCapacitor: | 101 | class FluxCapacitor: | ||
n | 98 | """Class that represents a simulation of a Halloween night""" | n | 102 | """Class that represents a simulation of a Halloween night.""" |
99 | 103 | ||||
100 | def __init__(self, participants: set): | 104 | def __init__(self, participants: set): | ||
101 | self._kids = [] | 105 | self._kids = [] | ||
102 | self._hosts = [] | 106 | self._hosts = [] | ||
103 | self.__fill_participants(participants) | 107 | self.__fill_participants(participants) | ||
n | n | 108 | self._all_critical_kids = [] | ||
104 | 109 | ||||
105 | def __fill_participants(self, participants: set): | 110 | def __fill_participants(self, participants: set): | ||
n | 106 | [ | n | ||
107 | self._kids.append(participant) if type(participant) is Kid | ||||
108 | else self._hosts.append(participant) | ||||
109 | for participant in participants | 111 | for participant in participants: | ||
110 | ] | 112 | if type(participant) is Kid: | ||
113 | self._kids.append(participant) | ||||
114 | else: | ||||
115 | self._hosts.append(participant) | ||||
111 | 116 | ||||
112 | def get_victim(self): | 117 | def get_victim(self): | ||
n | 113 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | n | 118 | """Simulate a Halloween night and return the Kids who have the most Uranium.""" |
114 | sorted_kids = self._kids[:] | 119 | hosts_with_candies = filter(lambda x: not not x.get_basket(), self._hosts) | ||
115 | sorted_hosts = self._hosts[:] | ||||
116 | 120 | ||||
n | n | 121 | kids_sorted_by_initiative = self._kids[:] | ||
117 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | 122 | kids_sorted_by_initiative.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||
118 | 123 | ||||
119 | critical_kids = [] | 124 | critical_kids = [] | ||
n | 120 | for kid in sorted_kids: | n | 125 | for kid in kids_sorted_by_initiative: |
121 | sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | 126 | min_dist_host = get_host_with_min_distance(kid, hosts_with_candies) | ||
122 | for host in sorted_hosts: | ||||
123 | removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | 127 | removed_candy = min_dist_host.remove_candy(max_candy_by_mass) | ||
124 | 128 | ||||
n | 125 | if removed_candy: | n | ||
126 | kid.add_candy(removed_candy) | 129 | kid.add_candy(removed_candy) | ||
127 | 130 | ||||
n | 128 | if kid.is_critical(): | n | 131 | if kid.is_critical(): |
129 | critical_kids.append(kid) | 132 | critical_kids.append(kid) | ||
130 | break | ||||
131 | 133 | ||||
t | 132 | return critical_kids if critical_kids else None | t | 134 | self._all_critical_kids.extend(critical_kids) |
135 | |||||
136 | return self._all_critical_kids or None |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass_lambda(): | f | 1 | def max_candy_by_mass_lambda(): |
2 | """Return a Lambda Function that returns the Candy with the most Mass""" | 2 | """Return a Lambda Function that returns the Candy with the most Mass""" | ||
3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | 3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | class Candy: | 6 | class Candy: | ||
7 | """A Class that represents a Candy""" | 7 | """A Class that represents a Candy""" | ||
8 | 8 | ||||
9 | def __init__(self, mass: float, uranium: float): | 9 | def __init__(self, mass: float, uranium: float): | ||
10 | self._mass = mass | 10 | self._mass = mass | ||
11 | self._uranium = uranium | 11 | self._uranium = uranium | ||
12 | 12 | ||||
13 | def get_mass(self): | 13 | def get_mass(self): | ||
14 | """Return the Mass of the Candy""" | 14 | """Return the Mass of the Candy""" | ||
15 | return self._mass | 15 | return self._mass | ||
16 | 16 | ||||
17 | def get_uranium_quantity(self): | 17 | def get_uranium_quantity(self): | ||
18 | """Return the total Amount of Uranium in the Candy""" | 18 | """Return the total Amount of Uranium in the Candy""" | ||
19 | return self._mass * self._uranium | 19 | return self._mass * self._uranium | ||
20 | 20 | ||||
21 | 21 | ||||
22 | class Person: | 22 | class Person: | ||
23 | """A Class that Represents a Person""" | 23 | """A Class that Represents a Person""" | ||
24 | 24 | ||||
25 | def __init__(self, position: tuple): | 25 | def __init__(self, position: tuple): | ||
26 | self._position = None | 26 | self._position = None | ||
27 | self.set_position(position) | 27 | self.set_position(position) | ||
28 | self._basket = [] | 28 | self._basket = [] | ||
29 | 29 | ||||
30 | def get_position(self): | 30 | def get_position(self): | ||
31 | """Return the Position of the Person""" | 31 | """Return the Position of the Person""" | ||
32 | return self._position | 32 | return self._position | ||
33 | 33 | ||||
34 | def set_position(self, position: tuple): | 34 | def set_position(self, position: tuple): | ||
35 | """Change the Position of the Person""" | 35 | """Change the Position of the Person""" | ||
36 | self._position = position | 36 | self._position = position | ||
37 | 37 | ||||
38 | def get_distance_to_person(self, person): | 38 | def get_distance_to_person(self, person): | ||
39 | """Return the Distance from the current Person to the passed in Person""" | 39 | """Return the Distance from the current Person to the passed in Person""" | ||
40 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 40 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
41 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 41 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
42 | 42 | ||||
43 | def __repr__(self): | 43 | def __repr__(self): | ||
44 | return f'{self._position}' | 44 | return f'{self._position}' | ||
45 | 45 | ||||
46 | def __getitem__(self, item): | 46 | def __getitem__(self, item): | ||
47 | if isinstance(item, Person): | 47 | if isinstance(item, Person): | ||
48 | return self.get_distance_to_person(item) | 48 | return self.get_distance_to_person(item) | ||
49 | 49 | ||||
50 | return self._position[item] | 50 | return self._position[item] | ||
51 | 51 | ||||
52 | 52 | ||||
53 | class Kid(Person): | 53 | class Kid(Person): | ||
54 | """A Class that represents a Kid""" | 54 | """A Class that represents a Kid""" | ||
55 | 55 | ||||
56 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 56 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
57 | 57 | ||||
58 | def __init__(self, position: tuple, initiative: int): | 58 | def __init__(self, position: tuple, initiative: int): | ||
59 | super().__init__(position) | 59 | super().__init__(position) | ||
60 | self._initiative = initiative | 60 | self._initiative = initiative | ||
61 | 61 | ||||
62 | def get_initiative(self): | 62 | def get_initiative(self): | ||
63 | """Return the Initiative of the Kid""" | 63 | """Return the Initiative of the Kid""" | ||
64 | return self._initiative | 64 | return self._initiative | ||
65 | 65 | ||||
66 | def add_candy(self, candy: Candy): | 66 | def add_candy(self, candy: Candy): | ||
67 | """Add a Candy to the Basket""" | 67 | """Add a Candy to the Basket""" | ||
68 | self._basket.append(candy) | 68 | self._basket.append(candy) | ||
69 | 69 | ||||
70 | def is_critical(self): | 70 | def is_critical(self): | ||
71 | """Return true if the Uranium Amount in the Basket is more than 20g""" | 71 | """Return true if the Uranium Amount in the Basket is more than 20g""" | ||
72 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 72 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
73 | 73 | ||||
74 | def __repr__(self): | 74 | def __repr__(self): | ||
75 | return f'{super().__repr__()} : {self._initiative}' | 75 | return f'{super().__repr__()} : {self._initiative}' | ||
76 | 76 | ||||
77 | 77 | ||||
78 | class Host(Person): | 78 | class Host(Person): | ||
79 | """A Class that represents a Host""" | 79 | """A Class that represents a Host""" | ||
80 | 80 | ||||
81 | def __init__(self, position: tuple, candies: list): | 81 | def __init__(self, position: tuple, candies: list): | ||
82 | super().__init__(position) | 82 | super().__init__(position) | ||
83 | self._basket = candies[:] | 83 | self._basket = candies[:] | ||
84 | 84 | ||||
85 | def remove_candy(self, candy_choosing_function): | 85 | def remove_candy(self, candy_choosing_function): | ||
86 | """Select a Candy from the Basket based on the passed in Function""" | 86 | """Select a Candy from the Basket based on the passed in Function""" | ||
87 | if not self._basket: | 87 | if not self._basket: | ||
88 | return None | 88 | return None | ||
89 | 89 | ||||
90 | chosen_candy = candy_choosing_function(self._basket) | 90 | chosen_candy = candy_choosing_function(self._basket) | ||
91 | 91 | ||||
92 | self._basket.remove(chosen_candy) | 92 | self._basket.remove(chosen_candy) | ||
93 | 93 | ||||
94 | return chosen_candy if chosen_candy else None | 94 | return chosen_candy if chosen_candy else None | ||
95 | 95 | ||||
96 | 96 | ||||
97 | class FluxCapacitor: | 97 | class FluxCapacitor: | ||
98 | """Class that represents a simulation of a Halloween night""" | 98 | """Class that represents a simulation of a Halloween night""" | ||
99 | 99 | ||||
100 | def __init__(self, participants: set): | 100 | def __init__(self, participants: set): | ||
101 | self._kids = [] | 101 | self._kids = [] | ||
102 | self._hosts = [] | 102 | self._hosts = [] | ||
103 | self.__fill_participants(participants) | 103 | self.__fill_participants(participants) | ||
104 | 104 | ||||
105 | def __fill_participants(self, participants: set): | 105 | def __fill_participants(self, participants: set): | ||
106 | [ | 106 | [ | ||
107 | self._kids.append(participant) if type(participant) is Kid | 107 | self._kids.append(participant) if type(participant) is Kid | ||
108 | else self._hosts.append(participant) | 108 | else self._hosts.append(participant) | ||
109 | for participant in participants | 109 | for participant in participants | ||
110 | ] | 110 | ] | ||
111 | 111 | ||||
112 | def get_victim(self): | 112 | def get_victim(self): | ||
113 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | 113 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | ||
114 | sorted_kids = self._kids[:] | 114 | sorted_kids = self._kids[:] | ||
115 | sorted_hosts = self._hosts[:] | 115 | sorted_hosts = self._hosts[:] | ||
116 | 116 | ||||
117 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | 117 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||
118 | 118 | ||||
119 | critical_kids = [] | 119 | critical_kids = [] | ||
120 | for kid in sorted_kids: | 120 | for kid in sorted_kids: | ||
121 | sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | 121 | sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | ||
122 | for host in sorted_hosts: | 122 | for host in sorted_hosts: | ||
123 | removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | 123 | removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | ||
124 | 124 | ||||
125 | if removed_candy: | 125 | if removed_candy: | ||
126 | kid.add_candy(removed_candy) | 126 | kid.add_candy(removed_candy) | ||
127 | 127 | ||||
128 | if kid.is_critical(): | 128 | if kid.is_critical(): | ||
129 | critical_kids.append(kid) | 129 | critical_kids.append(kid) | ||
130 | break | 130 | break | ||
131 | 131 | ||||
t | 132 | return critical_kids | t | 132 | return critical_kids if critical_kids else None |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass_lambda(): | f | 1 | def max_candy_by_mass_lambda(): |
2 | """Return a Lambda Function that returns the Candy with the most Mass""" | 2 | """Return a Lambda Function that returns the Candy with the most Mass""" | ||
3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | 3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | 5 | ||||
6 | class Candy: | 6 | class Candy: | ||
7 | """A Class that represents a Candy""" | 7 | """A Class that represents a Candy""" | ||
8 | 8 | ||||
9 | def __init__(self, mass: float, uranium: float): | 9 | def __init__(self, mass: float, uranium: float): | ||
10 | self._mass = mass | 10 | self._mass = mass | ||
11 | self._uranium = uranium | 11 | self._uranium = uranium | ||
12 | 12 | ||||
13 | def get_mass(self): | 13 | def get_mass(self): | ||
14 | """Return the Mass of the Candy""" | 14 | """Return the Mass of the Candy""" | ||
15 | return self._mass | 15 | return self._mass | ||
16 | 16 | ||||
17 | def get_uranium_quantity(self): | 17 | def get_uranium_quantity(self): | ||
18 | """Return the total Amount of Uranium in the Candy""" | 18 | """Return the total Amount of Uranium in the Candy""" | ||
19 | return self._mass * self._uranium | 19 | return self._mass * self._uranium | ||
20 | 20 | ||||
21 | 21 | ||||
22 | class Person: | 22 | class Person: | ||
23 | """A Class that Represents a Person""" | 23 | """A Class that Represents a Person""" | ||
24 | 24 | ||||
25 | def __init__(self, position: tuple): | 25 | def __init__(self, position: tuple): | ||
26 | self._position = None | 26 | self._position = None | ||
27 | self.set_position(position) | 27 | self.set_position(position) | ||
28 | self._basket = [] | 28 | self._basket = [] | ||
29 | 29 | ||||
30 | def get_position(self): | 30 | def get_position(self): | ||
31 | """Return the Position of the Person""" | 31 | """Return the Position of the Person""" | ||
32 | return self._position | 32 | return self._position | ||
33 | 33 | ||||
34 | def set_position(self, position: tuple): | 34 | def set_position(self, position: tuple): | ||
35 | """Change the Position of the Person""" | 35 | """Change the Position of the Person""" | ||
36 | self._position = position | 36 | self._position = position | ||
37 | 37 | ||||
38 | def get_distance_to_person(self, person): | 38 | def get_distance_to_person(self, person): | ||
39 | """Return the Distance from the current Person to the passed in Person""" | 39 | """Return the Distance from the current Person to the passed in Person""" | ||
40 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 40 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
41 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 41 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
42 | 42 | ||||
43 | def __repr__(self): | 43 | def __repr__(self): | ||
44 | return f'{self._position}' | 44 | return f'{self._position}' | ||
45 | 45 | ||||
46 | def __getitem__(self, item): | 46 | def __getitem__(self, item): | ||
47 | if isinstance(item, Person): | 47 | if isinstance(item, Person): | ||
48 | return self.get_distance_to_person(item) | 48 | return self.get_distance_to_person(item) | ||
49 | 49 | ||||
50 | return self._position[item] | 50 | return self._position[item] | ||
51 | 51 | ||||
52 | 52 | ||||
53 | class Kid(Person): | 53 | class Kid(Person): | ||
54 | """A Class that represents a Kid""" | 54 | """A Class that represents a Kid""" | ||
55 | 55 | ||||
56 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 56 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
57 | 57 | ||||
58 | def __init__(self, position: tuple, initiative: int): | 58 | def __init__(self, position: tuple, initiative: int): | ||
59 | super().__init__(position) | 59 | super().__init__(position) | ||
60 | self._initiative = initiative | 60 | self._initiative = initiative | ||
61 | 61 | ||||
62 | def get_initiative(self): | 62 | def get_initiative(self): | ||
63 | """Return the Initiative of the Kid""" | 63 | """Return the Initiative of the Kid""" | ||
64 | return self._initiative | 64 | return self._initiative | ||
65 | 65 | ||||
66 | def add_candy(self, candy: Candy): | 66 | def add_candy(self, candy: Candy): | ||
67 | """Add a Candy to the Basket""" | 67 | """Add a Candy to the Basket""" | ||
68 | self._basket.append(candy) | 68 | self._basket.append(candy) | ||
69 | 69 | ||||
70 | def is_critical(self): | 70 | def is_critical(self): | ||
71 | """Return true if the Uranium Amount in the Basket is more than 20g""" | 71 | """Return true if the Uranium Amount in the Basket is more than 20g""" | ||
72 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 72 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
73 | 73 | ||||
74 | def __repr__(self): | 74 | def __repr__(self): | ||
75 | return f'{super().__repr__()} : {self._initiative}' | 75 | return f'{super().__repr__()} : {self._initiative}' | ||
76 | 76 | ||||
77 | 77 | ||||
78 | class Host(Person): | 78 | class Host(Person): | ||
79 | """A Class that represents a Host""" | 79 | """A Class that represents a Host""" | ||
80 | 80 | ||||
81 | def __init__(self, position: tuple, candies: list): | 81 | def __init__(self, position: tuple, candies: list): | ||
82 | super().__init__(position) | 82 | super().__init__(position) | ||
83 | self._basket = candies[:] | 83 | self._basket = candies[:] | ||
84 | 84 | ||||
85 | def remove_candy(self, candy_choosing_function): | 85 | def remove_candy(self, candy_choosing_function): | ||
86 | """Select a Candy from the Basket based on the passed in Function""" | 86 | """Select a Candy from the Basket based on the passed in Function""" | ||
87 | if not self._basket: | 87 | if not self._basket: | ||
88 | return None | 88 | return None | ||
89 | 89 | ||||
90 | chosen_candy = candy_choosing_function(self._basket) | 90 | chosen_candy = candy_choosing_function(self._basket) | ||
91 | 91 | ||||
92 | self._basket.remove(chosen_candy) | 92 | self._basket.remove(chosen_candy) | ||
93 | 93 | ||||
94 | return chosen_candy if chosen_candy else None | 94 | return chosen_candy if chosen_candy else None | ||
95 | 95 | ||||
96 | 96 | ||||
97 | class FluxCapacitor: | 97 | class FluxCapacitor: | ||
98 | """Class that represents a simulation of a Halloween night""" | 98 | """Class that represents a simulation of a Halloween night""" | ||
99 | 99 | ||||
100 | def __init__(self, participants: set): | 100 | def __init__(self, participants: set): | ||
101 | self._kids = [] | 101 | self._kids = [] | ||
102 | self._hosts = [] | 102 | self._hosts = [] | ||
103 | self.__fill_participants(participants) | 103 | self.__fill_participants(participants) | ||
104 | 104 | ||||
105 | def __fill_participants(self, participants: set): | 105 | def __fill_participants(self, participants: set): | ||
106 | [ | 106 | [ | ||
107 | self._kids.append(participant) if type(participant) is Kid | 107 | self._kids.append(participant) if type(participant) is Kid | ||
108 | else self._hosts.append(participant) | 108 | else self._hosts.append(participant) | ||
109 | for participant in participants | 109 | for participant in participants | ||
110 | ] | 110 | ] | ||
111 | 111 | ||||
112 | def get_victim(self): | 112 | def get_victim(self): | ||
113 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | 113 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | ||
114 | sorted_kids = self._kids[:] | 114 | sorted_kids = self._kids[:] | ||
115 | sorted_hosts = self._hosts[:] | 115 | sorted_hosts = self._hosts[:] | ||
116 | 116 | ||||
117 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | 117 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||
118 | 118 | ||||
119 | critical_kids = [] | 119 | critical_kids = [] | ||
120 | for kid in sorted_kids: | 120 | for kid in sorted_kids: | ||
121 | sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | 121 | sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | ||
t | 122 | for host in self._hosts: | t | 122 | for host in sorted_hosts: |
123 | removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | 123 | removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | ||
124 | 124 | ||||
125 | if removed_candy: | 125 | if removed_candy: | ||
126 | kid.add_candy(removed_candy) | 126 | kid.add_candy(removed_candy) | ||
127 | 127 | ||||
128 | if kid.is_critical(): | 128 | if kid.is_critical(): | ||
129 | critical_kids.append(kid) | 129 | critical_kids.append(kid) | ||
130 | break | 130 | break | ||
131 | 131 | ||||
132 | return critical_kids | 132 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass_lambda(): | f | 1 | def max_candy_by_mass_lambda(): |
2 | """Return a Lambda Function that returns the Candy with the most Mass""" | 2 | """Return a Lambda Function that returns the Candy with the most Mass""" | ||
3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | 3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | ||
t | t | 4 | |||
4 | 5 | ||||
5 | class Candy: | 6 | class Candy: | ||
6 | """A Class that represents a Candy""" | 7 | """A Class that represents a Candy""" | ||
7 | 8 | ||||
8 | def __init__(self, mass: float, uranium: float): | 9 | def __init__(self, mass: float, uranium: float): | ||
9 | self._mass = mass | 10 | self._mass = mass | ||
10 | self._uranium = uranium | 11 | self._uranium = uranium | ||
11 | 12 | ||||
12 | def get_mass(self): | 13 | def get_mass(self): | ||
13 | """Return the Mass of the Candy""" | 14 | """Return the Mass of the Candy""" | ||
14 | return self._mass | 15 | return self._mass | ||
15 | 16 | ||||
16 | def get_uranium_quantity(self): | 17 | def get_uranium_quantity(self): | ||
17 | """Return the total Amount of Uranium in the Candy""" | 18 | """Return the total Amount of Uranium in the Candy""" | ||
18 | return self._mass * self._uranium | 19 | return self._mass * self._uranium | ||
19 | 20 | ||||
20 | 21 | ||||
21 | class Person: | 22 | class Person: | ||
22 | """A Class that Represents a Person""" | 23 | """A Class that Represents a Person""" | ||
23 | 24 | ||||
24 | def __init__(self, position: tuple): | 25 | def __init__(self, position: tuple): | ||
25 | self._position = None | 26 | self._position = None | ||
26 | self.set_position(position) | 27 | self.set_position(position) | ||
27 | self._basket = [] | 28 | self._basket = [] | ||
28 | 29 | ||||
29 | def get_position(self): | 30 | def get_position(self): | ||
30 | """Return the Position of the Person""" | 31 | """Return the Position of the Person""" | ||
31 | return self._position | 32 | return self._position | ||
32 | 33 | ||||
33 | def set_position(self, position: tuple): | 34 | def set_position(self, position: tuple): | ||
34 | """Change the Position of the Person""" | 35 | """Change the Position of the Person""" | ||
35 | self._position = position | 36 | self._position = position | ||
36 | 37 | ||||
37 | def get_distance_to_person(self, person): | 38 | def get_distance_to_person(self, person): | ||
38 | """Return the Distance from the current Person to the passed in Person""" | 39 | """Return the Distance from the current Person to the passed in Person""" | ||
39 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 40 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
40 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 41 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
41 | 42 | ||||
42 | def __repr__(self): | 43 | def __repr__(self): | ||
43 | return f'{self._position}' | 44 | return f'{self._position}' | ||
44 | 45 | ||||
45 | def __getitem__(self, item): | 46 | def __getitem__(self, item): | ||
46 | if isinstance(item, Person): | 47 | if isinstance(item, Person): | ||
47 | return self.get_distance_to_person(item) | 48 | return self.get_distance_to_person(item) | ||
48 | 49 | ||||
49 | return self._position[item] | 50 | return self._position[item] | ||
50 | 51 | ||||
51 | 52 | ||||
52 | class Kid(Person): | 53 | class Kid(Person): | ||
53 | """A Class that represents a Kid""" | 54 | """A Class that represents a Kid""" | ||
54 | 55 | ||||
55 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 56 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
56 | 57 | ||||
57 | def __init__(self, position: tuple, initiative: int): | 58 | def __init__(self, position: tuple, initiative: int): | ||
58 | super().__init__(position) | 59 | super().__init__(position) | ||
59 | self._initiative = initiative | 60 | self._initiative = initiative | ||
60 | 61 | ||||
61 | def get_initiative(self): | 62 | def get_initiative(self): | ||
62 | """Return the Initiative of the Kid""" | 63 | """Return the Initiative of the Kid""" | ||
63 | return self._initiative | 64 | return self._initiative | ||
64 | 65 | ||||
65 | def add_candy(self, candy: Candy): | 66 | def add_candy(self, candy: Candy): | ||
66 | """Add a Candy to the Basket""" | 67 | """Add a Candy to the Basket""" | ||
67 | self._basket.append(candy) | 68 | self._basket.append(candy) | ||
68 | 69 | ||||
69 | def is_critical(self): | 70 | def is_critical(self): | ||
70 | """Return true if the Uranium Amount in the Basket is more than 20g""" | 71 | """Return true if the Uranium Amount in the Basket is more than 20g""" | ||
71 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 72 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
72 | 73 | ||||
73 | def __repr__(self): | 74 | def __repr__(self): | ||
74 | return f'{super().__repr__()} : {self._initiative}' | 75 | return f'{super().__repr__()} : {self._initiative}' | ||
75 | 76 | ||||
76 | 77 | ||||
77 | class Host(Person): | 78 | class Host(Person): | ||
78 | """A Class that represents a Host""" | 79 | """A Class that represents a Host""" | ||
79 | 80 | ||||
80 | def __init__(self, position: tuple, candies: list): | 81 | def __init__(self, position: tuple, candies: list): | ||
81 | super().__init__(position) | 82 | super().__init__(position) | ||
82 | self._basket = candies[:] | 83 | self._basket = candies[:] | ||
83 | 84 | ||||
84 | def remove_candy(self, candy_choosing_function): | 85 | def remove_candy(self, candy_choosing_function): | ||
85 | """Select a Candy from the Basket based on the passed in Function""" | 86 | """Select a Candy from the Basket based on the passed in Function""" | ||
86 | if not self._basket: | 87 | if not self._basket: | ||
87 | return None | 88 | return None | ||
88 | 89 | ||||
89 | chosen_candy = candy_choosing_function(self._basket) | 90 | chosen_candy = candy_choosing_function(self._basket) | ||
90 | 91 | ||||
91 | self._basket.remove(chosen_candy) | 92 | self._basket.remove(chosen_candy) | ||
92 | 93 | ||||
93 | return chosen_candy if chosen_candy else None | 94 | return chosen_candy if chosen_candy else None | ||
94 | 95 | ||||
95 | 96 | ||||
96 | class FluxCapacitor: | 97 | class FluxCapacitor: | ||
97 | """Class that represents a simulation of a Halloween night""" | 98 | """Class that represents a simulation of a Halloween night""" | ||
98 | 99 | ||||
99 | def __init__(self, participants: set): | 100 | def __init__(self, participants: set): | ||
100 | self._kids = [] | 101 | self._kids = [] | ||
101 | self._hosts = [] | 102 | self._hosts = [] | ||
102 | self.__fill_participants(participants) | 103 | self.__fill_participants(participants) | ||
103 | 104 | ||||
104 | def __fill_participants(self, participants: set): | 105 | def __fill_participants(self, participants: set): | ||
105 | [ | 106 | [ | ||
106 | self._kids.append(participant) if type(participant) is Kid | 107 | self._kids.append(participant) if type(participant) is Kid | ||
107 | else self._hosts.append(participant) | 108 | else self._hosts.append(participant) | ||
108 | for participant in participants | 109 | for participant in participants | ||
109 | ] | 110 | ] | ||
110 | 111 | ||||
111 | def get_victim(self): | 112 | def get_victim(self): | ||
112 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | 113 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | ||
113 | sorted_kids = self._kids[:] | 114 | sorted_kids = self._kids[:] | ||
114 | sorted_hosts = self._hosts[:] | 115 | sorted_hosts = self._hosts[:] | ||
115 | 116 | ||||
116 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | 117 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||
117 | 118 | ||||
118 | critical_kids = [] | 119 | critical_kids = [] | ||
119 | for kid in sorted_kids: | 120 | for kid in sorted_kids: | ||
120 | sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | 121 | sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | ||
121 | for host in self._hosts: | 122 | for host in self._hosts: | ||
122 | removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | 123 | removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | ||
123 | 124 | ||||
124 | if removed_candy: | 125 | if removed_candy: | ||
125 | kid.add_candy(removed_candy) | 126 | kid.add_candy(removed_candy) | ||
126 | 127 | ||||
127 | if kid.is_critical(): | 128 | if kid.is_critical(): | ||
128 | critical_kids.append(kid) | 129 | critical_kids.append(kid) | ||
129 | break | 130 | break | ||
130 | 131 | ||||
131 | return critical_kids | 132 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def max_candy_by_mass_lambda(): | f | 1 | def max_candy_by_mass_lambda(): |
2 | """Return a Lambda Function that returns the Candy with the most Mass""" | 2 | """Return a Lambda Function that returns the Candy with the most Mass""" | ||
3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | 3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | ||
4 | 4 | ||||
5 | class Candy: | 5 | class Candy: | ||
6 | """A Class that represents a Candy""" | 6 | """A Class that represents a Candy""" | ||
7 | 7 | ||||
8 | def __init__(self, mass: float, uranium: float): | 8 | def __init__(self, mass: float, uranium: float): | ||
9 | self._mass = mass | 9 | self._mass = mass | ||
10 | self._uranium = uranium | 10 | self._uranium = uranium | ||
11 | 11 | ||||
12 | def get_mass(self): | 12 | def get_mass(self): | ||
13 | """Return the Mass of the Candy""" | 13 | """Return the Mass of the Candy""" | ||
14 | return self._mass | 14 | return self._mass | ||
15 | 15 | ||||
16 | def get_uranium_quantity(self): | 16 | def get_uranium_quantity(self): | ||
17 | """Return the total Amount of Uranium in the Candy""" | 17 | """Return the total Amount of Uranium in the Candy""" | ||
18 | return self._mass * self._uranium | 18 | return self._mass * self._uranium | ||
19 | 19 | ||||
20 | 20 | ||||
21 | class Person: | 21 | class Person: | ||
22 | """A Class that Represents a Person""" | 22 | """A Class that Represents a Person""" | ||
23 | 23 | ||||
24 | def __init__(self, position: tuple): | 24 | def __init__(self, position: tuple): | ||
25 | self._position = None | 25 | self._position = None | ||
26 | self.set_position(position) | 26 | self.set_position(position) | ||
27 | self._basket = [] | 27 | self._basket = [] | ||
28 | 28 | ||||
29 | def get_position(self): | 29 | def get_position(self): | ||
30 | """Return the Position of the Person""" | 30 | """Return the Position of the Person""" | ||
31 | return self._position | 31 | return self._position | ||
32 | 32 | ||||
33 | def set_position(self, position: tuple): | 33 | def set_position(self, position: tuple): | ||
34 | """Change the Position of the Person""" | 34 | """Change the Position of the Person""" | ||
35 | self._position = position | 35 | self._position = position | ||
36 | 36 | ||||
37 | def get_distance_to_person(self, person): | 37 | def get_distance_to_person(self, person): | ||
38 | """Return the Distance from the current Person to the passed in Person""" | 38 | """Return the Distance from the current Person to the passed in Person""" | ||
39 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 39 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
40 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 40 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
41 | 41 | ||||
42 | def __repr__(self): | 42 | def __repr__(self): | ||
43 | return f'{self._position}' | 43 | return f'{self._position}' | ||
44 | 44 | ||||
45 | def __getitem__(self, item): | 45 | def __getitem__(self, item): | ||
46 | if isinstance(item, Person): | 46 | if isinstance(item, Person): | ||
47 | return self.get_distance_to_person(item) | 47 | return self.get_distance_to_person(item) | ||
48 | 48 | ||||
49 | return self._position[item] | 49 | return self._position[item] | ||
50 | 50 | ||||
51 | 51 | ||||
52 | class Kid(Person): | 52 | class Kid(Person): | ||
53 | """A Class that represents a Kid""" | 53 | """A Class that represents a Kid""" | ||
54 | 54 | ||||
55 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 55 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
56 | 56 | ||||
57 | def __init__(self, position: tuple, initiative: int): | 57 | def __init__(self, position: tuple, initiative: int): | ||
58 | super().__init__(position) | 58 | super().__init__(position) | ||
59 | self._initiative = initiative | 59 | self._initiative = initiative | ||
60 | 60 | ||||
61 | def get_initiative(self): | 61 | def get_initiative(self): | ||
62 | """Return the Initiative of the Kid""" | 62 | """Return the Initiative of the Kid""" | ||
63 | return self._initiative | 63 | return self._initiative | ||
64 | 64 | ||||
65 | def add_candy(self, candy: Candy): | 65 | def add_candy(self, candy: Candy): | ||
66 | """Add a Candy to the Basket""" | 66 | """Add a Candy to the Basket""" | ||
67 | self._basket.append(candy) | 67 | self._basket.append(candy) | ||
68 | 68 | ||||
69 | def is_critical(self): | 69 | def is_critical(self): | ||
70 | """Return true if the Uranium Amount in the Basket is more than 20g""" | 70 | """Return true if the Uranium Amount in the Basket is more than 20g""" | ||
71 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 71 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
72 | 72 | ||||
73 | def __repr__(self): | 73 | def __repr__(self): | ||
74 | return f'{super().__repr__()} : {self._initiative}' | 74 | return f'{super().__repr__()} : {self._initiative}' | ||
75 | 75 | ||||
76 | 76 | ||||
77 | class Host(Person): | 77 | class Host(Person): | ||
78 | """A Class that represents a Host""" | 78 | """A Class that represents a Host""" | ||
79 | 79 | ||||
80 | def __init__(self, position: tuple, candies: list): | 80 | def __init__(self, position: tuple, candies: list): | ||
81 | super().__init__(position) | 81 | super().__init__(position) | ||
82 | self._basket = candies[:] | 82 | self._basket = candies[:] | ||
83 | 83 | ||||
84 | def remove_candy(self, candy_choosing_function): | 84 | def remove_candy(self, candy_choosing_function): | ||
85 | """Select a Candy from the Basket based on the passed in Function""" | 85 | """Select a Candy from the Basket based on the passed in Function""" | ||
86 | if not self._basket: | 86 | if not self._basket: | ||
87 | return None | 87 | return None | ||
88 | 88 | ||||
89 | chosen_candy = candy_choosing_function(self._basket) | 89 | chosen_candy = candy_choosing_function(self._basket) | ||
90 | 90 | ||||
91 | self._basket.remove(chosen_candy) | 91 | self._basket.remove(chosen_candy) | ||
92 | 92 | ||||
93 | return chosen_candy if chosen_candy else None | 93 | return chosen_candy if chosen_candy else None | ||
94 | 94 | ||||
95 | 95 | ||||
96 | class FluxCapacitor: | 96 | class FluxCapacitor: | ||
97 | """Class that represents a simulation of a Halloween night""" | 97 | """Class that represents a simulation of a Halloween night""" | ||
98 | 98 | ||||
99 | def __init__(self, participants: set): | 99 | def __init__(self, participants: set): | ||
100 | self._kids = [] | 100 | self._kids = [] | ||
101 | self._hosts = [] | 101 | self._hosts = [] | ||
102 | self.__fill_participants(participants) | 102 | self.__fill_participants(participants) | ||
103 | 103 | ||||
104 | def __fill_participants(self, participants: set): | 104 | def __fill_participants(self, participants: set): | ||
105 | [ | 105 | [ | ||
106 | self._kids.append(participant) if type(participant) is Kid | 106 | self._kids.append(participant) if type(participant) is Kid | ||
107 | else self._hosts.append(participant) | 107 | else self._hosts.append(participant) | ||
108 | for participant in participants | 108 | for participant in participants | ||
109 | ] | 109 | ] | ||
110 | 110 | ||||
111 | def get_victim(self): | 111 | def get_victim(self): | ||
112 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | 112 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | ||
113 | sorted_kids = self._kids[:] | 113 | sorted_kids = self._kids[:] | ||
114 | sorted_hosts = self._hosts[:] | 114 | sorted_hosts = self._hosts[:] | ||
115 | 115 | ||||
116 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | 116 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) | ||
117 | 117 | ||||
118 | critical_kids = [] | 118 | critical_kids = [] | ||
t | 119 | # for kid in sorted_kids: | t | 119 | for kid in sorted_kids: |
120 | # sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | 120 | sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | ||
121 | # for host in self._hosts: | 121 | for host in self._hosts: | ||
122 | # removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | 122 | removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | ||
123 | # | 123 | |||
124 | # if removed_candy: | 124 | if removed_candy: | ||
125 | # kid.add_candy(removed_candy) | 125 | kid.add_candy(removed_candy) | ||
126 | # | 126 | |||
127 | # if kid.is_critical(): | 127 | if kid.is_critical(): | ||
128 | # critical_kids.append(kid) | 128 | critical_kids.append(kid) | ||
129 | # break | 129 | break | ||
130 | 130 | ||||
131 | return critical_kids | 131 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
n | n | 1 | def max_candy_by_mass_lambda(): | ||
2 | """Return a Lambda Function that returns the Candy with the most Mass""" | ||||
3 | return lambda candies: max(candies, key=lambda candy: candy.get_mass()) | ||||
4 | |||||
1 | class Candy: | 5 | class Candy: | ||
2 | """A Class that represents a Candy""" | 6 | """A Class that represents a Candy""" | ||
3 | 7 | ||||
4 | def __init__(self, mass: float, uranium: float): | 8 | def __init__(self, mass: float, uranium: float): | ||
5 | self._mass = mass | 9 | self._mass = mass | ||
6 | self._uranium = uranium | 10 | self._uranium = uranium | ||
7 | 11 | ||||
8 | def get_mass(self): | 12 | def get_mass(self): | ||
9 | """Return the Mass of the Candy""" | 13 | """Return the Mass of the Candy""" | ||
10 | return self._mass | 14 | return self._mass | ||
11 | 15 | ||||
12 | def get_uranium_quantity(self): | 16 | def get_uranium_quantity(self): | ||
13 | """Return the total Amount of Uranium in the Candy""" | 17 | """Return the total Amount of Uranium in the Candy""" | ||
14 | return self._mass * self._uranium | 18 | return self._mass * self._uranium | ||
15 | 19 | ||||
16 | 20 | ||||
17 | class Person: | 21 | class Person: | ||
18 | """A Class that Represents a Person""" | 22 | """A Class that Represents a Person""" | ||
19 | 23 | ||||
20 | def __init__(self, position: tuple): | 24 | def __init__(self, position: tuple): | ||
21 | self._position = None | 25 | self._position = None | ||
22 | self.set_position(position) | 26 | self.set_position(position) | ||
23 | self._basket = [] | 27 | self._basket = [] | ||
24 | 28 | ||||
25 | def get_position(self): | 29 | def get_position(self): | ||
26 | """Return the Position of the Person""" | 30 | """Return the Position of the Person""" | ||
27 | return self._position | 31 | return self._position | ||
28 | 32 | ||||
29 | def set_position(self, position: tuple): | 33 | def set_position(self, position: tuple): | ||
30 | """Change the Position of the Person""" | 34 | """Change the Position of the Person""" | ||
31 | self._position = position | 35 | self._position = position | ||
32 | 36 | ||||
33 | def get_distance_to_person(self, person): | 37 | def get_distance_to_person(self, person): | ||
34 | """Return the Distance from the current Person to the passed in Person""" | 38 | """Return the Distance from the current Person to the passed in Person""" | ||
35 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 39 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
36 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 40 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
37 | 41 | ||||
38 | def __repr__(self): | 42 | def __repr__(self): | ||
39 | return f'{self._position}' | 43 | return f'{self._position}' | ||
40 | 44 | ||||
41 | def __getitem__(self, item): | 45 | def __getitem__(self, item): | ||
42 | if isinstance(item, Person): | 46 | if isinstance(item, Person): | ||
43 | return self.get_distance_to_person(item) | 47 | return self.get_distance_to_person(item) | ||
44 | 48 | ||||
45 | return self._position[item] | 49 | return self._position[item] | ||
46 | 50 | ||||
47 | 51 | ||||
48 | class Kid(Person): | 52 | class Kid(Person): | ||
49 | """A Class that represents a Kid""" | 53 | """A Class that represents a Kid""" | ||
50 | 54 | ||||
51 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 55 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
52 | 56 | ||||
53 | def __init__(self, position: tuple, initiative: int): | 57 | def __init__(self, position: tuple, initiative: int): | ||
54 | super().__init__(position) | 58 | super().__init__(position) | ||
55 | self._initiative = initiative | 59 | self._initiative = initiative | ||
56 | 60 | ||||
57 | def get_initiative(self): | 61 | def get_initiative(self): | ||
58 | """Return the Initiative of the Kid""" | 62 | """Return the Initiative of the Kid""" | ||
59 | return self._initiative | 63 | return self._initiative | ||
60 | 64 | ||||
61 | def add_candy(self, candy: Candy): | 65 | def add_candy(self, candy: Candy): | ||
62 | """Add a Candy to the Basket""" | 66 | """Add a Candy to the Basket""" | ||
63 | self._basket.append(candy) | 67 | self._basket.append(candy) | ||
64 | 68 | ||||
65 | def is_critical(self): | 69 | def is_critical(self): | ||
66 | """Return true if the Uranium Amount in the Basket is more than 20g""" | 70 | """Return true if the Uranium Amount in the Basket is more than 20g""" | ||
67 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 71 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
68 | 72 | ||||
69 | def __repr__(self): | 73 | def __repr__(self): | ||
70 | return f'{super().__repr__()} : {self._initiative}' | 74 | return f'{super().__repr__()} : {self._initiative}' | ||
71 | 75 | ||||
72 | 76 | ||||
73 | class Host(Person): | 77 | class Host(Person): | ||
74 | """A Class that represents a Host""" | 78 | """A Class that represents a Host""" | ||
75 | 79 | ||||
76 | def __init__(self, position: tuple, candies: list): | 80 | def __init__(self, position: tuple, candies: list): | ||
77 | super().__init__(position) | 81 | super().__init__(position) | ||
78 | self._basket = candies[:] | 82 | self._basket = candies[:] | ||
79 | 83 | ||||
80 | def remove_candy(self, candy_choosing_function): | 84 | def remove_candy(self, candy_choosing_function): | ||
81 | """Select a Candy from the Basket based on the passed in Function""" | 85 | """Select a Candy from the Basket based on the passed in Function""" | ||
82 | if not self._basket: | 86 | if not self._basket: | ||
83 | return None | 87 | return None | ||
84 | 88 | ||||
85 | chosen_candy = candy_choosing_function(self._basket) | 89 | chosen_candy = candy_choosing_function(self._basket) | ||
86 | 90 | ||||
87 | self._basket.remove(chosen_candy) | 91 | self._basket.remove(chosen_candy) | ||
88 | 92 | ||||
n | 89 | return chosen_candy | n | 93 | return chosen_candy if chosen_candy else None |
90 | 94 | ||||
91 | 95 | ||||
92 | class FluxCapacitor: | 96 | class FluxCapacitor: | ||
93 | """Class that represents a simulation of a Halloween night""" | 97 | """Class that represents a simulation of a Halloween night""" | ||
94 | 98 | ||||
95 | def __init__(self, participants: set): | 99 | def __init__(self, participants: set): | ||
96 | self._kids = [] | 100 | self._kids = [] | ||
97 | self._hosts = [] | 101 | self._hosts = [] | ||
98 | self.__fill_participants(participants) | 102 | self.__fill_participants(participants) | ||
99 | 103 | ||||
100 | def __fill_participants(self, participants: set): | 104 | def __fill_participants(self, participants: set): | ||
101 | [ | 105 | [ | ||
102 | self._kids.append(participant) if type(participant) is Kid | 106 | self._kids.append(participant) if type(participant) is Kid | ||
103 | else self._hosts.append(participant) | 107 | else self._hosts.append(participant) | ||
104 | for participant in participants | 108 | for participant in participants | ||
105 | ] | 109 | ] | ||
106 | 110 | ||||
107 | def get_victim(self): | 111 | def get_victim(self): | ||
108 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | 112 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | ||
109 | sorted_kids = self._kids[:] | 113 | sorted_kids = self._kids[:] | ||
110 | sorted_hosts = self._hosts[:] | 114 | sorted_hosts = self._hosts[:] | ||
111 | 115 | ||||
n | 112 | sorted_kids.sort(key=lambda kid: kid.get_initiative(), reverse=True) | n | 116 | sorted_kids.sort(key=lambda curr_kid: curr_kid.get_initiative(), reverse=True) |
113 | 117 | ||||
114 | critical_kids = [] | 118 | critical_kids = [] | ||
t | 115 | for kid in sorted_kids: | t | 119 | # for kid in sorted_kids: |
116 | sorted_hosts.sort(key=lambda h: (h[kid], h[0], h[1])) | 120 | # sorted_hosts.sort(key=lambda curr_host: (curr_host[kid], curr_host[0], curr_host[1])) | ||
117 | for host in self._hosts: | 121 | # for host in self._hosts: | ||
118 | removed_candy = host.remove_candy(lambda x: max(x, key=lambda c: c.get_uranium_quantity())) | 122 | # removed_candy = host.remove_candy(max_candy_by_mass_lambda()) | ||
119 | 123 | # | |||
120 | if removed_candy: | 124 | # if removed_candy: | ||
121 | kid.add_candy(removed_candy) | 125 | # kid.add_candy(removed_candy) | ||
122 | 126 | # | |||
123 | if kid.is_critical(): | 127 | # if kid.is_critical(): | ||
124 | critical_kids.append(kid) | 128 | # critical_kids.append(kid) | ||
125 | break | 129 | # break | ||
126 | 130 | ||||
127 | return critical_kids | 131 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | class Candy: | f | 1 | class Candy: |
2 | """A Class that represents a Candy""" | 2 | """A Class that represents a Candy""" | ||
3 | 3 | ||||
4 | def __init__(self, mass: float, uranium: float): | 4 | def __init__(self, mass: float, uranium: float): | ||
5 | self._mass = mass | 5 | self._mass = mass | ||
6 | self._uranium = uranium | 6 | self._uranium = uranium | ||
7 | 7 | ||||
8 | def get_mass(self): | 8 | def get_mass(self): | ||
9 | """Return the Mass of the Candy""" | 9 | """Return the Mass of the Candy""" | ||
10 | return self._mass | 10 | return self._mass | ||
11 | 11 | ||||
12 | def get_uranium_quantity(self): | 12 | def get_uranium_quantity(self): | ||
13 | """Return the total Amount of Uranium in the Candy""" | 13 | """Return the total Amount of Uranium in the Candy""" | ||
14 | return self._mass * self._uranium | 14 | return self._mass * self._uranium | ||
15 | 15 | ||||
16 | 16 | ||||
17 | class Person: | 17 | class Person: | ||
18 | """A Class that Represents a Person""" | 18 | """A Class that Represents a Person""" | ||
19 | 19 | ||||
20 | def __init__(self, position: tuple): | 20 | def __init__(self, position: tuple): | ||
21 | self._position = None | 21 | self._position = None | ||
22 | self.set_position(position) | 22 | self.set_position(position) | ||
23 | self._basket = [] | 23 | self._basket = [] | ||
24 | 24 | ||||
25 | def get_position(self): | 25 | def get_position(self): | ||
26 | """Return the Position of the Person""" | 26 | """Return the Position of the Person""" | ||
27 | return self._position | 27 | return self._position | ||
28 | 28 | ||||
29 | def set_position(self, position: tuple): | 29 | def set_position(self, position: tuple): | ||
30 | """Change the Position of the Person""" | 30 | """Change the Position of the Person""" | ||
31 | self._position = position | 31 | self._position = position | ||
32 | 32 | ||||
33 | def get_distance_to_person(self, person): | 33 | def get_distance_to_person(self, person): | ||
34 | """Return the Distance from the current Person to the passed in Person""" | 34 | """Return the Distance from the current Person to the passed in Person""" | ||
35 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | 35 | return ((self._position[0] - person.get_position()[0]) ** 2 + ( | ||
36 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | 36 | self._position[1] - person.get_position()[1]) ** 2) ** 0.5 | ||
37 | 37 | ||||
38 | def __repr__(self): | 38 | def __repr__(self): | ||
39 | return f'{self._position}' | 39 | return f'{self._position}' | ||
40 | 40 | ||||
41 | def __getitem__(self, item): | 41 | def __getitem__(self, item): | ||
42 | if isinstance(item, Person): | 42 | if isinstance(item, Person): | ||
43 | return self.get_distance_to_person(item) | 43 | return self.get_distance_to_person(item) | ||
44 | 44 | ||||
45 | return self._position[item] | 45 | return self._position[item] | ||
46 | 46 | ||||
47 | 47 | ||||
48 | class Kid(Person): | 48 | class Kid(Person): | ||
49 | """A Class that represents a Kid""" | 49 | """A Class that represents a Kid""" | ||
50 | 50 | ||||
51 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | 51 | CRITICAL_URANIUM_AMOUNT_IN_GRAMS = 20 | ||
52 | 52 | ||||
53 | def __init__(self, position: tuple, initiative: int): | 53 | def __init__(self, position: tuple, initiative: int): | ||
54 | super().__init__(position) | 54 | super().__init__(position) | ||
55 | self._initiative = initiative | 55 | self._initiative = initiative | ||
56 | 56 | ||||
57 | def get_initiative(self): | 57 | def get_initiative(self): | ||
58 | """Return the Initiative of the Kid""" | 58 | """Return the Initiative of the Kid""" | ||
59 | return self._initiative | 59 | return self._initiative | ||
60 | 60 | ||||
61 | def add_candy(self, candy: Candy): | 61 | def add_candy(self, candy: Candy): | ||
62 | """Add a Candy to the Basket""" | 62 | """Add a Candy to the Basket""" | ||
63 | self._basket.append(candy) | 63 | self._basket.append(candy) | ||
64 | 64 | ||||
65 | def is_critical(self): | 65 | def is_critical(self): | ||
66 | """Return true if the Uranium Amount in the Basket is more than 20g""" | 66 | """Return true if the Uranium Amount in the Basket is more than 20g""" | ||
67 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | 67 | return sum([candy.get_uranium_quantity() for candy in self._basket]) > Kid.CRITICAL_URANIUM_AMOUNT_IN_GRAMS | ||
68 | 68 | ||||
69 | def __repr__(self): | 69 | def __repr__(self): | ||
70 | return f'{super().__repr__()} : {self._initiative}' | 70 | return f'{super().__repr__()} : {self._initiative}' | ||
71 | 71 | ||||
72 | 72 | ||||
73 | class Host(Person): | 73 | class Host(Person): | ||
74 | """A Class that represents a Host""" | 74 | """A Class that represents a Host""" | ||
75 | 75 | ||||
76 | def __init__(self, position: tuple, candies: list): | 76 | def __init__(self, position: tuple, candies: list): | ||
77 | super().__init__(position) | 77 | super().__init__(position) | ||
78 | self._basket = candies[:] | 78 | self._basket = candies[:] | ||
79 | 79 | ||||
80 | def remove_candy(self, candy_choosing_function): | 80 | def remove_candy(self, candy_choosing_function): | ||
81 | """Select a Candy from the Basket based on the passed in Function""" | 81 | """Select a Candy from the Basket based on the passed in Function""" | ||
82 | if not self._basket: | 82 | if not self._basket: | ||
83 | return None | 83 | return None | ||
84 | 84 | ||||
85 | chosen_candy = candy_choosing_function(self._basket) | 85 | chosen_candy = candy_choosing_function(self._basket) | ||
86 | 86 | ||||
87 | self._basket.remove(chosen_candy) | 87 | self._basket.remove(chosen_candy) | ||
88 | 88 | ||||
89 | return chosen_candy | 89 | return chosen_candy | ||
90 | 90 | ||||
91 | 91 | ||||
92 | class FluxCapacitor: | 92 | class FluxCapacitor: | ||
93 | """Class that represents a simulation of a Halloween night""" | 93 | """Class that represents a simulation of a Halloween night""" | ||
94 | 94 | ||||
95 | def __init__(self, participants: set): | 95 | def __init__(self, participants: set): | ||
96 | self._kids = [] | 96 | self._kids = [] | ||
97 | self._hosts = [] | 97 | self._hosts = [] | ||
98 | self.__fill_participants(participants) | 98 | self.__fill_participants(participants) | ||
99 | 99 | ||||
100 | def __fill_participants(self, participants: set): | 100 | def __fill_participants(self, participants: set): | ||
101 | [ | 101 | [ | ||
102 | self._kids.append(participant) if type(participant) is Kid | 102 | self._kids.append(participant) if type(participant) is Kid | ||
103 | else self._hosts.append(participant) | 103 | else self._hosts.append(participant) | ||
104 | for participant in participants | 104 | for participant in participants | ||
105 | ] | 105 | ] | ||
106 | 106 | ||||
107 | def get_victim(self): | 107 | def get_victim(self): | ||
108 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | 108 | """Simulate a Halloween night and return the Kids who have the most Uranium""" | ||
109 | sorted_kids = self._kids[:] | 109 | sorted_kids = self._kids[:] | ||
110 | sorted_hosts = self._hosts[:] | 110 | sorted_hosts = self._hosts[:] | ||
111 | 111 | ||||
112 | sorted_kids.sort(key=lambda kid: kid.get_initiative(), reverse=True) | 112 | sorted_kids.sort(key=lambda kid: kid.get_initiative(), reverse=True) | ||
113 | 113 | ||||
114 | critical_kids = [] | 114 | critical_kids = [] | ||
115 | for kid in sorted_kids: | 115 | for kid in sorted_kids: | ||
t | 116 | sorted_hosts.sort(key=lambda h: (h[k1], h[0], h[1])) | t | 116 | sorted_hosts.sort(key=lambda h: (h[kid], h[0], h[1])) |
117 | for host in self._hosts: | 117 | for host in self._hosts: | ||
118 | removed_candy = host.remove_candy(lambda x: max(x, key=lambda c: c.get_uranium_quantity())) | 118 | removed_candy = host.remove_candy(lambda x: max(x, key=lambda c: c.get_uranium_quantity())) | ||
119 | 119 | ||||
120 | if removed_candy: | 120 | if removed_candy: | ||
121 | kid.add_candy(removed_candy) | 121 | kid.add_candy(removed_candy) | ||
122 | 122 | ||||
123 | if kid.is_critical(): | 123 | if kid.is_critical(): | ||
124 | critical_kids.append(kid) | 124 | critical_kids.append(kid) | ||
125 | break | 125 | break | ||
126 | 126 | ||||
127 | return critical_kids | 127 | return critical_kids |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|