import operator from itertools import pairwise, groupby def cas_za_povezavo(povezava, pribitki): return 4 + sum(pribitki[vescina] for vescina in zemljevid[povezava]) def cas(pot, pribitki): return sum(cas_za_povezavo(povezava, pribitki) for povezava in pairwise(pot)) def povezava_spotike(pribitki): return max(reversed(zemljevid), key=lambda povezava: cas_za_povezavo(povezava, pribitki)) def urnik(pot, pribitki): cas_od_zacetka = 0 urnik_dict = dict() urnik_dict[pot[0]] = 0 for povezava in pairwise(pot): cas_od_zacetka += cas_za_povezavo(povezava, pribitki) if povezava[1] not in urnik_dict: urnik_dict[povezava[1]] = cas_od_zacetka return urnik_dict def skupinski_sport(pot, pribitkii): return sum(max(cas_za_povezavo(povezava, pribitki) for pribitki in pribitkii) for povezava in pairwise(pot)) def tekma(pot, pribitkii): _, kol = min( [(k, list(v)) for k, v in groupby(sorted(((i, sum(cas_za_povezavo(povezava, pribitki) for povezava in pairwise(pot))) for i, pribitki in enumerate(pribitkii)), key=operator.itemgetter(1)), key=operator.itemgetter(1))], key=lambda x: x[0]) if len(kol) > 1: return None return kol[0][0] def cas_za_povezavo_trening(povezava, pribitki): s = 4 for vescina in zemljevid[povezava]: s += pribitki[vescina] pribitki[vescina] *= 0.95 return s def trening(pot, pribitki): return sum(cas_za_povezavo_trening(povezava, pribitki) for povezava in pairwise(pot)) def zastavice(pot, pribitkii): tocke = dict() for i, pribitki in enumerate(pribitkii): for tocka, time in urnik(pot, pribitki).items(): if tocka in tocke: (_, prev_time) = tocke[tocka] if prev_time <= time: continue tocke[tocka] = (i, time) return [len([i for a, _ in tocke.values() if a == i]) for i, _ in enumerate(pribitkii)] def najkrajsa_povezava(tocka, prejsnja, pribitki): povezave = [povezava for povezava in zemljevid if povezava[0] == tocka and povezava[1] != prejsnja] return min(povezave, key=lambda povezava: cas_za_povezavo(povezava, pribitki)) def cikel(zacetna_tocka, pribitki): prevozene = [] tocka = zacetna_tocka prejsnja = None while True: povezava = najkrajsa_povezava(tocka, prejsnja, pribitki) if povezava in prevozene: return len(prevozene) - prevozene.index(povezava) prevozene.append(povezava) prejsnja = tocka tocka = povezava[1] def urnik2(pot, pribitki): cas_od_zacetka = 0 urnik_list = [(pot[0], 0)] for povezava in pairwise(pot): cas_od_zacetka += cas_za_povezavo(povezava, pribitki) urnik_list.append((povezava[1], cas_od_zacetka)) return urnik_list def izpadanje(poti, pribitkii): timetable = dict() for kolesar, pot in enumerate(poti): for tocka, time in urnik2(pot, pribitkii[kolesar]): if time not in timetable: timetable[time] = dict() if tocka not in timetable[time]: timetable[time][tocka] = set() timetable[time][tocka].add(kolesar) pobrane = set() izpadli = [] for time, tocke in sorted(timetable.items()): for tocka, kolesarji in tocke.items(): # Odstrani kolesarje, ki so že izpadli kolesarji = [kolesar for kolesar in kolesarji if kolesar not in izpadli] if len(kolesarji) == 0: # Ni kolesarja, ki bi pobral zastavico (vsi so izpadli) continue if tocka in pobrane: # Izpadejo vsi na tej točki izpadli.extend(kolesarji) else: # Poberi zastavico pobrane.add(tocka) # Dodaj točko v pobrane zastavice izpadli.extend(kolesarji[1:]) # Izpadi vse kolesarje razen prvega return izpadli import unittest A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, R, S, T, U, V = "ABCDEFGHIJKLMNOPRSTUV" zemljevid = { (A, B): {'trava', 'gravel'}, (B, A): {'trava', 'gravel'}, (A, V): {'lonci', 'pešci'}, (V, A): {'lonci', 'pešci'}, (B, C): {'lonci', 'bolt'}, (C, B): {'lonci', 'bolt'}, (B, V): set(), (V, B): set(), (C, R): {'lonci', 'pešci', 'stopnice'}, (R, C): {'lonci', 'pešci', 'stopnice'}, (D, F): {'pešci', 'stopnice'}, (F, D): {'pešci', 'stopnice'}, (D, R): {'pešci'}, (R, D): {'pešci'}, (E, I): {'lonci', 'trava'}, (I, E): {'lonci', 'trava'}, (F, G): {'črepinje', 'trava'}, (G, F): {'črepinje', 'trava'}, (G, H): {'pešci', 'črepinje'}, (H, G): {'pešci', 'črepinje'}, (G, I): {'avtocesta'}, (I, G): {'avtocesta'}, (H, J): {'bolt', 'robnik'}, (J, H): {'bolt', 'robnik'}, (I, M): {'avtocesta'}, (M, I): {'avtocesta'}, (I, P): {'gravel'}, (P, I): {'gravel'}, (I, R): {'stopnice', 'robnik'}, (R, I): {'stopnice', 'robnik'}, (J, K): set(), (K, J): set(), (J, L): {'bolt', 'gravel'}, (L, J): {'bolt', 'gravel'}, (K, M): {'bolt', 'stopnice'}, (M, K): {'bolt', 'stopnice'}, (L, M): {'pešci', 'robnik'}, (M, L): {'pešci', 'robnik'}, (M, N): {'rodeo'}, (N, M): {'rodeo'}, (N, P): {'gravel'}, (P, N): {'gravel'}, (O, P): {'gravel'}, (P, O): {'gravel'}, (P, S): set(), (S, P): set(), (R, U): {'pešci', 'trava'}, (U, R): {'pešci', 'trava'}, (R, V): {'lonci', 'pešci'}, (V, R): {'lonci', 'pešci'}, (S, T): {'robnik', 'trava'}, (T, S): {'robnik', 'trava'}, (T, U): {'trava', 'gravel'}, (U, T): {'trava', 'gravel'}, (U, V): {'lonci', 'robnik', 'trava'}, (V, U): {'lonci', 'robnik', 'trava'} } pribitki1 = dict(gravel=2, trava=3, lonci=1, bolt=2, pešci=4, stopnice=3, avtocesta=5, črepinje=1, robnik=1, rodeo=4) pribitki2 = dict(gravel=2, trava=3, lonci=1, bolt=100, pešci=4, stopnice=3, avtocesta=5, črepinje=1, robnik=1, rodeo=4) pribitki3 = dict(gravel=2, trava=3, lonci=100, bolt=2, pešci=4, stopnice=3, avtocesta=5, črepinje=1, robnik=1, rodeo=4) pribitki4 = dict(gravel=2, trava=3, lonci=1, bolt=2, pešci=100, stopnice=3, avtocesta=5, črepinje=1, robnik=1, rodeo=4) class Test06(unittest.TestCase): def test_01_cas_za_povezavo(self): self.assertEqual(4 + 1 + 2, cas_za_povezavo((A, B), dict(gravel=1, trava=2, robnik=3, avtocesta=5, bolt=2))) self.assertEqual(4 + 2 + 2, cas_za_povezavo((H, J), dict(gravel=1, trava=2, robnik=2, avtocesta=5, bolt=2))) self.assertEqual(4 + 5, cas_za_povezavo((G, I), dict(gravel=1, trava=2, robnik=3, avtocesta=5, bolt=2))) self.assertEqual(4, cas_za_povezavo((S, P), dict(gravel=1, trava=2, robnik=3, avtocesta=5, bolt=2))) self.assertEqual(4 + 2 + 3, cas_za_povezavo((A, B), pribitki1)) self.assertEqual(4 + 2 + 1, cas_za_povezavo((B, C), pribitki1)) self.assertEqual(4 + 3 + 5, cas_za_povezavo((C, R), pribitki1)) self.assertEqual(4 + 4, cas_za_povezavo((R, D), pribitki1)) self.assertEqual(4 + 3 + 4, cas_za_povezavo((D, F), pribitki1)) self.assertEqual(4 + 3 + 1, cas_za_povezavo((F, G), pribitki1)) def test_02_cas(self): self.assertEqual(9 + 7 + 3 * 12 + 8 + 11 + 8, cas("ABCRCRDFG", pribitki1)) self.assertEqual(9, cas("AB", pribitki1)) self.assertEqual(7, cas("AB", dict(gravel=1, trava=2, robnik=3, avtocesta=5, bolt=2))) self.assertEqual(7 + 21, cas("ABC", dict(gravel=1, trava=2, robnik=3, avtocesta=5, bolt=2, lonci=15))) self.assertEqual(8, cas("SPS", dict(gravel=1, trava=2, robnik=3, avtocesta=5, bolt=2, lonci=15))) def test_03_povezava_spotike(self): self.assertEqual((R, C), povezava_spotike(pribitki1)) pribitki = pribitki1.copy() pribitki["avtocesta"] = 100 self.assertEqual((M, I), povezava_spotike(pribitki)) pribitki = dict.fromkeys(pribitki1, 0) # vsi pribitki so 0, razen: pribitki["staopnice"] = pribitki["bolt"] = 1 self.assertEqual((M, K), povezava_spotike(pribitki)) class Test07(unittest.TestCase): def test_01_urnik(self): self.assertEqual(dict(A=0, B=9, C=16, R=28, D=60, F=71, G=79), urnik("ABCRCRDFG", pribitki1)) pribitki = dict.fromkeys(pribitki1, 0) # vsi pribitki so 0, razen: self.assertEqual(dict(A=0, B=4, C=8, R=12, D=24, F=28, G=32), urnik("ABCRCRDFG", pribitki)) pribitki["lonci"] = 1 self.assertEqual(dict(A=0, B=4, C=9, R=14, D=28, F=32, G=36), urnik("ABCRCRDFG", pribitki)) def test_02_skupinski_sport(self): self.assertEqual(9 + 7 + 3 * 12 + 8 + 11 + 8, skupinski_sport("ABCRCRDFG", [pribitki1])) self.assertEqual(177, skupinski_sport("ABCRCRDFG", [pribitki1, pribitki2])) self.assertEqual(177, skupinski_sport("ABCRCRDFG", [pribitki1, pribitki2, pribitki2])) self.assertEqual(475, skupinski_sport("ABCRCRDFG", [pribitki1, pribitki2, pribitki2, pribitki3])) def test_03_tekma(self): # pribitki1 je hitrejši od pribitki2, pribitki2 je hitrejši od pribitki3 self.assertEqual(0, tekma("ABCRDF", [pribitki2])) self.assertEqual(0, tekma("ABCRDF", [pribitki2, pribitki3])) self.assertEqual(1, tekma("ABCRDF", [pribitki3, pribitki2])) self.assertEqual(2, tekma("ABCRDF", [pribitki3, pribitki2, pribitki1])) self.assertIsNone(tekma("ABCRDF", [pribitki1, pribitki2, pribitki1])) self.assertIsNone(tekma("ABCRDF", [pribitki3, pribitki1, pribitki2, pribitki1])) self.assertIsNone(tekma("ABCRDF", [pribitki3, pribitki1, pribitki1, pribitki2])) self.assertEqual(0, tekma("ABCRDF", [pribitki1, pribitki2, pribitki2])) self.assertEqual(1, tekma("ABCRDF", [pribitki2, pribitki1, pribitki2])) self.assertEqual(2, tekma("ABCRDF", [pribitki2, pribitki2, pribitki1])) class Test08(unittest.TestCase): def test_01_trening(self): pribitki = pribitki1.copy() self.assertAlmostEqual(4 + 2 + 3, trening("AB", pribitki)) pribitki = pribitki1.copy() self.assertAlmostEqual(4 + 2 + 3 + 4 + 2 * 0.95 + 3 * 0.95, trening("ABA", pribitki)) pribitki = pribitki1.copy() self.assertAlmostEqual(4 + 2 + 3, trening("AB", pribitki)) self.assertAlmostEqual(4 + 2 * 0.95 + 3 * 0.95, trening("BA", pribitki), "Je nekdo pozabil spremeniti `pribitki`?") pribitki = pribitki1.copy() self.assertAlmostEqual(75.787025, trening("ABCRCRDFG", pribitki)) def test_02_zastavice(self): # pribitki1 je hiter # pribitki2 zmrzne na BC zaradi bolta, potem je hiter # pribitki3 zmrzne na BC in CR zaradi loncev # pribitki4 je hitro čez BC, na CR, CD, DF ga ustavijo pešci self.assertEqual([7], zastavice("ABCRCRDFG", [pribitki1])) self.assertEqual([7], zastavice("ABCRCRDFG", [pribitki2])) self.assertEqual([7, 0], zastavice("ABCRCRDFG", [pribitki1, pribitki1])) self.assertEqual([7, 0], zastavice("ABCRCRDFG", [pribitki1, pribitki2])) self.assertEqual([2, 5], zastavice("ABCRCRDFG", [pribitki2, pribitki1])) self.assertEqual([5, 2], zastavice("ABCRCRDFG", [pribitki2, pribitki4])) self.assertEqual([4, 3], zastavice("ABCRCRDFG", [pribitki3, pribitki4])) self.assertEqual([5, 2], zastavice("ABCRCRDFG", [pribitki4, pribitki3])) self.assertEqual([5, 2, 0], zastavice("ABCRCRDFG", [pribitki2, pribitki4, pribitki3])) self.assertEqual([2, 3, 2], zastavice("ABCRCRDFG", [pribitki3, pribitki2, pribitki4])) class Test09(unittest.TestCase): def test_01_cikel(self): try: zemljevid2 = zemljevid.copy() for p in ((O, P), (I, E)): del zemljevid[p] del zemljevid[p[::-1]] self.assertEqual(3, cikel("A", pribitki1)) # cikel je ABV self.assertEqual(3, cikel("B", pribitki1)) # cikel je BVA self.assertEqual(16, cikel("R", pribitki1)) # RDFGHJKMNPSTUVBC self.assertEqual(16, cikel("U", pribitki1)) # isti self.assertEqual(16, cikel("L", pribitki1)) # isti; pazi, ne vsebuje L-ja! self.assertEqual(16, cikel("I", pribitki1)) # isti; pazi, ne vsebuje I-ja! pribitki = {v: i for i, v in enumerate(sorted(pribitki1))} self.assertEqual(3, cikel("B", pribitki)) # cikel je BVA self.assertEqual(3, cikel("C", pribitki)) # isti cikel - iz C gre v B self.assertEqual(11, cikel("A", pribitki)) # cikel je RDFGIMNPSTU, do njega pride po ABVC self.assertEqual(11, cikel("V", pribitki)) # isto self.assertEqual(6, cikel("J", pribitki)) # JKMIGH self.assertEqual(6, cikel("L", pribitki)) # isto, iz L gre v JKMIGH finally: zemljevid.update(zemljevid2) class Test10(unittest.TestCase): def test_01_izpadanje(self): ni_pribitkov = dict.fromkeys(pribitki1, 0) self.assertEqual([], izpadanje(["UVB", "SPIM"], [ni_pribitkov] * 2)) self.assertEqual([], izpadanje(["UVBCR", "SP"], [ni_pribitkov] * 2)) # 0 izloči 1 v I self.assertEqual([1], izpadanje(["URIE", "TSPIG"], [ni_pribitkov] * 2)) # 1 izloči 0 v I self.assertEqual([0], izpadanje(["TSPIG", "URIE"], [ni_pribitkov] * 2)) # hkrati v I, vendar je izločen tisti z večjim indeksom self.assertEqual([1], izpadanje(["SPIG", "URIE"], [ni_pribitkov] * 2)) self.assertEqual([1], izpadanje(["URIE", "SPIG"], [ni_pribitkov] * 2)) # 2 prehiti ostala dva v I self.assertEqual([0, 1], izpadanje(["URIE", "SPIG", "GIM"], [ni_pribitkov] * 3)) self.assertEqual([1, 0], izpadanje(["VURIE", "SPIG", "GIM"], [ni_pribitkov] * 3)) # 2 ju ne prehiti, ker obstane na avtocesti avtocesta = ni_pribitkov.copy() avtocesta["avtocesta"] = 100 self.assertEqual([0, 2], izpadanje(["VURIE", "SPI", "GIM"], [ni_pribitkov, ni_pribitkov, avtocesta])) self.assertEqual([0, 1, 2], izpadanje(["VURIE", "SPIG", "GIM"], [ni_pribitkov, ni_pribitkov, avtocesta])) self.assertEqual([1, 2, 0], izpadanje(["GIM", "SPIG", "VURIE"], [avtocesta, ni_pribitkov, ni_pribitkov])) # ničti izrine prvega (na P), zato prvi na izrine zadnjega, čeprav je ta na I precej pozneje self.assertEqual([1], izpadanje(["PNMKJ", "SPI", "GIE"], [ni_pribitkov, ni_pribitkov, avtocesta])) # ... isto, s premešanimi mesti self.assertEqual([0], izpadanje(["SPI", "PNMKJ", "GIE"], [ni_pribitkov, ni_pribitkov, avtocesta])) self.assertEqual([1], izpadanje(["GIE", "SPI", "PNMKJ"], [avtocesta, ni_pribitkov, ni_pribitkov])) self.assertEqual([2], izpadanje(["GIE", "PNMKJ", "SPI"], [avtocesta, ni_pribitkov, ni_pribitkov])) # ničti izrine prvega na P, drugega na I self.assertEqual([1, 2], izpadanje(["PNMIR", "SPI", "GIE"], [ni_pribitkov, ni_pribitkov, avtocesta])) # ... isto, s premešanimi mesti self.assertEqual([0, 2], izpadanje(["SPI", "PNMIR", "GIE"], [ni_pribitkov, ni_pribitkov, avtocesta])) self.assertEqual([2, 0], izpadanje(["GIE", "PNMIR", "SPI"], [avtocesta, ni_pribitkov, ni_pribitkov])) self.assertEqual([2, 1], izpadanje(["PNMIR", "GIE", "SPI"], [ni_pribitkov, avtocesta, ni_pribitkov])) self.assertEqual([2, 1], izpadanje(["SPI", "GIE", "SPI"], [ni_pribitkov, avtocesta, ni_pribitkov])) # ničti izrine prvega, zatem pa drugi ničtega na I (ker nima pribitka na avtocesti!) self.assertEqual([1, 0], izpadanje(["PNMIR", "SPI", "GIE"], [ni_pribitkov, ni_pribitkov, ni_pribitkov])) # vmes se še tretji ustreli v nogo self.assertEqual([1, 3, 0], izpadanje(["PNMIR", "SPI", "GIE", "DFD"], [ni_pribitkov] * 4)) # ničti izrine prvega na P, drugega na I self.assertEqual([1, 3, 2], izpadanje(["PNMIR", "SPI", "GIE", "DFD"], [ni_pribitkov, ni_pribitkov, avtocesta, ni_pribitkov])) pribitki5 = dict(gravel=4, trava=1, lonci=5, bolt=0, pešci=2, stopnice=4, avtocesta=1, črepinje=3, robnik=3, rodeo=2) pribitki6 = dict(gravel=1, trava=1, lonci=2, bolt=3, pešci=1, stopnice=1, avtocesta=3, črepinje=1, robnik=2, rodeo=4) self.assertEqual([1, 3, 4, 0], izpadanje(["ABCRVUTSP", "DRCBVUT", "EI", "GHJKMNPOPS", "SPNMK"], [pribitki1, pribitki5, pribitki1, pribitki6, pribitki1])) self.assertEqual([1, 4, 3, 0], izpadanje(["ABCRVUTSP", "DRCBVUT", "EI", "GHJKMNPOPS", "SPNMK"], [pribitki5, pribitki5, pribitki6, pribitki1, pribitki1])) if __name__ == "__main__": unittest.main()