Skúška 23.1.2023 - Písmenkový robot


Na štvorčekovej ploche sa pohybuje robot, ktorý je riadený postupnosťou povelov:

  • povel je buď písmeno pre smer 'znak', ktoré je jedno z 's', 'v', 'j', 'z' (pre sever, východ, juh, západ), alebo znak aj s číslom 'čísloznak', kde číslo označuje, koľkokrát sa robot pohne daným smerom

  • napríklad, povely môžu byť 'v', '3j', '12z' a potom postupnosť povelov bude 'v3j12z'

Pri štarte sa v ploche na niektorých políčkach môžu nachádzať písmenká. Okrem toho na obvode plochy (t.j. prvý aj posledný riadok, prvý aj posledný stĺpec) sú umiestnené prekážky. Ak počas vykonávania povelu by robot mal nabúrať do prekážky, tento povel už ignoruje a poslúcha až ďalšie povely.

Ak robot počas chodenia prejde cez políčko s písmenkom, zdvihne ho (zapamätá si ho) a na jeho miesto položí prekážku: na budúce cez toto políčko už neprejde.

Vstupný súbor obsahuje popis plochy:

  • v prvom riadku súboru sú dve čísla: počet riadkov a počet stĺpcov (veľkosť plochy aj s rámikom)

  • ďalšie riadky popisujú pozície písmeniek, v každom riadku sú tri hodnoty:

    písmeno riadok stĺpec

  • môžeš predpokladať, že súbor je zadaný korektne.

Zadefinuj triedu PismenkovyRobot:

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

    def __repr__(self):
        ...

    def robot(self, riadok, stlpec):
        ...

    def zisti(self):
        ...

    def povely(self, postupnost):
        ...

kde

  • metóda __init__(meno_suboru): prečíta súbor a vytvorí dvojrozmerné pole s rozložením písmeniek

  • metóda __repr__(): vráti znakový reťazec, ktorý reprezentuje momentálny stav plochy aj s prekážkami (znak '*'), robot zobrazí znakom '@'; medzi riadkami je znak '\n'

  • metóda robot(riadok, stlpec): umiestni robota na zadanú pozíciu, môžeš predpokladať, že je voľná a nie je na nej prekážka ani písmenko

  • metóda zisti(): vráti množinu políčok s písmenkami, ktoré sa ešte nepozbierali (ako množinu trojíc (písmeno, riadok, stĺpec))

  • metóda povely(postupnost): robot vykoná zadanú postupnosť povelov a po skončení metóda vráti dvojicu hodnôt (tuple): počet naozaj vykonaných krokov a znakový reťazec s pozbieranými znakmi; každé volanie tejto metódy vráti len tie znaky, ktoré sa pozbierali počas tohto volania

Každé ďalšie volanie metód robot() aj povely() pokračuje na ploche, v ktorej sa chodilo predtým a už sa tu zbierali písmenká a tým aj kládli prekážky do plochy.

Napríklad, pre plochu:

*****
* A *
*J H*
* O *
*****

tento test:

if __name__ == '__main__':
    p = PismenkovyRobot('subor.txt')
    print(p)
    print(p.zisti())
    p.robot(2, 2)
    s = p.povely('sv2jzz2s')
    print('vysledok:', s)
    print(p)
    print(p.zisti())

vypíše:

*****
* A *
*J H*
* O *
*****
{('O', 3, 2), ('A', 1, 2), ('H', 2, 3), ('J', 2, 1)}
vysledok: (8, 'AHOJ')
*****
*@* *
** **
* * *
*****
set()

V druhom teste si všimni, že metódu povely() voláme dvakrát za sebou. Plocha:

******
* JF *
* OM *
* HF *
* AI *
******

test:

if __name__ == '__main__':
    p = PismenkovyRobot('sub/subor1.txt')
    print(p.zisti())
    p.robot(4, 1)
    print(p)
    print('prvy:', p.povely('v4s'))
    print(p)
    print(p.zisti())
    print('druhy:', p.povely('v5j'))
    print(p)
    print(p.zisti())

vypíše:

{('F', 3, 3), ('A', 4, 2), ('H', 3, 2), ('M', 2, 3), ('O', 2, 2),
 ('I', 4, 3), ('J', 1, 2), ('F', 1, 3)}
******
* JF *
* OM *
* HF *
*@AI *
******
prvy: (4, 'AHOJ')
******
* @F *
* *M *
* *F *
* *I *
******
{('M', 2, 3), ('F', 3, 3), ('F', 1, 3), ('I', 4, 3)}
druhy: (4, 'FMFI')
******
* ** *
* ** *
* ** *
* *@ *
******
set()

Z úlohového servera L.I.S.T. si stiahni kostru programu skuska.py. Pozri si testovacie dáta v súboroch 'subor.txt', 'subor1.txt', …, ktoré bude používať 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:

# 4. skuska: pismenkovy robot
# autor: Janko Hraško
# datum: 23.1.2023