Домашни > Хелоуин в Припят > Решения > Решението на Костадин Русалов

Резултати
9 точки от тестове
2 точки от учител

11 точки общо

11 успешни теста
1 неуспешни теста
Код

  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

Отвъд дребната забележка - добро, изчистено решение.
История

f1from collections import dequef1from collections import deque
22
33
4class Candy:4class 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 = mass7        self.mass = mass
8        self.uranium = uranium8        self.uranium = uranium
99
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.mass12        return self.mass
1313
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.mass16        return self.uranium * self.mass
nn17 
1718
18class Person:19class 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 = position22        self.position = position
2223
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.position26        return self.position
2627
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 = position30        self.position = position
3031
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]) ** 234        return ((other.position[0] - self.position[0]) ** 2
34                + (other.position[1] - self.position[1]) ** 2)35                + (other.position[1] - self.position[1]) ** 2)
3536
3637
37class Kid(Person):38class 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 = initiative42        self.initiative = initiative
42        self.bag = set()43        self.bag = set()
43        self._uranium_mass = 0.044        self._uranium_mass = 0.0
4445
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.initiative48        return self.initiative
4849
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)
5354
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 > 2057        return self._uranium_mass > 20
5758
5859
59class Host(Person):60class Host(Person):
n60    """A class that represents a host."""n61    """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)
6566
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            return70            return
70        candy = criterion(self.bag)71        candy = criterion(self.bag)
71        self.bag.remove(candy)72        self.bag.remove(candy)
72        return candy73        return candy
7374
7475
75class FluxCapacitor:76class FluxCapacitor:
76    """A class that simulates a Halloween night in Pripyat."""77    """A class that simulates a Halloween night in Pripyat."""
77    @staticmethod78    @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 - kids82        hosts = participants - kids
8283
83        host_paths = {}84        host_paths = {}
84        for host in hosts:85        for host in hosts:
n85            host_distances = [(host.sq_distance_to(other), other.position, other) for other in hosts]n86            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])
8889
89        paths = {}90        paths = {}
90        for kid in kids:91        for kid in kids:
n91            _, _, first_host = min([(kid.sq_distance_to(host), host.position, host) for host in hosts])n92            _, _, 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)
9495
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)
9798
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)
100101
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 = False105        has_victims = False
105106
n106        while self._path_len > 0:n107        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:
n108                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                    continue112                    continue
113113
nn114                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 = True118                    has_victims = True
118119
n119            self._path_len -= 1n
120            if has_victims:
121                break
122        return victims if has_victims else None120        return victims if has_victims else None
tt121 
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
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1from collections import dequef1from collections import deque
22
33
4class Candy:4class 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 = mass7        self.mass = mass
8        self.uranium = uranium8        self.uranium = uranium
99
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.mass12        return self.mass
1313
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.mass16        return self.uranium * self.mass
1717
18class Person:18class 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 = position21        self.position = position
2222
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.position25        return self.position
2626
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 = position29        self.position = position
3030
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]) ** 233        return ((other.position[0] - self.position[0]) ** 2
34                + (other.position[1] - self.position[1]) ** 2)34                + (other.position[1] - self.position[1]) ** 2)
3535
3636
37class Kid(Person):37class 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 = initiative41        self.initiative = initiative
42        self.bag = set()42        self.bag = set()
43        self._uranium_mass = 0.043        self._uranium_mass = 0.0
4444
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.initiative47        return self.initiative
4848
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)
5353
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."""
t56        return self._uranium_mass >= 20t56        return self._uranium_mass > 20
5757
5858
59class Host(Person):59class 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)
6565
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            return69            return
70        candy = criterion(self.bag)70        candy = criterion(self.bag)
71        self.bag.remove(candy)71        self.bag.remove(candy)
72        return candy72        return candy
7373
7474
75class FluxCapacitor:75class FluxCapacitor:
76    """A class that simulates a Halloween night in Pripyat."""76    """A class that simulates a Halloween night in Pripyat."""
77    @staticmethod77    @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 - kids81        hosts = participants - kids
8282
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])
8888
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)
9494
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)
9797
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)
100100
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 = False104        has_victims = False
105105
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                    continue112                    continue
113113
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 = True117                    has_victims = True
118118
119            self._path_len -= 1119            self._path_len -= 1
120            if has_victims:120            if has_victims:
121                break121                break
122        return victims if has_victims else None122        return victims if has_victims else None
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op