1class Candy:
2 def __init__(self, mass, uranium):
3 self.mass = mass
4 self.uranium = uranium
5
6 def get_uranium_quantity(self):
7 return self.mass * self.uranium
8
9 def get_mass(self):
10 return self.mass
11
12
13class Person:
14 def __init__(self, position):
15 self.position = position
16
17 def get_position(self):
18 return self.position
19
20 def set_position(self, new_position):
21 self.position = new_position
22
23
24class Kid(Person):
25 THRESHOLD_URANIUM = 20
26
27 def __init__(self, position, initiative):
28 super().__init__(position)
29 self.initiative = initiative
30 self.candy_basket = []
31 self.visited_hosts = set()
32
33 def get_initiative(self):
34 return self.initiative
35
36 def add_candy(self, candy):
37 self.candy_basket.append(candy)
38
39 def add_host(self, host):
40 self.visited_hosts.add(host)
41
42 def is_critical(self):
43 total_uranium = sum(candy.get_uranium_quantity() for candy in self.candy_basket)
44 return total_uranium > self.THRESHOLD_URANIUM
45
46
47class Host(Person):
48 def __init__(self, position, candies):
49 super().__init__(position)
50 self.candy_basket = [Candy(*candy) for candy in candies]
51
52 def remove_candy(self, selection_function):
53 if self.candy_basket:
54 selected_candy = selection_function(self.candy_basket)
55 self.candy_basket.remove(selected_candy)
56 return selected_candy
57 else:
58 return None
59
60
61def find_closest_host(kid, hosts):
62 closest_host = None
63 min_distance = float('inf')
64
65 for host in hosts:
66 if host not in kid.visited_hosts and host.candy_basket:
67 distance = abs(host.get_position()[0] - kid.get_position()[0]) + abs(host.get_position()[1] - kid.get_position()[1])
68 if distance < min_distance:
69 min_distance = distance
70 closest_host = host
71 elif distance == min_distance:
72 if host.get_position()[0] < closest_host.get_position()[0]:
73 closest_host = host
74 elif host.get_position()[0] == closest_host.get_position()[0] and host.get_position()[1] < closest_host.get_position()[1]:
75 closest_host = host
76
77 return closest_host
78
79
80class FluxCapacitor:
81
82 def __init__(self, participants):
83 self.participants = participants
84 self.kids = [participant for participant in participants if isinstance(participant, Kid)]
85 self.hosts = [participant for participant in participants if isinstance(participant, Host)]
86
87 @staticmethod
88 def select_max_mass_candy(candies):
89 return max(candies, key=lambda candy: candy.get_mass())
90
91 def get_victim(self):
92
93 victims = set()
94
95 while True:
96
97 if all(len(kid.visited_hosts) == len(self.hosts) for kid in self.kids):
98 return None
99
100 for kid in self.kids:
101 closest_host = find_closest_host(kid, self.hosts)
102
103 if closest_host:
104 candy = closest_host.remove_candy(self.select_max_mass_candy)
105 if candy:
106 kid.add_candy(candy)
107 kid.add_host(closest_host)
108 kid.set_position(closest_host.get_position())
109
110 if kid.is_critical():
111 victims.add(kid)
112
113 if not victims:
114 continue
115 else:
116 return victims
117
....F.......
======================================================================
FAIL: test_no_candies (test.FluxCapacitorTest)
Test with no candies.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/timeout_decorator/timeout_decorator.py", line 82, in new_function
return function(*args, **kwargs)
File "/tmp/test.py", line 106, in test_no_candies
self.assertEqual(flux_capacitor.get_victim(), None)
File "/tmp/solution.py", line 101, in get_victim
closest_host = find_closest_host(kid, self.hosts)
File "/tmp/solution.py", line 61, in find_closest_host
def find_closest_host(kid, hosts):
File "/usr/local/lib/python3.10/dist-packages/timeout_decorator/timeout_decorator.py", line 69, in handler
_raise_exception(timeout_exception, exception_message)
File "/usr/local/lib/python3.10/dist-packages/timeout_decorator/timeout_decorator.py", line 45, in _raise_exception
raise exception()
timeout_decorator.timeout_decorator.TimeoutError: 'Timed Out'
----------------------------------------------------------------------
Ran 12 tests in 0.201s
FAILED (failures=1)
Георги Кунчев
07.11.2023 11:25Поради проблемите, свързани с безкрайни цикли в някои от тестовете, добавихме подобрение на сайта, така че той вече ще отрази точките на всички останали тестове.
Ако имаш безкраен цикъл за някой тест кейс, той ще касае само него и все пак ще получиш точки за остнаалите си тестове.
|
Габриела Костева
07.11.2023 10:44Изтествах и случая, в който трябва да върне None и също нямам безкраен цикъл
|
Георги Кунчев
07.11.2023 10:26Ако ти дам, ще е нечестно спрямо останалите :(.
Виж граничните стойности
|
Габриела Костева
07.11.2023 10:23Аз пробвах този случай:
k1 = Kid((1, 1), 1)
k2 = Kid((-8, 2), -5)
k4 = Kid((14, -7), 12)
k5 = Kid((5, 9), 2)
h1 = Host((0, 0), [(5.2, 0.2), (1.2, 0.1111), (4.3333, 0.78592), (2.1, 0.3), (3.2, 0.4),
(5.2, 0.2), (1.2, 0.1111), (4.3333, 0.78592), (2.1, 0.3), (3.2, 0.4)])
h2 = Host((21, 5), [(12.4, 0.5), (8.3, 0.999), (3.257849, 0.12345), (1.2, 0.2), (2.1, 0.3),
(3.2, 0.4), (12.4, 0.5), (8.3, 0.999), (3.257849, 0.12345)])
h3 = Host((-13, 2), [(11, 0.2), (4.43432, 0.7), (9.123, 1), (1.2, 1), (2.1, 1),
(3.2, 0.99), (3.2, 1), (3.2, 1), (3.2, 1), (3.2, 1), ])
h4 = Host((0, 0), [(5.2, 0.2), (1.2, 0.1111), (4.3333, 0.78592), (2.1, 0.3), (3.2, 0.4),
(5.2, 0.2), (1.2, 0.1111), (4.3333, 0.78592), (2.1, 0.3), (3.2, 0.4)])
h5 = Host((21, 5), [(12.4, 0.5), (8.3, 0.999), (3.257849, 0.12345), (1.2, 0.2), (2.1, 0.3),
(3.2, 0.4), (12.4, 0.5), (8.3, 0.999), (3.257849, 0.12345)])
h6 = Host((-13, 2), [(11, 0.2), (4.43432, 0.7), (9.123, 1), (1.2, 1), (2.1, 1),
(3.2, 0.99), (3.2, 1), (3.2, 1), (3.2, 1), (3.2, 1), ])
people = {k1, h3, h2, k5, h4, h5, h6, h1, k4, k2}
fc = FluxCapacitor(people)
while (output := fc.get_victim()) is not None:
print(output);
и ми изкарва този резултат:
{<__main__.Kid object at 0x7faf0e714e90>, <__main__.Kid object at 0x7faf0e714d10>, <__main__.Kid object at 0x7faf0e714050>}
{<__main__.Kid object at 0x7faf0e714e90>, <__main__.Kid object at 0x7faf0e714d10>, <__main__.Kid object at 0x7faf0e714050>}
{<__main__.Kid object at 0x7faf0e714050>}, но безкраен цикъл не съм удряла. Може ли да ми дадеш един примерен вход, в който се случва това
|
Георги Кунчев
07.11.2023 08:57Имаш безкраен цикъл, заради който тестовете ни ще зависнат и няма д аполучиш точки. Моля изтествай с реален случай. Преди последната промяна беше добре.
|
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, new_position): | 20 | def set_position(self, new_position): | ||
21 | self.position = new_position | 21 | self.position = new_position | ||
22 | 22 | ||||
23 | 23 | ||||
24 | class Kid(Person): | 24 | class Kid(Person): | ||
25 | THRESHOLD_URANIUM = 20 | 25 | THRESHOLD_URANIUM = 20 | ||
26 | 26 | ||||
27 | def __init__(self, position, initiative): | 27 | def __init__(self, position, initiative): | ||
28 | super().__init__(position) | 28 | super().__init__(position) | ||
29 | self.initiative = initiative | 29 | self.initiative = initiative | ||
30 | self.candy_basket = [] | 30 | self.candy_basket = [] | ||
31 | self.visited_hosts = set() | 31 | self.visited_hosts = set() | ||
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): | ||
37 | self.candy_basket.append(candy) | 37 | self.candy_basket.append(candy) | ||
38 | 38 | ||||
39 | def add_host(self, host): | 39 | def add_host(self, host): | ||
40 | self.visited_hosts.add(host) | 40 | self.visited_hosts.add(host) | ||
41 | 41 | ||||
42 | def is_critical(self): | 42 | def is_critical(self): | ||
43 | total_uranium = sum(candy.get_uranium_quantity() for candy in self.candy_basket) | 43 | total_uranium = sum(candy.get_uranium_quantity() for candy in self.candy_basket) | ||
44 | return total_uranium > self.THRESHOLD_URANIUM | 44 | return total_uranium > self.THRESHOLD_URANIUM | ||
45 | 45 | ||||
46 | 46 | ||||
47 | class Host(Person): | 47 | class Host(Person): | ||
48 | def __init__(self, position, candies): | 48 | def __init__(self, position, candies): | ||
49 | super().__init__(position) | 49 | super().__init__(position) | ||
50 | self.candy_basket = [Candy(*candy) for candy in candies] | 50 | self.candy_basket = [Candy(*candy) for candy in candies] | ||
51 | 51 | ||||
52 | def remove_candy(self, selection_function): | 52 | def remove_candy(self, selection_function): | ||
53 | if self.candy_basket: | 53 | if self.candy_basket: | ||
54 | selected_candy = selection_function(self.candy_basket) | 54 | selected_candy = selection_function(self.candy_basket) | ||
55 | self.candy_basket.remove(selected_candy) | 55 | self.candy_basket.remove(selected_candy) | ||
56 | return selected_candy | 56 | return selected_candy | ||
57 | else: | 57 | else: | ||
58 | return None | 58 | return None | ||
59 | 59 | ||||
60 | 60 | ||||
61 | def find_closest_host(kid, hosts): | 61 | def find_closest_host(kid, hosts): | ||
62 | closest_host = None | 62 | closest_host = None | ||
63 | min_distance = float('inf') | 63 | min_distance = float('inf') | ||
64 | 64 | ||||
65 | for host in hosts: | 65 | for host in hosts: | ||
n | 66 | if host not in kid.visited_hosts: | n | 66 | if host not in kid.visited_hosts and host.candy_basket: |
67 | distance = abs(host.get_position()[0] - kid.get_position()[0]) + abs(host.get_position()[1] - kid.get_position()[1]) | 67 | distance = abs(host.get_position()[0] - kid.get_position()[0]) + abs(host.get_position()[1] - kid.get_position()[1]) | ||
68 | if distance < min_distance: | 68 | if distance < min_distance: | ||
69 | min_distance = distance | 69 | min_distance = distance | ||
70 | closest_host = host | 70 | closest_host = host | ||
71 | elif distance == min_distance: | 71 | elif distance == min_distance: | ||
72 | if host.get_position()[0] < closest_host.get_position()[0]: | 72 | if host.get_position()[0] < closest_host.get_position()[0]: | ||
73 | closest_host = host | 73 | closest_host = host | ||
74 | elif host.get_position()[0] == closest_host.get_position()[0] and host.get_position()[1] < closest_host.get_position()[1]: | 74 | elif host.get_position()[0] == closest_host.get_position()[0] and host.get_position()[1] < closest_host.get_position()[1]: | ||
75 | closest_host = host | 75 | closest_host = host | ||
76 | 76 | ||||
77 | return closest_host | 77 | return closest_host | ||
78 | 78 | ||||
79 | 79 | ||||
80 | class FluxCapacitor: | 80 | class FluxCapacitor: | ||
n | n | 81 | |||
81 | def __init__(self, participants): | 82 | def __init__(self, participants): | ||
82 | self.participants = participants | 83 | self.participants = participants | ||
83 | self.kids = [participant for participant in participants if isinstance(participant, Kid)] | 84 | self.kids = [participant for participant in participants if isinstance(participant, Kid)] | ||
84 | self.hosts = [participant for participant in participants if isinstance(participant, Host)] | 85 | self.hosts = [participant for participant in participants if isinstance(participant, Host)] | ||
85 | 86 | ||||
86 | @staticmethod | 87 | @staticmethod | ||
87 | def select_max_mass_candy(candies): | 88 | def select_max_mass_candy(candies): | ||
88 | return max(candies, key=lambda candy: candy.get_mass()) | 89 | return max(candies, key=lambda candy: candy.get_mass()) | ||
89 | 90 | ||||
90 | def get_victim(self): | 91 | def get_victim(self): | ||
91 | 92 | ||||
92 | victims = set() | 93 | victims = set() | ||
93 | 94 | ||||
94 | while True: | 95 | while True: | ||
n | n | 96 | |||
97 | if all(len(kid.visited_hosts) == len(self.hosts) for kid in self.kids): | ||||
98 | return None | ||||
95 | 99 | ||||
96 | for kid in self.kids: | 100 | for kid in self.kids: | ||
n | 97 | while len(kid.visited_hosts) is not len(self.hosts): | n | ||
98 | closest_host = find_closest_host(kid, self.hosts) | 101 | closest_host = find_closest_host(kid, self.hosts) | ||
99 | 102 | ||||
n | 100 | if closest_host: | n | 103 | if closest_host: |
101 | candy = closest_host.remove_candy(self.select_max_mass_candy) | 104 | candy = closest_host.remove_candy(self.select_max_mass_candy) | ||
102 | if candy: | 105 | if candy: | ||
103 | kid.add_candy(candy) | 106 | kid.add_candy(candy) | ||
104 | kid.add_host(closest_host) | 107 | kid.add_host(closest_host) | ||
105 | kid.set_position(closest_host.get_position()) | 108 | kid.set_position(closest_host.get_position()) | ||
106 | 109 | ||||
107 | if kid.is_critical(): | 110 | if kid.is_critical(): | ||
108 | victims.add(kid) | 111 | victims.add(kid) | ||
n | 109 | break | n | ||
110 | 112 | ||||
111 | if not victims: | 113 | if not victims: | ||
n | 112 | return None | n | 114 | continue |
113 | else: | 115 | else: | ||
114 | return victims | 116 | return victims | ||
t | t | 117 |
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, new_position): | 20 | def set_position(self, new_position): | ||
21 | self.position = new_position | 21 | self.position = new_position | ||
22 | 22 | ||||
23 | 23 | ||||
24 | class Kid(Person): | 24 | class Kid(Person): | ||
n | n | 25 | THRESHOLD_URANIUM = 20 | ||
26 | |||||
25 | def __init__(self, position, initiative): | 27 | def __init__(self, position, initiative): | ||
26 | super().__init__(position) | 28 | super().__init__(position) | ||
27 | self.initiative = initiative | 29 | self.initiative = initiative | ||
28 | self.candy_basket = [] | 30 | self.candy_basket = [] | ||
n | n | 31 | self.visited_hosts = set() | ||
29 | 32 | ||||
30 | def get_initiative(self): | 33 | def get_initiative(self): | ||
31 | return self.initiative | 34 | return self.initiative | ||
32 | 35 | ||||
33 | def add_candy(self, candy): | 36 | def add_candy(self, candy): | ||
34 | self.candy_basket.append(candy) | 37 | self.candy_basket.append(candy) | ||
35 | 38 | ||||
n | n | 39 | def add_host(self, host): | ||
40 | self.visited_hosts.add(host) | ||||
41 | |||||
36 | def is_critical(self): | 42 | def is_critical(self): | ||
37 | total_uranium = sum(candy.get_uranium_quantity() for candy in self.candy_basket) | 43 | total_uranium = sum(candy.get_uranium_quantity() for candy in self.candy_basket) | ||
n | 38 | return total_uranium > 20 | n | 44 | return total_uranium > self.THRESHOLD_URANIUM |
39 | 45 | ||||
40 | 46 | ||||
41 | class Host(Person): | 47 | class Host(Person): | ||
42 | def __init__(self, position, candies): | 48 | def __init__(self, position, candies): | ||
43 | super().__init__(position) | 49 | super().__init__(position) | ||
n | 44 | self.candy_basket = [] | n | 50 | self.candy_basket = [Candy(*candy) for candy in candies] |
45 | |||||
46 | for candy_data in candies: | ||||
47 | mass, uranium = candy_data | ||||
48 | candy = Candy(mass, uranium) | ||||
49 | self.candy_basket.append(candy) | ||||
50 | 51 | ||||
51 | def remove_candy(self, selection_function): | 52 | def remove_candy(self, selection_function): | ||
52 | if self.candy_basket: | 53 | if self.candy_basket: | ||
53 | selected_candy = selection_function(self.candy_basket) | 54 | selected_candy = selection_function(self.candy_basket) | ||
54 | self.candy_basket.remove(selected_candy) | 55 | self.candy_basket.remove(selected_candy) | ||
55 | return selected_candy | 56 | return selected_candy | ||
56 | else: | 57 | else: | ||
57 | return None | 58 | return None | ||
58 | 59 | ||||
59 | 60 | ||||
n | n | 61 | def find_closest_host(kid, hosts): | ||
62 | closest_host = None | ||||
63 | min_distance = float('inf') | ||||
64 | |||||
65 | for host in hosts: | ||||
66 | if host not in kid.visited_hosts: | ||||
67 | distance = abs(host.get_position()[0] - kid.get_position()[0]) + abs(host.get_position()[1] - kid.get_position()[1]) | ||||
68 | if distance < min_distance: | ||||
69 | min_distance = distance | ||||
70 | closest_host = host | ||||
71 | elif distance == min_distance: | ||||
72 | if host.get_position()[0] < closest_host.get_position()[0]: | ||||
73 | closest_host = host | ||||
74 | elif host.get_position()[0] == closest_host.get_position()[0] and host.get_position()[1] < closest_host.get_position()[1]: | ||||
75 | closest_host = host | ||||
76 | |||||
77 | return closest_host | ||||
78 | |||||
79 | |||||
60 | class FluxCapacitor: | 80 | class FluxCapacitor: | ||
61 | def __init__(self, participants): | 81 | def __init__(self, participants): | ||
62 | self.participants = participants | 82 | self.participants = participants | ||
n | n | 83 | self.kids = [participant for participant in participants if isinstance(participant, Kid)] | ||
84 | self.hosts = [participant for participant in participants if isinstance(participant, Host)] | ||||
85 | |||||
86 | @staticmethod | ||||
87 | def select_max_mass_candy(candies): | ||||
88 | return max(candies, key=lambda candy: candy.get_mass()) | ||||
63 | 89 | ||||
64 | def get_victim(self): | 90 | def get_victim(self): | ||
n | 65 | kids = [participant for participant in self.participants if isinstance(participant, Kid)] | n | ||
66 | hosts = [participant for participant in self.participants if isinstance(participant, Host)] | ||||
67 | 91 | ||||
68 | victims = set() | 92 | victims = set() | ||
69 | 93 | ||||
70 | while True: | 94 | while True: | ||
n | 71 | for kid in kids: | n | ||
72 | if not kid.candy_basket: | ||||
73 | continue | ||||
74 | 95 | ||||
n | 75 | closest_host = min( | n | 96 | for kid in self.kids: |
76 | (host for host in hosts if host.candy_basket), | 97 | while len(kid.visited_hosts) is not len(self.hosts): | ||
77 | key=lambda host: abs(host.get_position()[0] - kid.get_position()[0]) + abs( | 98 | closest_host = find_closest_host(kid, self.hosts) | ||
78 | host.get_position()[1] - kid.get_position()[1]) | ||||
79 | ) | ||||
80 | 99 | ||||
n | n | 100 | if closest_host: | ||
81 | candy = closest_host.remove_candy(select_max_mass_candy) | 101 | candy = closest_host.remove_candy(self.select_max_mass_candy) | ||
82 | if candy: | 102 | if candy: | ||
83 | kid.add_candy(candy) | 103 | kid.add_candy(candy) | ||
104 | kid.add_host(closest_host) | ||||
105 | kid.set_position(closest_host.get_position()) | ||||
84 | 106 | ||||
n | 85 | for kid in kids: | n | ||
86 | if kid.is_critical(): | 107 | if kid.is_critical(): | ||
87 | victims.add(kid) | 108 | victims.add(kid) | ||
109 | break | ||||
88 | 110 | ||||
t | 89 | all_visited = all(not kid.candy_basket for kid in kids) | t | 111 | if not victims: |
90 | if all_visited: | ||||
91 | break | 112 | return None | ||
92 | 113 | else: | |||
93 | return victims | 114 | return victims | ||
94 | |||||
95 | |||||
96 | def select_max_mass_candy(candies): | ||||
97 | return max(candies, key=lambda candy: candy.get_mass()) | ||||
98 | |||||
99 | |||||
100 | if __name__ == '__main__': | ||||
101 | candy = Candy(20, 0.3) | ||||
102 | person = Person((1, 2)) | ||||
103 | kid = Kid((0, 0), 123) | ||||
104 | host = Host((3, 4), [(1, 1.0), (2, 0.5)]) | ||||
105 | flux_capacitor = FluxCapacitor({kid, host}) | ||||
106 | flux_capacitor.get_victim() |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|