1from collections import deque
2
3
4class Candy:
5 """A class that represents radioactive candy."""
6 def __init__(self, mass, uranium):
7 self.mass = mass
8 self.uranium = uranium
9
10 def get_mass(self):
11 """Return the mass of the candy."""
12 return self.mass
13
14 def get_uranium_quantity(self):
15 """Return the uranium mass in the candy."""
16 return self.uranium * self.mass
17
18
19class Person:
20 """A base class that represents a person from Pripyat."""
21 def __init__(self, position):
22 self.position = position
23
24 def get_position(self):
25 """Return the position of the person."""
26 return self.position
27
28 def set_position(self, position):
29 """Set the position of the person."""
30 self.position = position
31
32 def sq_distance_to(self, other):
33 """Return the square of the distance to another person."""
34 return ((other.position[0] - self.position[0]) ** 2
35 + (other.position[1] - self.position[1]) ** 2)
36
37
38class Kid(Person):
39 """A class that represents a kid from Pripyat."""
40 def __init__(self, position, initiative):
41 super().__init__(position)
42 self.initiative = initiative
43 self.bag = set()
44 self._uranium_mass = 0.0
45
46 def get_initiative(self):
47 """Return the initiative of a kid."""
48 return self.initiative
49
50 def add_candy(self, candy):
51 """Add candy into the bag."""
52 self._uranium_mass += candy.get_uranium_quantity()
53 self.bag.add(candy)
54
55 def is_critical(self):
56 """Return whether the mass of the uranium in the bag is critical."""
57 return self._uranium_mass > 20
58
59
60class Host(Person):
61 """A class that represents a host from Pripyat."""
62 def __init__(self, position, candies):
63 super().__init__(position)
64 self.bag = [Candy(mass, uranium) for mass, uranium in candies]
65 self.bag.sort(key=Candy.get_mass)
66
67 def remove_candy(self, criterion):
68 """Remove candy by criterion from a host's bag."""
69 if not self.bag:
70 return
71 candy = criterion(self.bag)
72 self.bag.remove(candy)
73 return candy
74
75
76class FluxCapacitor:
77 """A class that simulates a Halloween night in Pripyat."""
78 @staticmethod
79 def _draw_paths(participants):
80 """Return a dictionary of each kids' path of hosts and the number of hosts."""
81 kids = {person for person in participants if type(person) is Kid}
82 hosts = participants - kids
83
84 host_paths = {}
85 for host in hosts:
86 host_distances = [(host.sq_distance_to(other), other.position[0], other) for other in hosts]
87 host_distances.sort()
88 host_paths[host] = deque([host for _, _, host in host_distances])
89
90 paths = {}
91 for kid in kids:
92 _, _, first_host = min([(kid.sq_distance_to(host), host.position[0], host) for host in hosts])
93 paths[kid] = host_paths[first_host].copy()
94 return paths, len(hosts)
95
96 def __init__(self, participants):
97 self._paths, self._path_len = FluxCapacitor._draw_paths(participants)
98
99 self._kids_order = list(self._paths.keys())
100 self._kids_order.sort(key=Kid.get_initiative, reverse=True)
101
102 def get_victim(self):
103 """Return a set of the first kids whose candy have reached critical mass or None."""
104 victims = set()
105 has_victims = False
106
107 while self._path_len > 0 and not has_victims:
108 self._path_len -= 1
109 for kid in self._kids_order:
110 host = self._paths[kid].popleft()
111 if not host.bag:
112 continue
113
114 candy = host.bag.pop()
115 kid.add_candy(candy)
116 if kid.is_critical():
117 victims.add(kid)
118 has_victims = True
119
120 return victims if has_victims else None
121
122# the beef has just begun.
123# (Candy := type('Candy', (), {'__init__': lambda _, m, u: (setattr(_, 'm', m), setattr(_, 'u', u * m))[0],'get_mass': lambda _: _.m, 'get_uranium_quantity': lambda _: _.u}), Person := type('Person', (), {'__init__': lambda _, p: setattr(_, 'p', p), 'get_position': lambda _: _.p, 'set_position': lambda _, p: setattr(_, 'p', p), 't': lambda _, o: (o.p[0] - _.p[0]) ** 2 + (o.p[1] - _.p[1]) ** 2}), Kid := type('Kid', (Person,), {'__init__': lambda _, p, i: (Person.__init__(_, p), setattr(_, 'i', i), setattr(_, 'b', set()), setattr(_, 'u', 0.0))[0], 'get_initiative': lambda _: _.i, 'add_candy': lambda _, c: (setattr(_, 'u', _.u + c.u), _.b.add(c))[0], 'is_critical': lambda _: _.u > 20}), Host := type('Host', (Person,), {'__init__': lambda _, p, c: (Person.__init__(_, p), setattr(_, 'b', sorted([Candy(m, u) for m, u in c], key=Candy.get_mass)))[0], 'remove_candy': lambda _, f: (c := f(_.b), _.b.remove(c))[0] if _.b else None}), dp := lambda pp: (kk := {p for p in pp if type(p) is Kid}, hh := pp - kk, hp := {h: deque([h_[2] for h_ in sorted([(h.t(o), o.p[0], o) for o in hh])]) for h in hh}, {k: hp[min([(k.t(h), h.p[0], h) for h in hh])[2]].copy() for k in kk}, len(hh))[-2:], FluxCapacitor := type('FluxCapacitor', (), {'__init__': lambda _, p: (d := dp(p), setattr(_, 'p', d[0]), setattr(_, 'l', d[1]), setattr(_, 'o', sorted(list(_.p.keys()), key=Kid.get_initiative, reverse=True)))[1], 'get_victim': lambda _: (None, v)[v != 1] if (setattr(_, 'l', _.l - 1), v := {k for k in _.o if (k.add_candy(b.pop() if (b := _.p[k].popleft().b) else Candy(0, 0)), k.is_critical())[1]} if _.l >= 0 else 1)[1] else _.get_victim()}))
..E.........
======================================================================
ERROR: test_empty_hosts (test.FluxCapacitorTest)
Test with empty hosts.
----------------------------------------------------------------------
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 87, in test_empty_hosts
flux_capacitor = FluxCapacitor({kid1, kid2})
File "/tmp/solution.py", line 97, in __init__
self._paths, self._path_len = FluxCapacitor._draw_paths(participants)
File "/tmp/solution.py", line 92, in _draw_paths
_, _, first_host = min([(kid.sq_distance_to(host), host.position[0], host) for host in hosts])
ValueError: min() arg is an empty sequence
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (errors=1)
Костадин Русалов
07.11.2023 19:15В единия имаше грешен вход. (Другия кейс се надявах да не го тествате)
|
Виктор Бечев
07.11.2023 18:44Бонус и за телешкото. :D
П.П. Два теста не ти минават и на едноредката, по абсолютно същия начин.
|
Виктор Бечев
06.11.2023 14:10Отвъд дребната забележка - добро, изчистено решение.
|
f | 1 | from collections import deque | f | 1 | from collections import deque |
2 | 2 | ||||
3 | 3 | ||||
4 | class Candy: | 4 | class Candy: | ||
5 | """A class that represents radioactive candy.""" | 5 | """A class that represents radioactive candy.""" | ||
6 | def __init__(self, mass, uranium): | 6 | def __init__(self, mass, uranium): | ||
7 | self.mass = mass | 7 | self.mass = mass | ||
8 | self.uranium = uranium | 8 | self.uranium = uranium | ||
9 | 9 | ||||
10 | def get_mass(self): | 10 | def get_mass(self): | ||
11 | """Return the mass of the candy.""" | 11 | """Return the mass of the candy.""" | ||
12 | return self.mass | 12 | return self.mass | ||
13 | 13 | ||||
14 | def get_uranium_quantity(self): | 14 | def get_uranium_quantity(self): | ||
15 | """Return the uranium mass in the candy.""" | 15 | """Return the uranium mass in the candy.""" | ||
16 | return self.uranium * self.mass | 16 | return self.uranium * self.mass | ||
n | n | 17 | |||
17 | 18 | ||||
18 | class Person: | 19 | class Person: | ||
19 | """A base class that represents a person from Pripyat.""" | 20 | """A base class that represents a person from Pripyat.""" | ||
20 | def __init__(self, position): | 21 | def __init__(self, position): | ||
21 | self.position = position | 22 | self.position = position | ||
22 | 23 | ||||
23 | def get_position(self): | 24 | def get_position(self): | ||
24 | """Return the position of the person.""" | 25 | """Return the position of the person.""" | ||
25 | return self.position | 26 | return self.position | ||
26 | 27 | ||||
27 | def set_position(self, position): | 28 | def set_position(self, position): | ||
28 | """Set the position of the person.""" | 29 | """Set the position of the person.""" | ||
29 | self.position = position | 30 | self.position = position | ||
30 | 31 | ||||
31 | def sq_distance_to(self, other): | 32 | def sq_distance_to(self, other): | ||
32 | """Return the square of the distance to another person.""" | 33 | """Return the square of the distance to another person.""" | ||
33 | return ((other.position[0] - self.position[0]) ** 2 | 34 | return ((other.position[0] - self.position[0]) ** 2 | ||
34 | + (other.position[1] - self.position[1]) ** 2) | 35 | + (other.position[1] - self.position[1]) ** 2) | ||
35 | 36 | ||||
36 | 37 | ||||
37 | class Kid(Person): | 38 | class Kid(Person): | ||
38 | """A class that represents a kid from Pripyat.""" | 39 | """A class that represents a kid from Pripyat.""" | ||
39 | def __init__(self, position, initiative): | 40 | def __init__(self, position, initiative): | ||
40 | super().__init__(position) | 41 | super().__init__(position) | ||
41 | self.initiative = initiative | 42 | self.initiative = initiative | ||
42 | self.bag = set() | 43 | self.bag = set() | ||
43 | self._uranium_mass = 0.0 | 44 | self._uranium_mass = 0.0 | ||
44 | 45 | ||||
45 | def get_initiative(self): | 46 | def get_initiative(self): | ||
46 | """Return the initiative of a kid.""" | 47 | """Return the initiative of a kid.""" | ||
47 | return self.initiative | 48 | return self.initiative | ||
48 | 49 | ||||
49 | def add_candy(self, candy): | 50 | def add_candy(self, candy): | ||
50 | """Add candy into the bag.""" | 51 | """Add candy into the bag.""" | ||
51 | self._uranium_mass += candy.get_uranium_quantity() | 52 | self._uranium_mass += candy.get_uranium_quantity() | ||
52 | self.bag.add(candy) | 53 | self.bag.add(candy) | ||
53 | 54 | ||||
54 | def is_critical(self): | 55 | def is_critical(self): | ||
55 | """Return whether the mass of the uranium in the bag is critical.""" | 56 | """Return whether the mass of the uranium in the bag is critical.""" | ||
56 | return self._uranium_mass > 20 | 57 | return self._uranium_mass > 20 | ||
57 | 58 | ||||
58 | 59 | ||||
59 | class Host(Person): | 60 | class Host(Person): | ||
n | 60 | """A class that represents a host.""" | n | 61 | """A class that represents a host from Pripyat.""" |
61 | def __init__(self, position, candies): | 62 | def __init__(self, position, candies): | ||
62 | super().__init__(position) | 63 | super().__init__(position) | ||
63 | self.bag = [Candy(mass, uranium) for mass, uranium in candies] | 64 | self.bag = [Candy(mass, uranium) for mass, uranium in candies] | ||
64 | self.bag.sort(key=Candy.get_mass) | 65 | self.bag.sort(key=Candy.get_mass) | ||
65 | 66 | ||||
66 | def remove_candy(self, criterion): | 67 | def remove_candy(self, criterion): | ||
67 | """Remove candy by criterion from a host's bag.""" | 68 | """Remove candy by criterion from a host's bag.""" | ||
68 | if not self.bag: | 69 | if not self.bag: | ||
69 | return | 70 | return | ||
70 | candy = criterion(self.bag) | 71 | candy = criterion(self.bag) | ||
71 | self.bag.remove(candy) | 72 | self.bag.remove(candy) | ||
72 | return candy | 73 | return candy | ||
73 | 74 | ||||
74 | 75 | ||||
75 | class FluxCapacitor: | 76 | class FluxCapacitor: | ||
76 | """A class that simulates a Halloween night in Pripyat.""" | 77 | """A class that simulates a Halloween night in Pripyat.""" | ||
77 | @staticmethod | 78 | @staticmethod | ||
78 | def _draw_paths(participants): | 79 | def _draw_paths(participants): | ||
79 | """Return a dictionary of each kids' path of hosts and the number of hosts.""" | 80 | """Return a dictionary of each kids' path of hosts and the number of hosts.""" | ||
80 | kids = {person for person in participants if type(person) is Kid} | 81 | kids = {person for person in participants if type(person) is Kid} | ||
81 | hosts = participants - kids | 82 | hosts = participants - kids | ||
82 | 83 | ||||
83 | host_paths = {} | 84 | host_paths = {} | ||
84 | for host in hosts: | 85 | for host in hosts: | ||
n | 85 | host_distances = [(host.sq_distance_to(other), other.position, other) for other in hosts] | n | 86 | host_distances = [(host.sq_distance_to(other), other.position[0], other) for other in hosts] |
86 | host_distances.sort() | 87 | host_distances.sort() | ||
87 | host_paths[host] = deque([host for _, _, host in host_distances]) | 88 | host_paths[host] = deque([host for _, _, host in host_distances]) | ||
88 | 89 | ||||
89 | paths = {} | 90 | paths = {} | ||
90 | for kid in kids: | 91 | for kid in kids: | ||
n | 91 | _, _, first_host = min([(kid.sq_distance_to(host), host.position, host) for host in hosts]) | n | 92 | _, _, first_host = min([(kid.sq_distance_to(host), host.position[0], host) for host in hosts]) |
92 | paths[kid] = host_paths[first_host].copy() | 93 | paths[kid] = host_paths[first_host].copy() | ||
93 | return paths, len(hosts) | 94 | return paths, len(hosts) | ||
94 | 95 | ||||
95 | def __init__(self, participants): | 96 | def __init__(self, participants): | ||
96 | self._paths, self._path_len = FluxCapacitor._draw_paths(participants) | 97 | self._paths, self._path_len = FluxCapacitor._draw_paths(participants) | ||
97 | 98 | ||||
98 | self._kids_order = list(self._paths.keys()) | 99 | self._kids_order = list(self._paths.keys()) | ||
99 | self._kids_order.sort(key=Kid.get_initiative, reverse=True) | 100 | self._kids_order.sort(key=Kid.get_initiative, reverse=True) | ||
100 | 101 | ||||
101 | def get_victim(self): | 102 | def get_victim(self): | ||
102 | """Return a set of the first kids whose candy have reached critical mass or None.""" | 103 | """Return a set of the first kids whose candy have reached critical mass or None.""" | ||
103 | victims = set() | 104 | victims = set() | ||
104 | has_victims = False | 105 | has_victims = False | ||
105 | 106 | ||||
n | 106 | while self._path_len > 0: | n | 107 | while self._path_len > 0 and not has_victims: |
108 | self._path_len -= 1 | ||||
107 | for kid in self._kids_order: | 109 | for kid in self._kids_order: | ||
n | 108 | try: | n | ||
109 | host = self._paths[kid].popleft() | 110 | host = self._paths[kid].popleft() | ||
110 | candy = host.bag.pop() | 111 | if not host.bag: | ||
111 | except IndexError: | ||||
112 | continue | 112 | continue | ||
113 | 113 | ||||
n | n | 114 | candy = host.bag.pop() | ||
114 | kid.add_candy(candy) | 115 | kid.add_candy(candy) | ||
115 | if kid.is_critical(): | 116 | if kid.is_critical(): | ||
116 | victims.add(kid) | 117 | victims.add(kid) | ||
117 | has_victims = True | 118 | has_victims = True | ||
118 | 119 | ||||
n | 119 | self._path_len -= 1 | n | ||
120 | if has_victims: | ||||
121 | break | ||||
122 | return victims if has_victims else None | 120 | return victims if has_victims else None | ||
t | t | 121 | |||
122 | # the beef has just begun. | ||||
123 | # (Candy := type('Candy', (), {'__init__': lambda _, m, u: (setattr(_, 'm', m), setattr(_, 'u', u * m))[0],'get_mass': lambda _: _.m, 'get_uranium_quantity': lambda _: _.u}), Person := type('Person', (), {'__init__': lambda _, p: setattr(_, 'p', p), 'get_position': lambda _: _.p, 'set_position': lambda _, p: setattr(_, 'p', p), 't': lambda _, o: (o.p[0] - _.p[0]) ** 2 + (o.p[1] - _.p[1]) ** 2}), Kid := type('Kid', (Person,), {'__init__': lambda _, p, i: (Person.__init__(_, p), setattr(_, 'i', i), setattr(_, 'b', set()), setattr(_, 'u', 0.0))[0], 'get_initiative': lambda _: _.i, 'add_candy': lambda _, c: (setattr(_, 'u', _.u + c.u), _.b.add(c))[0], 'is_critical': lambda _: _.u > 20}), Host := type('Host', (Person,), {'__init__': lambda _, p, c: (Person.__init__(_, p), setattr(_, 'b', sorted([Candy(m, u) for m, u in c], key=Candy.get_mass)))[0], 'remove_candy': lambda _, f: (c := f(_.b), _.b.remove(c))[0] if _.b else None}), dp := lambda pp: (kk := {p for p in pp if type(p) is Kid}, hh := pp - kk, hp := {h: deque([h_[2] for h_ in sorted([(h.t(o), o.p[0], o) for o in hh])]) for h in hh}, {k: hp[min([(k.t(h), h.p[0], h) for h in hh])[2]].copy() for k in kk}, len(hh))[-2:], FluxCapacitor := type('FluxCapacitor', (), {'__init__': lambda _, p: (d := dp(p), setattr(_, 'p', d[0]), setattr(_, 'l', d[1]), setattr(_, 'o', sorted(list(_.p.keys()), key=Kid.get_initiative, reverse=True)))[1], 'get_victim': lambda _: (None, v)[v != 1] if (setattr(_, 'l', _.l - 1), v := {k for k in _.o if (k.add_candy(b.pop() if (b := _.p[k].popleft().b) else Candy(0, 0)), k.is_critical())[1]} if _.l >= 0 else 1)[1] else _.get_victim()})) |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | from collections import deque | f | 1 | from collections import deque |
2 | 2 | ||||
3 | 3 | ||||
4 | class Candy: | 4 | class Candy: | ||
5 | """A class that represents radioactive candy.""" | 5 | """A class that represents radioactive candy.""" | ||
6 | def __init__(self, mass, uranium): | 6 | def __init__(self, mass, uranium): | ||
7 | self.mass = mass | 7 | self.mass = mass | ||
8 | self.uranium = uranium | 8 | self.uranium = uranium | ||
9 | 9 | ||||
10 | def get_mass(self): | 10 | def get_mass(self): | ||
11 | """Return the mass of the candy.""" | 11 | """Return the mass of the candy.""" | ||
12 | return self.mass | 12 | return self.mass | ||
13 | 13 | ||||
14 | def get_uranium_quantity(self): | 14 | def get_uranium_quantity(self): | ||
15 | """Return the uranium mass in the candy.""" | 15 | """Return the uranium mass in the candy.""" | ||
16 | return self.uranium * self.mass | 16 | return self.uranium * self.mass | ||
17 | 17 | ||||
18 | class Person: | 18 | class Person: | ||
19 | """A base class that represents a person from Pripyat.""" | 19 | """A base class that represents a person from Pripyat.""" | ||
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 the position of the person.""" | 24 | """Return the position of the person.""" | ||
25 | return self.position | 25 | return self.position | ||
26 | 26 | ||||
27 | def set_position(self, position): | 27 | def set_position(self, position): | ||
28 | """Set the position of the person.""" | 28 | """Set the position of the person.""" | ||
29 | self.position = position | 29 | self.position = position | ||
30 | 30 | ||||
31 | def sq_distance_to(self, other): | 31 | def sq_distance_to(self, other): | ||
32 | """Return the square of the distance to another person.""" | 32 | """Return the square of the distance to another person.""" | ||
33 | return ((other.position[0] - self.position[0]) ** 2 | 33 | return ((other.position[0] - self.position[0]) ** 2 | ||
34 | + (other.position[1] - self.position[1]) ** 2) | 34 | + (other.position[1] - self.position[1]) ** 2) | ||
35 | 35 | ||||
36 | 36 | ||||
37 | class Kid(Person): | 37 | class Kid(Person): | ||
38 | """A class that represents a kid from Pripyat.""" | 38 | """A class that represents a kid from Pripyat.""" | ||
39 | def __init__(self, position, initiative): | 39 | def __init__(self, position, initiative): | ||
40 | super().__init__(position) | 40 | super().__init__(position) | ||
41 | self.initiative = initiative | 41 | self.initiative = initiative | ||
42 | self.bag = set() | 42 | self.bag = set() | ||
43 | self._uranium_mass = 0.0 | 43 | self._uranium_mass = 0.0 | ||
44 | 44 | ||||
45 | def get_initiative(self): | 45 | def get_initiative(self): | ||
46 | """Return the initiative of a kid.""" | 46 | """Return the initiative of a kid.""" | ||
47 | return self.initiative | 47 | return self.initiative | ||
48 | 48 | ||||
49 | def add_candy(self, candy): | 49 | def add_candy(self, candy): | ||
50 | """Add candy into the bag.""" | 50 | """Add candy into the bag.""" | ||
51 | self._uranium_mass += candy.get_uranium_quantity() | 51 | self._uranium_mass += candy.get_uranium_quantity() | ||
52 | self.bag.add(candy) | 52 | self.bag.add(candy) | ||
53 | 53 | ||||
54 | def is_critical(self): | 54 | def is_critical(self): | ||
55 | """Return whether the mass of the uranium in the bag is critical.""" | 55 | """Return whether the mass of the uranium in the bag is critical.""" | ||
t | 56 | return self._uranium_mass >= 20 | t | 56 | return self._uranium_mass > 20 |
57 | 57 | ||||
58 | 58 | ||||
59 | class Host(Person): | 59 | class Host(Person): | ||
60 | """A class that represents a host.""" | 60 | """A class that represents a host.""" | ||
61 | def __init__(self, position, candies): | 61 | def __init__(self, position, candies): | ||
62 | super().__init__(position) | 62 | super().__init__(position) | ||
63 | self.bag = [Candy(mass, uranium) for mass, uranium in candies] | 63 | self.bag = [Candy(mass, uranium) for mass, uranium in candies] | ||
64 | self.bag.sort(key=Candy.get_mass) | 64 | self.bag.sort(key=Candy.get_mass) | ||
65 | 65 | ||||
66 | def remove_candy(self, criterion): | 66 | def remove_candy(self, criterion): | ||
67 | """Remove candy by criterion from a host's bag.""" | 67 | """Remove candy by criterion from a host's bag.""" | ||
68 | if not self.bag: | 68 | if not self.bag: | ||
69 | return | 69 | return | ||
70 | candy = criterion(self.bag) | 70 | candy = criterion(self.bag) | ||
71 | self.bag.remove(candy) | 71 | self.bag.remove(candy) | ||
72 | return candy | 72 | return candy | ||
73 | 73 | ||||
74 | 74 | ||||
75 | class FluxCapacitor: | 75 | class FluxCapacitor: | ||
76 | """A class that simulates a Halloween night in Pripyat.""" | 76 | """A class that simulates a Halloween night in Pripyat.""" | ||
77 | @staticmethod | 77 | @staticmethod | ||
78 | def _draw_paths(participants): | 78 | def _draw_paths(participants): | ||
79 | """Return a dictionary of each kids' path of hosts and the number of hosts.""" | 79 | """Return a dictionary of each kids' path of hosts and the number of hosts.""" | ||
80 | kids = {person for person in participants if type(person) is Kid} | 80 | kids = {person for person in participants if type(person) is Kid} | ||
81 | hosts = participants - kids | 81 | hosts = participants - kids | ||
82 | 82 | ||||
83 | host_paths = {} | 83 | host_paths = {} | ||
84 | for host in hosts: | 84 | for host in hosts: | ||
85 | host_distances = [(host.sq_distance_to(other), other.position, other) for other in hosts] | 85 | host_distances = [(host.sq_distance_to(other), other.position, other) for other in hosts] | ||
86 | host_distances.sort() | 86 | host_distances.sort() | ||
87 | host_paths[host] = deque([host for _, _, host in host_distances]) | 87 | host_paths[host] = deque([host for _, _, host in host_distances]) | ||
88 | 88 | ||||
89 | paths = {} | 89 | paths = {} | ||
90 | for kid in kids: | 90 | for kid in kids: | ||
91 | _, _, first_host = min([(kid.sq_distance_to(host), host.position, host) for host in hosts]) | 91 | _, _, first_host = min([(kid.sq_distance_to(host), host.position, host) for host in hosts]) | ||
92 | paths[kid] = host_paths[first_host].copy() | 92 | paths[kid] = host_paths[first_host].copy() | ||
93 | return paths, len(hosts) | 93 | return paths, len(hosts) | ||
94 | 94 | ||||
95 | def __init__(self, participants): | 95 | def __init__(self, participants): | ||
96 | self._paths, self._path_len = FluxCapacitor._draw_paths(participants) | 96 | self._paths, self._path_len = FluxCapacitor._draw_paths(participants) | ||
97 | 97 | ||||
98 | self._kids_order = list(self._paths.keys()) | 98 | self._kids_order = list(self._paths.keys()) | ||
99 | self._kids_order.sort(key=Kid.get_initiative, reverse=True) | 99 | self._kids_order.sort(key=Kid.get_initiative, reverse=True) | ||
100 | 100 | ||||
101 | def get_victim(self): | 101 | def get_victim(self): | ||
102 | """Return a set of the first kids whose candy have reached critical mass or None.""" | 102 | """Return a set of the first kids whose candy have reached critical mass or None.""" | ||
103 | victims = set() | 103 | victims = set() | ||
104 | has_victims = False | 104 | has_victims = False | ||
105 | 105 | ||||
106 | while self._path_len > 0: | 106 | while self._path_len > 0: | ||
107 | for kid in self._kids_order: | 107 | for kid in self._kids_order: | ||
108 | try: | 108 | try: | ||
109 | host = self._paths[kid].popleft() | 109 | host = self._paths[kid].popleft() | ||
110 | candy = host.bag.pop() | 110 | candy = host.bag.pop() | ||
111 | except IndexError: | 111 | except IndexError: | ||
112 | continue | 112 | continue | ||
113 | 113 | ||||
114 | kid.add_candy(candy) | 114 | kid.add_candy(candy) | ||
115 | if kid.is_critical(): | 115 | if kid.is_critical(): | ||
116 | victims.add(kid) | 116 | victims.add(kid) | ||
117 | has_victims = True | 117 | has_victims = True | ||
118 | 118 | ||||
119 | self._path_len -= 1 | 119 | self._path_len -= 1 | ||
120 | if has_victims: | 120 | if has_victims: | ||
121 | break | 121 | break | ||
122 | return victims if has_victims else None | 122 | return victims if has_victims else None |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|