Reševanje naloge UNDO

Reševanje naloge UNDO

Avtor: Tanja Kokalj

Besedilo naloge

Napredno podjetje na področju urejevalnikov besedila se je odločilo za povsem nov pristop. Namesto večanja števila operacij, ki so na voljo uporabniku, so se odločili število operacij drastično zmanjšati. Svoj novi produkt nameravajo poimenovati rise (Reduced Instruction Set Editor), tebe pa so prosili za pomoč pri razvoju. Odločili so se obdržati le dva ukaza, enega za dodajanje besede na konec trenutnega besedila in enega za razveljavitev nekaj predhodnih ukazov. Ukaz za razveljavitev pa ima neko posebnost, z njim lahko namreč razveljavimo tudi več prejšnjih razveljavitvenih ukazov. Napiši program, ki prebere zaporedje ukazov in izpiše besedilo, ki nastane po izvedbi vseh prebranih ukazov.

Vhodna datoteka: v prvi vrstici je celo število n, ki pove, koliko ukazov sledi (velja 1 <= n <= 100 000). Sledi n vrstic, v vsaki je po en ukaz. Ukazi za dodajanje besede bodo imeli obliko WRITE <beseda>. Razveljavitveni ukazi pa bodo v obliki UNDO <k>, kjer k pomeni število predhodnih ukazov, ki jih želimo razveljaviti. Število k ne bo nikoli večje od števila dotlej izvedenih ukazov. Posamezne besede bodo krajše od 100 znakov in sestavljene samo iz velikih in malih črk angleške abecede, brez ločil ali presledkov.

Izhodna datoteka: vanjo izpiši besedilo, ki nastane po izvedbi vseh prebranih ukazov. Med besedami ne piši presledkov, na koncu besedila pa izpiši znak za konec vrstice.

Primer vhodne datoteke:

  • 6
  • WRITE Danes
  • WRITE je
  • UNDO 1
  • WRITE lep
  • UNDO 2
  • WRITE dan
Pripadajoča izhodna datoteka: Danesjedan

OPIS PROBLEMA IN IDEJA REŠITVE

Sestaviti moramo program, ki iz vhodne datoteke prebere neke podatke. Pri branju bomo moral biti pozorni na tri ukaze in sicer število vrstic (zapisano s številko v prvi vrstici) , UNDO in WRITE. Prvi podatek (število vrstic) nam pove koliko vrstic bomo prebrali. Ukaz WRITE bo povedal, da podatek za njim zapišemo v datoteko. UNDO pa bo razveljavil število ukazov, ki bo navedeno v podatku za njim. Torej če bo pisalo UNDO 2 moramo razveljaviti zadnji dve vrstici. Pozorni pa moramo biti tudi na to, da ukaz UNDO razveljavi prejšnjega UNDO.

IDEJA Kot je že zgoraj omenjeno bomo brali iz datotek in zapisovali vanje. Za to bomo uporabili bralca. Sprva bomo pogledali število vrstic, ki jih želimo obdelati s programom. Ker je problem nekoliko zakompliciran glede skakanja iz vrstice v vrstico sem se odločila, da najprej pregledam kakšen je postopek. Ukaz WRITE le pove nek podatek in ga zapišemo ali shranimo. UNDO pa gleda nazaj glede na število podanih vrstic. Torej naš program pravzaprav gleda vrstice od zadnje proti prvi. Zato sem se odločila, da bo moj program bral podatke od zadnje vrstice naprej. Torej sprva s pomočjo bralca pogledamo koliko vrstic bomo obdelali. Dobimo podatek n. Nato se postavimo v vrstico n+1 (ne smemo pozabiti, da je prva vrstica že porabljena). Podatke, ki jih bomo prebrali v naslednji vrsticah bomo razdelili na dva dela. Prvi bo ime ukaza (WRITE ali UNDO) drugi pa njegova vrednost. V primeru, da se bo pojavil ukaz WRITE bomo njegovo vrednost iz leve strani pripisali v nek niz vmesniRez in se pomaknili vrstico višje. Sicer (ukaz UNDO) pa bomo preverili vrednost od ukaza in se pomaknili za toliko vrstic višje. Torej če bomo prišli do ukaza UNDO 3 se bomo pomaknili za tri vrstice višje in vmesne ignorirali. Postopek ponavljamo dokler ne pridemo do 2. oziroma prve vrstice. Na koncu le še ta niz izpišemo oz. zapišemo na datoteko.

