Rešitev: Kalkulator za aritmetične izraze v obrnjenem poljskem zapisu (Mathematica)

Iz MaFiRaWiki

Naloga: Kalkulator za aritmetične izraze v obrnjenem poljskem zapisu

Ker računanje izraza v obrnjeni poljski notaciji poteka tako, da elemente dodajamo na konec seznama, kjer jih hranimo dokler ne naletimo na operacijo in zato zamenjamo tiste elemente, ki smo jih nazadnje dodali v seznam z rezultatom operacije (kot je opisano v članku Aritmetični izrazi v obrnjenem poljskem zapisu), bomo v našem programu uporabili podatkovno strukturo sklad.

Torej najprej implementiramo sklad:

 Clear[Pripravi,Vstavi,JePrazen,Vrh,Odstrani];
 JePrazen[Pripravi[]]:=True;
 JePrazen[Vstavi[s_,e_]]:=False;
 JePrazen::usage="Funkcija JePrazen[s] vrne True če je sklad s prazen in False sicer.";

 Vrh[Pripravi[]]:=Null;
 Vrh[Vstavi[s_,e_]]:=e;
 Vrh::usage="Funkcija Vrh[s] vrne zgornji element sklada s. Če pa je sklad prazen, vrne Null.";

 Odstrani[Pripravi[]]:=Pripravi[]; 
 Odstrani[Vstavi[s_,e_]]:=s;
 Odstrani::usage="Funkcija Odstrani[s] vrne sklad s brez zgornjega elementa. Če je sklad prazen, vrne prazen sklad.";

Kalkulator za izraze v obrnjenem poljskem zapisu:

 Clear[NizVStevilo,VsebujeEnElt,VsebujeDvaElta,Kal];
 NizVStevilo[w_String]:=Block[{ss, rezultat}, ss=StringToStream[w]; rezultat=Read[ss,Number]; Close[ss]; rezultat];
 NizVStevilo::usage="Funkcija NizVStevilo[w] pretvori niz, ki je sestavljen iz števk, v število.";
 
 VsebujeEnElt[s_]:=!JePrazen[s];
 VsebujeEnElt::usage="Funkcija VsebujeEnElt[s] vrne True, če sklad s vsebuje vsaj en element, in False sicer.";
 
 VsebujeDvaElta[s_]:=!JePrazen[Odstrani[s]];
 VsebujeDvaElta::usage="Funkcija VsebujeDvaElta[s] vrne True, če sklad s vsebuje vsaj dva elementa, in False sicer.";

 Kal[w_String]:=Kal[StringSplit[w], Pripravi[]];
 Kal[{}, Pripravi[]]:=Print[0];
 Kal[{}, s_]:=Print[Vrh[s]];
 Kal[w_List, s_] /; Last[w]=="a"&&VsebujeEnElt[s] := Kal[Most[w], Vstavi[Odstrani[s], -Vrh[s]]];
 Kal[w_List, s_] /; Last[w]=="+"&&VsebujeDvaElta[s] := Kal[Most[w], Vstavi[Odstrani[Odstrani[s]], Vrh[Odstrani[s]]+Vrh[s]]];
 Kal[w_List, s_] /; Last[w]=="-"&&VsebujeDvaElta[s] := Kal[Most[w], Vstavi[Odstrani[Odstrani[s]], Vrh[Odstrani[s]]-Vrh[s]]];
 Kal[w_List, s_] /; Last[w]=="*"&&VsebujeDvaElta[s] := Kal[Most[w], Vstavi[Odstrani[Odstrani[s]], Vrh[Odstrani[s]]*Vrh[s]]];
 Kal[w_List, s_] /; Last[w]=="/"&&VsebujeDvaElta[s] := Kal[Most[w], Vstavi[Odstrani[Odstrani[s]], Vrh[Odstrani[s]]/Vrh[s]]];
 Kal[w_List, s_] /; MemberQ[{"+","-","*","/","a"},Last[w]] && (!(VsebujeEnElt[s]&&Last[w]=="a") || !(VsebujeDvaElta[s]&&
  MemberQ[{"+","-","*","/"},Last[w]])) := Print["Izraza ni mogoče izračunati, ker ni pravilno sestavljen (obstaja operacija v 
  izrazu, za katero ne obstaja predpisano število operandov)."];
 Kal[w_List, s_] /; NumberQ[NizVStevilo[Last[w]]] := Kal[Most[w], Vstavi[s, NizVStevilo[Last[w]]]];
 Kal[w_List, s_] := Print["Niz je sestavljen iz napačnih znakov (dovoljeni znaki so le presledek, števke, a, +, -, * in / )."];
 Kal::usage="Funkcija Kal[w] vrne rezultat v nizu zapisanega izraza v obrnjeni poljski notaciji (bere iz desne proti levi). 
  Če izraz ni sestavljen pravilno ali vsebuje nedovoljene znake javi napako.";

Preizkusimo na primerih:

 Clear[w1,w2,w3];
 w1="/ a 12 * + 6 * - 4 6 5 3";
 In[32]:= Kal[w1]
 Out[32]:= -4
 w2="+ 2";
 In[34]:= Kal[w2]
 Out[34]:= Izraza ni mogoče izračunati, ker ni pravilno sestavljen (obstaja operacija v izrazu, za katero ne obstaja 
  predpisano število operandov).
 w3="a";
 In[36]:= Kal[w3]
 Out[36]:= Izraza ni mogoče izračunati, ker ni pravilno sestavljen (obstaja operacija v izrazu, za katero ne obstaja 
  predpisano število operandov).

Glej tudi

Osebna orodja