1class Candy:
2
3 def __init__(self, mass, uranium):
4 self.mass = mass
5 self.uranium = uranium
6
7 def get_uranium_quantity(self):
8 return self.mass * self.uranium
9
10 def get_mass(self):
11 return self.mass
12
13
14class Person:
15
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, new_position):
23 setattr(self, self.position, new_position)
24
25 def get_dist(self, other_person):
26 return ((self.position[0] - other_person.position[0])**2 + ((self.position[1] - other_person.position[1])**2))**(1/2)
27
28
29class Kid(Person):
30
31 def __init__(self, position, initiative):
32 super().__init__(position)
33 self.initiative = initiative
34 self.basket = []
35 self.hosts_to_visit = []
36 self.uranium_in_basket = 0
37
38 @staticmethod
39 def get_candy_with_most_mass(candys):
40 return max(candys, key=lambda c: c.mass)
41
42 def get_initiative(self):
43 return self.initiative
44
45 def add_candy(self, candy):
46 if candy is not None:
47 self.basket.append(candy)
48 self.uranium_in_basket += candy.get_uranium_quantity()
49
50 def is_critical(self):
51 return self.uranium_in_basket > 20
52
53 def fill_hosts_to_visit(self, hosts):
54 for host in hosts:
55 self.hosts_to_visit.append(host)
56
57 def go_to_closest_host(self):
58 if not self.hosts_to_visit:
59 return
60
61 min_dist = None
62 for host in self.hosts_to_visit:
63 if not min_dist:
64 min_dist = self.get_dist(self.hosts_to_visit[0])
65 min_dist_host = self.hosts_to_visit[0]
66 if (curr_dist := self.get_dist(host)) < min_dist:
67 min_dist = curr_dist
68 min_dist_host = host
69 elif (curr_dist := self.get_dist(host)) == min_dist:
70 if host.position[0] < min_dist_host.position[0]:
71 min_dist_host = host
72 elif host.position[0] == min_dist_host.position[0]:
73 if host.position[1] < min_dist_host.position[1]:
74 min_dist_host = host
75
76 self.add_candy(min_dist_host.remove_candy(Kid.get_candy_with_most_mass))
77 self.position = host.get_position()
78 self.hosts_to_visit.remove(host)
79
80
81class Host(Person):
82
83 def __init__(self, position, candies):
84 super().__init__(position)
85 self.candies = [Candy(*candy) for candy in candies]
86
87 def remove_candy(self, func):
88 if len(self.candies) == 0:
89 return None
90
91 candy = func(self.candies)
92 self.candies.remove(candy)
93 return candy
94
95
96class FluxCapacitor:
97
98 def __init__(self, participants):
99 self.kids = list(filter(lambda x: type(x) is Kid, participants))
100 self.hosts = list(filter(lambda x: type(x) is Host, participants))
101 self.kids.sort(reverse=True, key=lambda kid: kid.initiative)
102
103 def get_victim(self):
104
105 for kid in self.kids:
106 kid.fill_hosts_to_visit(self.hosts)
107
108 dead_children = set()
109 while True:
110 no_more_hosts_to_visit = True
111 for kid in self.kids:
112 if kid.hosts_to_visit:
113 no_more_hosts_to_visit = False
114 break
115
116 if no_more_hosts_to_visit:
117 return None
118
119 for kid in self.kids:
120 kid.go_to_closest_host()
121
122 for kid in self.kids:
123 if kid.is_critical():
124 dead_children.add(kid)
125
126 if len(dead_children) > 0:
127 return dead_children
...........E
======================================================================
ERROR: test_basic_usage (test.PersonTest)
Test basic usage of Person class.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 25, in test_basic_usage
person.set_position((2, 2))
File "/tmp/solution.py", line 23, in set_position
setattr(self, self.position, new_position)
TypeError: attribute name must be string, not 'tuple'
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (errors=1)
Георги Кунчев
07.11.2023 19:17Една бонус точка, защото аз съм подвел с моя коментар.
|
n | 1 | def get_candy_with_most_mass(candys): | n | ||
2 | return max(candys, key=lambda c: c.mass) | ||||
3 | |||||
4 | |||||
5 | class Candy: | 1 | class Candy: | ||
6 | 2 | ||||
7 | def __init__(self, mass, uranium): | 3 | def __init__(self, mass, uranium): | ||
8 | self.mass = mass | 4 | self.mass = mass | ||
9 | self.uranium = uranium | 5 | self.uranium = uranium | ||
10 | 6 | ||||
11 | def get_uranium_quantity(self): | 7 | def get_uranium_quantity(self): | ||
12 | return self.mass * self.uranium | 8 | return self.mass * self.uranium | ||
13 | 9 | ||||
14 | def get_mass(self): | 10 | def get_mass(self): | ||
15 | return self.mass | 11 | return self.mass | ||
16 | 12 | ||||
17 | 13 | ||||
18 | class Person: | 14 | class Person: | ||
19 | 15 | ||||
20 | def __init__(self, position): | 16 | def __init__(self, position): | ||
21 | self.position = position | 17 | self.position = position | ||
22 | 18 | ||||
23 | def get_position(self): | 19 | def get_position(self): | ||
24 | return self.position | 20 | return self.position | ||
25 | 21 | ||||
26 | def set_position(self, new_position): | 22 | def set_position(self, new_position): | ||
n | 27 | object.__setattr__(self, self.position, new_position) | n | 23 | setattr(self, self.position, new_position) |
28 | 24 | ||||
29 | def get_dist(self, other_person): | 25 | def get_dist(self, other_person): | ||
30 | return ((self.position[0] - other_person.position[0])**2 + ((self.position[1] - other_person.position[1])**2))**(1/2) | 26 | return ((self.position[0] - other_person.position[0])**2 + ((self.position[1] - other_person.position[1])**2))**(1/2) | ||
31 | 27 | ||||
32 | 28 | ||||
33 | class Kid(Person): | 29 | class Kid(Person): | ||
34 | 30 | ||||
35 | def __init__(self, position, initiative): | 31 | def __init__(self, position, initiative): | ||
36 | super().__init__(position) | 32 | super().__init__(position) | ||
37 | self.initiative = initiative | 33 | self.initiative = initiative | ||
38 | self.basket = [] | 34 | self.basket = [] | ||
39 | self.hosts_to_visit = [] | 35 | self.hosts_to_visit = [] | ||
n | n | 36 | self.uranium_in_basket = 0 | ||
40 | 37 | ||||
n | n | 38 | @staticmethod | ||
39 | def get_candy_with_most_mass(candys): | ||||
40 | return max(candys, key=lambda c: c.mass) | ||||
41 | |||||
41 | def get_initiative(self): | 42 | def get_initiative(self): | ||
42 | return self.initiative | 43 | return self.initiative | ||
43 | 44 | ||||
44 | def add_candy(self, candy): | 45 | def add_candy(self, candy): | ||
n | 45 | if(candy is not None): | n | 46 | if candy is not None: |
46 | self.basket.append(candy) | 47 | self.basket.append(candy) | ||
n | 47 | n | 48 | self.uranium_in_basket += candy.get_uranium_quantity() | |
49 | |||||
48 | def is_critical(self): | 50 | def is_critical(self): | ||
n | 49 | uranium_in_basket = 0 | n | ||
50 | for candy in self.basket: | ||||
51 | uranium_in_basket += candy.get_uranium_quantity() | ||||
52 | |||||
53 | return uranium_in_basket > 20 | 51 | return self.uranium_in_basket > 20 | ||
54 | 52 | ||||
55 | def fill_hosts_to_visit(self, hosts): | 53 | def fill_hosts_to_visit(self, hosts): | ||
56 | for host in hosts: | 54 | for host in hosts: | ||
57 | self.hosts_to_visit.append(host) | 55 | self.hosts_to_visit.append(host) | ||
58 | 56 | ||||
59 | def go_to_closest_host(self): | 57 | def go_to_closest_host(self): | ||
n | 60 | if len(self.hosts_to_visit) == 0: | n | 58 | if not self.hosts_to_visit: |
61 | return | ||||
62 | if len(self.hosts_to_visit) == 1: | ||||
63 | self.add_candy(self.hosts_to_visit[0].remove_candy(get_candy_with_most_mass)) | ||||
64 | self.position = self.hosts_to_visit[0].get_position() | ||||
65 | self.hosts_to_visit.pop(0) | ||||
66 | return | 59 | return | ||
67 | 60 | ||||
n | 68 | min_dist = self.get_dist(self.hosts_to_visit[0]) | n | 61 | min_dist = None |
69 | min_dist_host = self.hosts_to_visit[0] | ||||
70 | for host in self.hosts_to_visit[1:]: | 62 | for host in self.hosts_to_visit: | ||
63 | if not min_dist: | ||||
64 | min_dist = self.get_dist(self.hosts_to_visit[0]) | ||||
65 | min_dist_host = self.hosts_to_visit[0] | ||||
71 | if (curr_dist := self.get_dist(host)) < min_dist: | 66 | if (curr_dist := self.get_dist(host)) < min_dist: | ||
72 | min_dist = curr_dist | 67 | min_dist = curr_dist | ||
73 | min_dist_host = host | 68 | min_dist_host = host | ||
n | 74 | elif curr_dist := self.get_dist(host) == min_dist: | n | 69 | elif (curr_dist := self.get_dist(host)) == min_dist: |
75 | if host.position[0] < min_dist_host.position[0]: | 70 | if host.position[0] < min_dist_host.position[0]: | ||
76 | min_dist_host = host | 71 | min_dist_host = host | ||
77 | elif host.position[0] == min_dist_host.position[0]: | 72 | elif host.position[0] == min_dist_host.position[0]: | ||
78 | if host.position[1] < min_dist_host.position[1]: | 73 | if host.position[1] < min_dist_host.position[1]: | ||
79 | min_dist_host = host | 74 | min_dist_host = host | ||
80 | 75 | ||||
n | 81 | self.add_candy(min_dist_host.remove_candy(get_candy_with_most_mass)) | n | 76 | self.add_candy(min_dist_host.remove_candy(Kid.get_candy_with_most_mass)) |
82 | self.position = host.get_position() | 77 | self.position = host.get_position() | ||
83 | self.hosts_to_visit.remove(host) | 78 | self.hosts_to_visit.remove(host) | ||
84 | 79 | ||||
85 | 80 | ||||
86 | class Host(Person): | 81 | class Host(Person): | ||
87 | 82 | ||||
88 | def __init__(self, position, candies): | 83 | def __init__(self, position, candies): | ||
89 | super().__init__(position) | 84 | super().__init__(position) | ||
n | 90 | self.candies = [] | n | 85 | self.candies = [Candy(*candy) for candy in candies] |
91 | for (mass, uranium) in candies: | ||||
92 | candy = Candy(mass, uranium) | ||||
93 | self.candies.append(candy) | ||||
94 | 86 | ||||
95 | def remove_candy(self, func): | 87 | def remove_candy(self, func): | ||
96 | if len(self.candies) == 0: | 88 | if len(self.candies) == 0: | ||
97 | return None | 89 | return None | ||
98 | 90 | ||||
99 | candy = func(self.candies) | 91 | candy = func(self.candies) | ||
100 | self.candies.remove(candy) | 92 | self.candies.remove(candy) | ||
101 | return candy | 93 | return candy | ||
102 | 94 | ||||
103 | 95 | ||||
104 | class FluxCapacitor: | 96 | class FluxCapacitor: | ||
105 | 97 | ||||
106 | def __init__(self, participants): | 98 | def __init__(self, participants): | ||
n | 107 | self.participants = participants | n | 99 | self.kids = list(filter(lambda x: type(x) is Kid, participants)) |
100 | self.hosts = list(filter(lambda x: type(x) is Host, participants)) | ||||
101 | self.kids.sort(reverse=True, key=lambda kid: kid.initiative) | ||||
108 | 102 | ||||
109 | def get_victim(self): | 103 | def get_victim(self): | ||
n | 110 | kids = list(filter(lambda x: type(x) is Kid, self.participants)) | n | ||
111 | hosts = list(filter(lambda x: type(x) is Host, self.participants)) | ||||
112 | kids.sort(reverse=True, key=lambda kid: kid.initiative) | ||||
113 | 104 | ||||
n | 114 | for kid in kids: | n | 105 | for kid in self.kids: |
115 | kid.fill_hosts_to_visit(hosts) | 106 | kid.fill_hosts_to_visit(self.hosts) | ||
116 | 107 | ||||
117 | dead_children = set() | 108 | dead_children = set() | ||
118 | while True: | 109 | while True: | ||
119 | no_more_hosts_to_visit = True | 110 | no_more_hosts_to_visit = True | ||
n | 120 | for kid in kids: | n | 111 | for kid in self.kids: |
121 | if len(kid.hosts_to_visit) > 0: | 112 | if kid.hosts_to_visit: | ||
122 | no_more_hosts_to_visit = False | 113 | no_more_hosts_to_visit = False | ||
123 | break | 114 | break | ||
124 | 115 | ||||
125 | if no_more_hosts_to_visit: | 116 | if no_more_hosts_to_visit: | ||
126 | return None | 117 | return None | ||
127 | 118 | ||||
n | 128 | for kid in kids: | n | 119 | for kid in self.kids: |
129 | kid.go_to_closest_host() | 120 | kid.go_to_closest_host() | ||
130 | 121 | ||||
n | 131 | for kid in kids: | n | 122 | for kid in self.kids: |
132 | if kid.is_critical(): | 123 | if kid.is_critical(): | ||
133 | dead_children.add(kid) | 124 | dead_children.add(kid) | ||
134 | 125 | ||||
135 | if len(dead_children) > 0: | 126 | if len(dead_children) > 0: | ||
136 | return dead_children | 127 | return dead_children | ||
t | 137 | t |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | def get_candy_with_most_mass(candys): | f | 1 | def get_candy_with_most_mass(candys): |
2 | return max(candys, key=lambda c: c.mass) | 2 | return max(candys, key=lambda c: c.mass) | ||
3 | 3 | ||||
4 | 4 | ||||
5 | class Candy: | 5 | class Candy: | ||
6 | 6 | ||||
7 | def __init__(self, mass, uranium): | 7 | def __init__(self, mass, uranium): | ||
8 | self.mass = mass | 8 | self.mass = mass | ||
9 | self.uranium = uranium | 9 | self.uranium = uranium | ||
10 | 10 | ||||
11 | def get_uranium_quantity(self): | 11 | def get_uranium_quantity(self): | ||
12 | return self.mass * self.uranium | 12 | return self.mass * self.uranium | ||
13 | 13 | ||||
14 | def get_mass(self): | 14 | def get_mass(self): | ||
15 | return self.mass | 15 | return self.mass | ||
16 | 16 | ||||
17 | 17 | ||||
18 | class Person: | 18 | class Person: | ||
19 | 19 | ||||
20 | def __init__(self, position): | 20 | def __init__(self, position): | ||
21 | self.position = position | 21 | self.position = position | ||
22 | 22 | ||||
23 | def get_position(self): | 23 | def get_position(self): | ||
24 | return self.position | 24 | return self.position | ||
25 | 25 | ||||
26 | def set_position(self, new_position): | 26 | def set_position(self, new_position): | ||
27 | object.__setattr__(self, self.position, new_position) | 27 | object.__setattr__(self, self.position, new_position) | ||
28 | 28 | ||||
29 | def get_dist(self, other_person): | 29 | def get_dist(self, other_person): | ||
30 | return ((self.position[0] - other_person.position[0])**2 + ((self.position[1] - other_person.position[1])**2))**(1/2) | 30 | return ((self.position[0] - other_person.position[0])**2 + ((self.position[1] - other_person.position[1])**2))**(1/2) | ||
31 | 31 | ||||
32 | 32 | ||||
33 | class Kid(Person): | 33 | class Kid(Person): | ||
34 | 34 | ||||
35 | def __init__(self, position, initiative): | 35 | def __init__(self, position, initiative): | ||
36 | super().__init__(position) | 36 | super().__init__(position) | ||
37 | self.initiative = initiative | 37 | self.initiative = initiative | ||
38 | self.basket = [] | 38 | self.basket = [] | ||
39 | self.hosts_to_visit = [] | 39 | self.hosts_to_visit = [] | ||
40 | 40 | ||||
41 | def get_initiative(self): | 41 | def get_initiative(self): | ||
42 | return self.initiative | 42 | return self.initiative | ||
43 | 43 | ||||
44 | def add_candy(self, candy): | 44 | def add_candy(self, candy): | ||
45 | if(candy is not None): | 45 | if(candy is not None): | ||
46 | self.basket.append(candy) | 46 | self.basket.append(candy) | ||
47 | 47 | ||||
48 | def is_critical(self): | 48 | def is_critical(self): | ||
49 | uranium_in_basket = 0 | 49 | uranium_in_basket = 0 | ||
50 | for candy in self.basket: | 50 | for candy in self.basket: | ||
51 | uranium_in_basket += candy.get_uranium_quantity() | 51 | uranium_in_basket += candy.get_uranium_quantity() | ||
52 | 52 | ||||
53 | return uranium_in_basket > 20 | 53 | return uranium_in_basket > 20 | ||
54 | 54 | ||||
55 | def fill_hosts_to_visit(self, hosts): | 55 | def fill_hosts_to_visit(self, hosts): | ||
56 | for host in hosts: | 56 | for host in hosts: | ||
57 | self.hosts_to_visit.append(host) | 57 | self.hosts_to_visit.append(host) | ||
58 | 58 | ||||
59 | def go_to_closest_host(self): | 59 | def go_to_closest_host(self): | ||
60 | if len(self.hosts_to_visit) == 0: | 60 | if len(self.hosts_to_visit) == 0: | ||
61 | return | 61 | return | ||
62 | if len(self.hosts_to_visit) == 1: | 62 | if len(self.hosts_to_visit) == 1: | ||
63 | self.add_candy(self.hosts_to_visit[0].remove_candy(get_candy_with_most_mass)) | 63 | self.add_candy(self.hosts_to_visit[0].remove_candy(get_candy_with_most_mass)) | ||
n | n | 64 | self.position = self.hosts_to_visit[0].get_position() | ||
64 | self.hosts_to_visit.pop(0) | 65 | self.hosts_to_visit.pop(0) | ||
65 | return | 66 | return | ||
66 | 67 | ||||
67 | min_dist = self.get_dist(self.hosts_to_visit[0]) | 68 | min_dist = self.get_dist(self.hosts_to_visit[0]) | ||
68 | min_dist_host = self.hosts_to_visit[0] | 69 | min_dist_host = self.hosts_to_visit[0] | ||
69 | for host in self.hosts_to_visit[1:]: | 70 | for host in self.hosts_to_visit[1:]: | ||
70 | if (curr_dist := self.get_dist(host)) < min_dist: | 71 | if (curr_dist := self.get_dist(host)) < min_dist: | ||
71 | min_dist = curr_dist | 72 | min_dist = curr_dist | ||
72 | min_dist_host = host | 73 | min_dist_host = host | ||
73 | elif curr_dist := self.get_dist(host) == min_dist: | 74 | elif curr_dist := self.get_dist(host) == min_dist: | ||
74 | if host.position[0] < min_dist_host.position[0]: | 75 | if host.position[0] < min_dist_host.position[0]: | ||
75 | min_dist_host = host | 76 | min_dist_host = host | ||
76 | elif host.position[0] == min_dist_host.position[0]: | 77 | elif host.position[0] == min_dist_host.position[0]: | ||
77 | if host.position[1] < min_dist_host.position[1]: | 78 | if host.position[1] < min_dist_host.position[1]: | ||
78 | min_dist_host = host | 79 | min_dist_host = host | ||
79 | 80 | ||||
80 | self.add_candy(min_dist_host.remove_candy(get_candy_with_most_mass)) | 81 | self.add_candy(min_dist_host.remove_candy(get_candy_with_most_mass)) | ||
n | n | 82 | self.position = host.get_position() | ||
81 | self.hosts_to_visit.remove(host) | 83 | self.hosts_to_visit.remove(host) | ||
82 | 84 | ||||
83 | 85 | ||||
84 | class Host(Person): | 86 | class Host(Person): | ||
85 | 87 | ||||
86 | def __init__(self, position, candies): | 88 | def __init__(self, position, candies): | ||
87 | super().__init__(position) | 89 | super().__init__(position) | ||
88 | self.candies = [] | 90 | self.candies = [] | ||
89 | for (mass, uranium) in candies: | 91 | for (mass, uranium) in candies: | ||
90 | candy = Candy(mass, uranium) | 92 | candy = Candy(mass, uranium) | ||
91 | self.candies.append(candy) | 93 | self.candies.append(candy) | ||
92 | 94 | ||||
93 | def remove_candy(self, func): | 95 | def remove_candy(self, func): | ||
94 | if len(self.candies) == 0: | 96 | if len(self.candies) == 0: | ||
95 | return None | 97 | return None | ||
96 | 98 | ||||
97 | candy = func(self.candies) | 99 | candy = func(self.candies) | ||
98 | self.candies.remove(candy) | 100 | self.candies.remove(candy) | ||
99 | return candy | 101 | return candy | ||
100 | 102 | ||||
101 | 103 | ||||
102 | class FluxCapacitor: | 104 | class FluxCapacitor: | ||
103 | 105 | ||||
104 | def __init__(self, participants): | 106 | def __init__(self, participants): | ||
105 | self.participants = participants | 107 | self.participants = participants | ||
106 | 108 | ||||
107 | def get_victim(self): | 109 | def get_victim(self): | ||
108 | kids = list(filter(lambda x: type(x) is Kid, self.participants)) | 110 | kids = list(filter(lambda x: type(x) is Kid, self.participants)) | ||
109 | hosts = list(filter(lambda x: type(x) is Host, self.participants)) | 111 | hosts = list(filter(lambda x: type(x) is Host, self.participants)) | ||
110 | kids.sort(reverse=True, key=lambda kid: kid.initiative) | 112 | kids.sort(reverse=True, key=lambda kid: kid.initiative) | ||
111 | 113 | ||||
112 | for kid in kids: | 114 | for kid in kids: | ||
113 | kid.fill_hosts_to_visit(hosts) | 115 | kid.fill_hosts_to_visit(hosts) | ||
114 | 116 | ||||
115 | dead_children = set() | 117 | dead_children = set() | ||
116 | while True: | 118 | while True: | ||
117 | no_more_hosts_to_visit = True | 119 | no_more_hosts_to_visit = True | ||
118 | for kid in kids: | 120 | for kid in kids: | ||
119 | if len(kid.hosts_to_visit) > 0: | 121 | if len(kid.hosts_to_visit) > 0: | ||
120 | no_more_hosts_to_visit = False | 122 | no_more_hosts_to_visit = False | ||
121 | break | 123 | break | ||
122 | 124 | ||||
123 | if no_more_hosts_to_visit: | 125 | if no_more_hosts_to_visit: | ||
124 | return None | 126 | return None | ||
125 | 127 | ||||
126 | for kid in kids: | 128 | for kid in kids: | ||
127 | kid.go_to_closest_host() | 129 | kid.go_to_closest_host() | ||
128 | 130 | ||||
129 | for kid in kids: | 131 | for kid in kids: | ||
130 | if kid.is_critical(): | 132 | if kid.is_critical(): | ||
131 | dead_children.add(kid) | 133 | dead_children.add(kid) | ||
132 | 134 | ||||
133 | if len(dead_children) > 0: | 135 | if len(dead_children) > 0: | ||
134 | return dead_children | 136 | return dead_children | ||
135 | 137 | ||||
t | 136 | t |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|