RAZLAGA ALGORITMA

Na začetku definiramo bralca. Z njegovo pomočjo preberemo prvo vrstico in dobimo podatek o številu vrstic, ki jih želimo obdelati. StreamReader bralec = new StreamReader("vhodnaDatoteka.txt"); // definiramo bralca
int steviloUkazov = int.Parse(bralec.ReadLine()); 

Nato vse vrstice razen prve prepišemo v tabelo seznamUkazov. string[] seznamUkazov = new string[steviloUkazov]; // ustvarimo novo tabelo

for (int i = 0; i < steviloUkazov; i++)   // vrstice (razen prve) prepišeš v tabelo
{
     seznamUkazov[i] = bralec.ReadLine();
}

S pomočjo for zanke gremo čez celoten seznam od zadnjega elementa proti prvemu. Ti so sestavljeni iz dveh delov. Prvi pove ime ukaza (WRITE ali UNDO) drugi pa vrednost. Zato bomo izbrani element poimenovali ukaz. for (int i = seznamUkazov.Length-1; i > -1; i--)
{
     string[] ukaz = seznamUkazov[i].Split(' ');

V primeru, da je prvi del WRITE potem njegovo vrednost pridružimo z leve strani k nizu Rez, ki smo ga definirali že prej.
     if (ukaz[0] == "WRITE")
     {
        Rez = ukaz[1] + Rez;
     }

Sicer pa se pomaknemo za vrednost ukaza UNDO v levo v seznamu.
     else
     {
        i -= int.Parse(ukaz[1]);
     }
}

Sedaj moramo le še naš rezultat zapisati v datoteko. To si pomagamo s pomočjo pisalca. Poleg rezultata na koncu še dodamo znak za konec vrstice. StreamWriter pisalec = new StreamWriter("izhodnaDatoteka.txt");
pisalec.Write(Rez);
pisalec.Write("\n");  // na koncu še dodamo znak za konec vrstice

Ker smo bralca in pisalca nehali uporabljati ju še zapremo.
bralec.Close();
pisalec.Close();

TESTNI PRIMERI

Za testiranje programa sem uporabila tri primere. 1. primer:

Vhodna datoteka:

6
WRITE Danes
WRITE je
UNDO 1
WRITE lep
UNDO 2
WRITE dan

Izhodna datoteka:

Danesjedan

2. primer:

Vhodna datoteka:

10
WRITE Danes
WRITE je
UNDO 1
WRITE popoln
WRITE dan
WRITE ampak
WRITE ne
UNDO 4
WRITE za
WRITE vsakogar

Izhodna datoteka:

Daneszavsakogar

3. primer:

Vhodna datoteka:

16
WRITE A
WRITE B
UNDO 1
WRITE C
WRITE D
UNDO 3
WRITE E
WRITE F
UNDO 1
WRITE G
UNDO 3
WRITE H
WRITE I
UNDO 2
WRITE J
WRITE K

Izhodna datoteka:

ABEJK

S prvim primerom sem preverila ali program res deluje, naslednja dva sem si pa izmislila. Pri drugem primeru sem zgolj preverjala ali prav deluje ukaz undo, nakar sem pri tretjem primeru preverila ali deluje tudi UNDO na UNDO. Zanimalo nas je ali res pride do razveljavitve.

0%
0%