1import math
2
3class Candy:
4 def __init__(self, mass, uranium):
5 self.mass = mass
6 self.uranium = uranium
7
8 def get_uranium_quantity(self):
9 return self.mass * self.uranium
10
11 def get_mass(self):
12 return self.mass
13
14
15class Person:
16 def __init__(self, position):
17 self.position = position
18
19 def get_position(self):
20 return self.position
21
22 def set_position(self, position):
23 self.position = position
24
25
26class Kid(Person):
27
28 MAX_URANIUM_QUANTITY = 20
29
30 def __init__(self, position, initiative):
31 super().__init__(position)
32 self.initiative = initiative
33 self.visited_hosts = []
34 self.basket = []
35
36 def get_initiative(self):
37 return self.initiative
38
39 def add_candy(self, candy):
40 self.basket.append(candy)
41
42 def if_host_visited(self, host):
43 found = False
44 for visited_host in self.visited_hosts:
45 if visited_host == host:
46 found = True
47 break
48
49 return found
50
51 def is_critical(self):
52 uranium_quantity = 0
53
54 for candy in self.basket:
55 uranium_quantity = uranium_quantity + candy.get_uranium_quantity()
56
57 return uranium_quantity > self.MAX_URANIUM_QUANTITY
58
59
60class Host(Person):
61
62 def __init__(self, position, candies = []):
63 super().__init__(position)
64 self.candies = []
65 for tup in candies:
66 self.candies.append(Candy(tup[0], tup[1]))
67
68 def remove_candy(self, func):
69
70 if not self.candies:
71 return None
72
73 candy_to_remove = func(self.candies)
74 self.candies.remove(candy_to_remove)
75
76 return candy_to_remove
77
78 def add_host(self, host):
79 self.visited_hosts.append(host)
80
81
82
83
84
85class FluxCapacitor:
86
87 def __init__(self, participants):
88 self.participants = participants
89
90 def __remove_biggest_mass_candy(self, candies):
91 return max(candies, key=lambda candy: candy.get_mass())
92
93 def __get_closest_host(self, hosts, kid):
94 closest_host = None
95 min_distance = float('inf')
96
97 for host in hosts:
98
99 if kid.if_host_visited(host):
100 continue
101
102 xi, yi = host.get_position()
103 x1, y1 = kid.get_position()
104 distance = math.sqrt((x1 - xi)**2 + (y1 - yi)**2)
105 if distance < min_distance:
106 min_distance = distance
107 closest_host = host
108 elif min_distance == distance and closest_host is not None:
109 if host.get_position[0] < closest_host.get_position[0]:
110 closest_host = host
111 elif host.get_position[0] == closest_host.get_position[0] and host.get_position[1] < closest_host.get_position[1]:
112 closest_host = host
113
114 return closest_host
115
116 def get_kids_critical(self, kids):
117
118 result = []
119
120 for kid in kids:
121 if kid.is_critical():
122 result.append(kid)
123
124 return result
125
126 def get_victim(self):
127
128 kids = set()
129 hosts = set()
130
131 for participant in self.participants:
132 if isinstance(participant, Kid):
133 kids.add(participant)
134 else:
135 hosts.add(participant)
136
137 counter_to_finish = 0
138 while True:
139 counter_to_finish = counter_to_finish + 1
140 for kid in kids:
141 host = self.__get_closest_host(hosts, kid)
142
143 if host is not None:
144 candy = host.remove_candy(self.__remove_biggest_mass_candy)
145 if candy is not None:
146 kid.add_candy(candy)
147
148 result = self.get_kids_critical(kids)
149 if result:
150 return result
151 else:
152 counter = 0
153 for kid in kids:
154 if len(kid.visited_hosts) == len(hosts):
155 counter = counter + 1
156
157 if counter == len(kids) or counter_to_finish == len(hosts):
158 return None
159
160
161
162candy = Candy(20, 1.2)
163person = Person((1, 2))
164kid = Kid((0, 0), 123)
165host = Host((3, 4), [(100, 1.0), (200, 0.5)])
166flux_capacitor = FluxCapacitor({kid, host})
167flux_capacitor.get_victim()
.....F......
======================================================================
FAIL: test_real_case (test.FluxCapacitorTest)
Test with real case.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/timeout_decorator/timeout_decorator.py", line 82, in new_function
return function(*args, **kwargs)
File "/tmp/test.py", line 115, in test_real_case
self.assertEqual(FluxCapacitor({kid1, kid2, host1, host2}).get_victim(), {kid1, kid2})
AssertionError: [<solution.Kid object at 0x7f2e758114e0>,[36 chars]3f0>] != {<solution.Kid object at 0x7f2e758114e0>,[36 chars]3f0>}
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (failures=1)
Георги Кунчев
07.11.2023 14:06Да. Минават тестове за сигнатурата на домашното. Целта е да ти подскажем, ако не си използвала правилното име на клас/функция. Повече инфо:
[тук](/info/code)
|
Адем Црънчалиев
07.11.2023 14:01А когато пуснем някое решение, минават ли някакви нулеви тестове?
|
Георги Кунчев
07.11.2023 13:17За жалост - не. Доста от логиката ти липсва. Трябва да имаш обхождане на деца по хостове, раздаване на лакомства, проверка за критична маса... Аз не виждам нищо от тези неща в имплементацията.
|
Адем Црънчалиев
07.11.2023 13:05Кое не е довършено? Не е ли изпълнено FluxCapacitor както трябва?
|
n | n | 1 | import math | ||
2 | |||||
1 | class Candy: | 3 | class Candy: | ||
2 | def __init__(self, mass, uranium): | 4 | def __init__(self, mass, uranium): | ||
3 | self.mass = mass | 5 | self.mass = mass | ||
4 | self.uranium = uranium | 6 | self.uranium = uranium | ||
5 | 7 | ||||
6 | def get_uranium_quantity(self): | 8 | def get_uranium_quantity(self): | ||
7 | return self.mass * self.uranium | 9 | return self.mass * self.uranium | ||
8 | 10 | ||||
9 | def get_mass(self): | 11 | def get_mass(self): | ||
10 | return self.mass | 12 | return self.mass | ||
11 | 13 | ||||
12 | 14 | ||||
13 | class Person: | 15 | class Person: | ||
14 | def __init__(self, position): | 16 | def __init__(self, position): | ||
15 | self.position = position | 17 | self.position = position | ||
16 | 18 | ||||
17 | def get_position(self): | 19 | def get_position(self): | ||
18 | return self.position | 20 | return self.position | ||
19 | 21 | ||||
20 | def set_position(self, position): | 22 | def set_position(self, position): | ||
21 | self.position = position | 23 | self.position = position | ||
22 | 24 | ||||
23 | 25 | ||||
24 | class Kid(Person): | 26 | class Kid(Person): | ||
25 | 27 | ||||
n | 26 | max_uranium_quantity = 20 | n | 28 | MAX_URANIUM_QUANTITY = 20 |
27 | 29 | ||||
28 | def __init__(self, position, initiative): | 30 | def __init__(self, position, initiative): | ||
29 | super().__init__(position) | 31 | super().__init__(position) | ||
30 | self.initiative = initiative | 32 | self.initiative = initiative | ||
n | n | 33 | self.visited_hosts = [] | ||
31 | self.basket = [] | 34 | self.basket = [] | ||
32 | 35 | ||||
33 | def get_initiative(self): | 36 | def get_initiative(self): | ||
34 | return self.initiative | 37 | return self.initiative | ||
35 | 38 | ||||
36 | def add_candy(self, candy): | 39 | def add_candy(self, candy): | ||
37 | self.basket.append(candy) | 40 | self.basket.append(candy) | ||
n | n | 41 | |||
42 | def if_host_visited(self, host): | ||||
43 | found = False | ||||
44 | for visited_host in self.visited_hosts: | ||||
45 | if visited_host == host: | ||||
46 | found = True | ||||
47 | break | ||||
48 | |||||
49 | return found | ||||
38 | 50 | ||||
39 | def is_critical(self): | 51 | def is_critical(self): | ||
40 | uranium_quantity = 0 | 52 | uranium_quantity = 0 | ||
41 | 53 | ||||
n | 42 | for candy in basket: | n | 54 | for candy in self.basket: |
43 | uranium_quantity = uranium_quantity + candy.get_uranium_quantity() | 55 | uranium_quantity = uranium_quantity + candy.get_uranium_quantity() | ||
44 | 56 | ||||
n | 45 | return uranium_quantity > max_uranium_quantity | n | 57 | return uranium_quantity > self.MAX_URANIUM_QUANTITY |
46 | 58 | ||||
47 | 59 | ||||
48 | class Host(Person): | 60 | class Host(Person): | ||
49 | 61 | ||||
50 | def __init__(self, position, candies = []): | 62 | def __init__(self, position, candies = []): | ||
51 | super().__init__(position) | 63 | super().__init__(position) | ||
52 | self.candies = [] | 64 | self.candies = [] | ||
53 | for tup in candies: | 65 | for tup in candies: | ||
54 | self.candies.append(Candy(tup[0], tup[1])) | 66 | self.candies.append(Candy(tup[0], tup[1])) | ||
55 | 67 | ||||
56 | def remove_candy(self, func): | 68 | def remove_candy(self, func): | ||
57 | 69 | ||||
58 | if not self.candies: | 70 | if not self.candies: | ||
59 | return None | 71 | return None | ||
60 | 72 | ||||
61 | candy_to_remove = func(self.candies) | 73 | candy_to_remove = func(self.candies) | ||
62 | self.candies.remove(candy_to_remove) | 74 | self.candies.remove(candy_to_remove) | ||
63 | 75 | ||||
64 | return candy_to_remove | 76 | return candy_to_remove | ||
65 | 77 | ||||
n | n | 78 | def add_host(self, host): | ||
79 | self.visited_hosts.append(host) | ||||
80 | |||||
81 | |||||
82 | |||||
66 | 83 | ||||
67 | 84 | ||||
68 | class FluxCapacitor: | 85 | class FluxCapacitor: | ||
69 | 86 | ||||
70 | def __init__(self, participants): | 87 | def __init__(self, participants): | ||
71 | self.participants = participants | 88 | self.participants = participants | ||
n | n | 89 | |||
90 | def __remove_biggest_mass_candy(self, candies): | ||||
91 | return max(candies, key=lambda candy: candy.get_mass()) | ||||
92 | |||||
93 | def __get_closest_host(self, hosts, kid): | ||||
94 | closest_host = None | ||||
95 | min_distance = float('inf') | ||||
96 | |||||
97 | for host in hosts: | ||||
98 | |||||
99 | if kid.if_host_visited(host): | ||||
100 | continue | ||||
101 | |||||
102 | xi, yi = host.get_position() | ||||
103 | x1, y1 = kid.get_position() | ||||
104 | distance = math.sqrt((x1 - xi)**2 + (y1 - yi)**2) | ||||
105 | if distance < min_distance: | ||||
106 | min_distance = distance | ||||
107 | closest_host = host | ||||
108 | elif min_distance == distance and closest_host is not None: | ||||
109 | if host.get_position[0] < closest_host.get_position[0]: | ||||
110 | closest_host = host | ||||
111 | elif host.get_position[0] == closest_host.get_position[0] and host.get_position[1] < closest_host.get_position[1]: | ||||
112 | closest_host = host | ||||
113 | |||||
114 | return closest_host | ||||
72 | 115 | ||||
n | 73 | def get_victim(): | n | 116 | def get_kids_critical(self, kids): |
117 | |||||
118 | result = [] | ||||
119 | |||||
120 | for kid in kids: | ||||
121 | if kid.is_critical(): | ||||
122 | result.append(kid) | ||||
74 | 123 | ||||
n | n | 124 | return result | ||
125 | |||||
126 | def get_victim(self): | ||||
127 | |||||
128 | kids = set() | ||||
75 | result = set() | 129 | hosts = set() | ||
76 | 130 | ||||
n | 77 | for participant in participants: | n | 131 | for participant in self.participants: |
78 | if isinstance(participant, Kid) and participant.is_critical(): | 132 | if isinstance(participant, Kid): | ||
133 | kids.add(participant) | ||||
134 | else: | ||||
79 | result.add(participant) | 135 | hosts.add(participant) | ||
80 | 136 | ||||
n | 81 | if result: | n | 137 | counter_to_finish = 0 |
82 | return result | 138 | while True: | ||
83 | else: | 139 | counter_to_finish = counter_to_finish + 1 | ||
84 | return None | 140 | for kid in kids: | ||
141 | host = self.__get_closest_host(hosts, kid) | ||||
85 | 142 | ||||
n | n | 143 | if host is not None: | ||
144 | candy = host.remove_candy(self.__remove_biggest_mass_candy) | ||||
145 | if candy is not None: | ||||
146 | kid.add_candy(candy) | ||||
147 | |||||
148 | result = self.get_kids_critical(kids) | ||||
149 | if result: | ||||
150 | return result | ||||
151 | else: | ||||
152 | counter = 0 | ||||
153 | for kid in kids: | ||||
154 | if len(kid.visited_hosts) == len(hosts): | ||||
155 | counter = counter + 1 | ||||
156 | |||||
157 | if counter == len(kids) or counter_to_finish == len(hosts): | ||||
158 | return None | ||||
159 | |||||
160 | |||||
161 | |||||
86 | candy = Candy(20, 0.3) | 162 | candy = Candy(20, 1.2) | ||
87 | person = Person((1, 2)) | 163 | person = Person((1, 2)) | ||
88 | kid = Kid((0, 0), 123) | 164 | kid = Kid((0, 0), 123) | ||
n | 89 | host = Host((3, 4), [(1, 1.0), (2, 0.5)]) | n | 165 | host = Host((3, 4), [(100, 1.0), (200, 0.5)]) |
90 | flux_capacitor = FluxCapacitor({kid, host}) | 166 | flux_capacitor = FluxCapacitor({kid, host}) | ||
t | t | 167 | flux_capacitor.get_victim() |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | class Candy: | f | 1 | class Candy: |
2 | def __init__(self, mass, uranium): | 2 | def __init__(self, mass, uranium): | ||
3 | self.mass = mass | 3 | self.mass = mass | ||
4 | self.uranium = uranium | 4 | self.uranium = uranium | ||
5 | 5 | ||||
6 | def get_uranium_quantity(self): | 6 | def get_uranium_quantity(self): | ||
7 | return self.mass * self.uranium | 7 | return self.mass * self.uranium | ||
8 | 8 | ||||
9 | def get_mass(self): | 9 | def get_mass(self): | ||
10 | return self.mass | 10 | return self.mass | ||
11 | 11 | ||||
12 | 12 | ||||
13 | class Person: | 13 | class Person: | ||
14 | def __init__(self, position): | 14 | def __init__(self, position): | ||
15 | self.position = position | 15 | self.position = position | ||
16 | 16 | ||||
17 | def get_position(self): | 17 | def get_position(self): | ||
18 | return self.position | 18 | return self.position | ||
19 | 19 | ||||
20 | def set_position(self, position): | 20 | def set_position(self, position): | ||
21 | self.position = position | 21 | self.position = position | ||
22 | 22 | ||||
23 | 23 | ||||
24 | class Kid(Person): | 24 | class Kid(Person): | ||
25 | 25 | ||||
26 | max_uranium_quantity = 20 | 26 | max_uranium_quantity = 20 | ||
27 | 27 | ||||
28 | def __init__(self, position, initiative): | 28 | def __init__(self, position, initiative): | ||
29 | super().__init__(position) | 29 | super().__init__(position) | ||
30 | self.initiative = initiative | 30 | self.initiative = initiative | ||
31 | self.basket = [] | 31 | self.basket = [] | ||
32 | 32 | ||||
33 | def get_initiative(self): | 33 | def get_initiative(self): | ||
34 | return self.initiative | 34 | return self.initiative | ||
35 | 35 | ||||
36 | def add_candy(self, candy): | 36 | def add_candy(self, candy): | ||
t | 37 | self.basket.push(candy) | t | 37 | self.basket.append(candy) |
38 | 38 | ||||
39 | def is_critical(self): | 39 | def is_critical(self): | ||
40 | uranium_quantity = 0 | 40 | uranium_quantity = 0 | ||
41 | 41 | ||||
42 | for candy in basket: | 42 | for candy in basket: | ||
43 | uranium_quantity = uranium_quantity + candy.get_uranium_quantity() | 43 | uranium_quantity = uranium_quantity + candy.get_uranium_quantity() | ||
44 | 44 | ||||
45 | return uranium_quantity > max_uranium_quantity | 45 | return uranium_quantity > max_uranium_quantity | ||
46 | 46 | ||||
47 | 47 | ||||
48 | class Host(Person): | 48 | class Host(Person): | ||
49 | 49 | ||||
50 | def __init__(self, position, candies = []): | 50 | def __init__(self, position, candies = []): | ||
51 | super().__init__(position) | 51 | super().__init__(position) | ||
52 | self.candies = [] | 52 | self.candies = [] | ||
53 | for tup in candies: | 53 | for tup in candies: | ||
54 | self.candies.append(Candy(tup[0], tup[1])) | 54 | self.candies.append(Candy(tup[0], tup[1])) | ||
55 | 55 | ||||
56 | def remove_candy(self, func): | 56 | def remove_candy(self, func): | ||
57 | 57 | ||||
58 | if not self.candies: | 58 | if not self.candies: | ||
59 | return None | 59 | return None | ||
60 | 60 | ||||
61 | candy_to_remove = func(self.candies) | 61 | candy_to_remove = func(self.candies) | ||
62 | self.candies.remove(candy_to_remove) | 62 | self.candies.remove(candy_to_remove) | ||
63 | 63 | ||||
64 | return candy_to_remove | 64 | return candy_to_remove | ||
65 | 65 | ||||
66 | 66 | ||||
67 | 67 | ||||
68 | class FluxCapacitor: | 68 | class FluxCapacitor: | ||
69 | 69 | ||||
70 | def __init__(self, participants): | 70 | def __init__(self, participants): | ||
71 | self.participants = participants | 71 | self.participants = participants | ||
72 | 72 | ||||
73 | def get_victim(): | 73 | def get_victim(): | ||
74 | 74 | ||||
75 | result = set() | 75 | result = set() | ||
76 | 76 | ||||
77 | for participant in participants: | 77 | for participant in participants: | ||
78 | if isinstance(participant, Kid) and participant.is_critical(): | 78 | if isinstance(participant, Kid) and participant.is_critical(): | ||
79 | result.add(participant) | 79 | result.add(participant) | ||
80 | 80 | ||||
81 | if result: | 81 | if result: | ||
82 | return result | 82 | return result | ||
83 | else: | 83 | else: | ||
84 | return None | 84 | return None | ||
85 | 85 | ||||
86 | candy = Candy(20, 0.3) | 86 | candy = Candy(20, 0.3) | ||
87 | person = Person((1, 2)) | 87 | person = Person((1, 2)) | ||
88 | kid = Kid((0, 0), 123) | 88 | kid = Kid((0, 0), 123) | ||
89 | host = Host((3, 4), [(1, 1.0), (2, 0.5)]) | 89 | host = Host((3, 4), [(1, 1.0), (2, 0.5)]) | ||
90 | flux_capacitor = FluxCapacitor({kid, host}) | 90 | flux_capacitor = FluxCapacitor({kid, host}) |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|