Skúška 25.1.2024 - Juraj Jánošík


Juraj Jánošík sa dostal do jaskynného labyrintu (štvorcová sieť) s množstvom schránok s rôznymi cennosťami. Tieto ležia na niektorých políčkach labyrintu, pričom v každej schránke sa nachádza nejaký jeden drahocenný predmet (napríklad zlato, diamant, striebro, …). Budeme ich označovať písmenami malej abecedy (rovnaký druh rovnakým písmenom). Juraj získa tento predmet vtedy, keď príde na políčko so schránkou (a vtedy sa schránka z plochy odstráni).

Pri štarte sa hráč (Juraj) nachádza na prázdnom políčku (bez schránky s cennosťou) a je otočený v jednom zo smerov:

  • 0 = východ, 1 = juh, 2 = západ, 3 = sever

Ďalej budeme hráča riadiť pomocou postupnosti celých čísel takto:

krok1 otoč1 krok2 otoč2 ...

Funguje to takto:

  • najprv urobí krok1 krokov vpred vo svojom momentálnom smere, pričom krok1 je nezáporné číslo; ak sa niekoľko krokov urobiť nedá kvôli prekážke alebo okraju plochy, tak sa tieto ignorujú a hráč pri nich ostáva na mieste

  • potom sa otočí otoč1 krát vpravo (o 90 stupňov); otoc1 môže byť aj záporné číslo; napríklad, ak je momentálne otočený na juh (smer = 1) a číslo otočení je -3, tak sa otočí na západ

  • takto postupne pokračuje so všetkými číslami postupnosti; táto postupnosť čísel môže byť párnej aj nepárnej dĺžky

  • počas pohybu, ak je na políčku so schránkou s cennosťou, tak ju otvorí a vyberie obsah - takto si postupne zbiera písmená drahocenných predmetov (schránku z labyrintu odstráni)

Celá mapa labyrintu aj s vyznačenými schránkami (s písmenami) je zaznačená do štvorcovej siete: každé políčko je buď prázdne (budeme značiť '.'), je tam stena, teda prekážka (budeme značiť 'M'), alebo schránka s cennosťou (budeme zobrazovať '#'). Štruktúra súboru s popisom labyrintu je nasledovná:

  • v prvom riadku sú dve celé čísla (oddelené medzerou): počet riadkov a počet stĺpcov štvorcovej siete

  • v každom nasledujúcom riadku súboru je na začiatku nejaký jeden znak, za ktorým je niekoľko celých čísel (oddelených medzerou)

  • ak riadok začína znakom 'M', tak za tým nasleduje postupnosť pozícií (riadok, stĺpec), na ktorých sa nachádzajú prekážky

  • ak riadok začína malým písmenom (od 'a' po 'z'), za tým nasledujú pozície v ploche, kde sa nachádzajú tieto drahocennosti - pri zobrazovaní plochy sa budú vykresľovať znakom '#'

  • ak riadok začína znakom '@', za tým nasledujú tri celé čísla: riadok a stĺpec pozície hráča a jeho štartový smer natočenia (číslo od 0 do 3)

Môžeš predpokladať, že súbor je zadaný korektne a okrem prvého riadku s rozmermi obsahuje ešte aspoň jeden riadok s pozíciou hráča (začína znakom '@').

Napríklad pre 'subor1.txt':

4 5
M 1 2 3 0
c 2 3
@ 0 2 2
a 2 4 1 4
M 0 4
b 3 3

labyrint by sa zobrazil takto:

..@.M
..M.#
...##
M..#.

Napíš metódy triedy JurajJanosik:

class JurajJanosik:
    def __init__(self, meno_suboru):
        ...

    def __str__(self):
        return ''

    def pohyb(self, *postupnost):
        return set()

    def ziskane(self):
        return set()

kde metóda:

  • init(meno_suboru) - prečíta súbor s popisom labyrintu

  • __str__() - vráti znakový reťazec, ktorý reprezentuje stav labyrintu s hráčom: prázdne políčka zobrazuje ako '.', navštívené políčka ako '+', prekážky ako 'M', ešte nezozbierané schránky ako '#' a momentálnu pozíciu hráča ako '@'

  • pohyb(*postupnost) - dostane neprázdnu postupnosť celých čísel pre pohyb hráča; v postupnosti sa striedajú čísla pre počty krokov a počty otočení; ak je postupnosť nepárnej dĺžky, na konci sa neurobí žiadne otočenie; funkcia vráti množinu (set) zozbieraných predmetov v tomto ťahu (ak je v tejto množine viackrát nejaké písmeno, tak sa upraví podobne ako v metóde ziskane)

  • ziskane() - vráti celkovú množinu (set) zozbieraných predmetov (písmen) počas všetkých pohybov hráča; ak sa v tejto množine má objaviť niektoré písmeno viackrát, tak sa uvedie aj s číslom o počte výskytov, napríklad, množina s jediným 'a' a tromi 'e' sa zapíše {'a', '3e'}

Napríklad, takýto test:

if __name__ == '__main__':
    jj = JurajJanosik('subor1.txt')
    print(jj)
    print('zozbieral:', jj.pohyb(1, 3, 2, -1, 5, 1))
    print(jj)
    print('zozbieral:', jj.pohyb(1, 1, 1))
    print(jj)
    print('spolu ziskal:', jj.ziskane())

vypíše:

..@.M
..M.#
...##
M..#.
zozbieral: {'c', 'a'}
.++.M
.+M.#
.+++@
M..#.
zozbieral: {'b'}
.++.M
.+M.#
.++++
M..@+
spolu ziskal: {'c', 'a', 'b'}

Z úlohového servera L.I.S.T. si stiahni kostru programu skuska.py. Pozri si testovacie dáta v súboroch 'subor1.txt', 'subor2.txt', …, ktoré bude používať aj testovač.

Aby si mohol spúšťať skúškové testy, program ulož do súboru skuska.py. Riešenie (bez dátových súborov) odovzdaj na úlohový server https://list.fmph.uniba.sk/. Tvoj odovzdaný program musí začínať tromi riadkami komentárov:

# 3. skuska: Juraj Janosik
# autor: Janko Hraško
# datum: 25.1.2024