ExprFX
Ülesandeks on implementeerida matemaatiliste avaldiste lihtsustamise programm, millel on ScalaFX-iga loodud kasutajaliides.
Vahetähtaeg: 11. dets
Lõpptähtaeg: 19. dets 23:55
Kuna hindame ka koodi struktureerimist ja stiili (2 punkti 7st), siis soovitame esitada vahetähtajaks. Siis saate oma koodi veel parandada.
Sisend
Kasutajaliideses peab olema võimalus sisestada matemaatiline avaldis allkirjeldatud kujul. Selleks võib kasutada tekstivälja.
Avaldised
Sisendiks olevad avaldised koosnevad järgmistest komponentidest:
- Täisarvulised konstandid, nt 0, 1, 5.
- Väiketähelised muutujad, nt x, y, a.
- Binaarsed operatsioonid: liitmine (+), lahutamine (-), korrutamine (*), täisarvuline jagamine (/), astendamine (^), mille argumentideks on omakorda mistahes avaldised.
S-expression
Kasutaja sisestab lihtsustatava avaldise mitte tüüpilisel infikssel kujul, vaid S-expression-ina. Näiteks
- infiksne avaldis
2*(3+4)
kirjutatakse S-expression-ina(* 2 (+ 3 4))
, - infiksne avaldis
(5-5)*x^2+8
kirjutatakse S-expression-ina(+ (* (- 5 5) (^ x 2)) 8)
.
S-expression-eid on lihtsam parsida kui infiksseid avaldisi, sest avaldispuu struktuur on ette antud ega pea muretsema tehete prioriteetide ja assotsiatiivsuste pärast.
Parsimine
Sisendsõne parsimist avaldiseks on võimalik implementeerida käsitsi, kuid palju mugavam on selleks kasutada Scala parserkombinaatorite teeki scala-parser-combinators, mis varem kuulus Scala standardteekide hulka, kuid nüüd tuleb see sõltuvusena oma SBT projektile lisada.
Parserkombinaatorite ja spetsiifiliselt scala-parser-combinators teegi kasutamise kohta vaata näidet KalaParser Scalas. Selle põhjal peaks olema võimalik implementeerida S-expression-ite parsimine. Rohkem infot võib leida näiteks scala-parser-combinators-i viidatud allikatest.
Kui kasutaja sisestatu on vigane, st seda ei õnnestu parsida, siis peab kasutajat sellest kuidagi teavitama.
Lihtsustamine
Kuigi järgnevad lihtsustamise reeglid ja näited on kirjeldatud infikssete operaatorite abil, siis kasutaja sisend on ikkagi S-expression-i abil nagu ülal kirjeldatud. Lihtsustamine toimub programmisiseselt ja konkreetne sisendformaat pole seejuures oluline.
Arvutamine
Kui binaarse operatsiooni mõlemaks argumendiks on konstant, siis tuleb see operatsioon asendada arvutatud tulemusega, nt 1+2 → 3
, 3/2 → 1
.
Lihtsustusreeglid
Kui binaarse operatsiooni argumendid pole konstandid, siis on teatud juhtudel ikka võimalik avaldist lihtsustada. Olgu E
suvaline avaldis, siis tuleb rakendada järgnevaid lihtsustusreegleid:
- Liitmine
-
E + 0 → E
0 + E → E
- Lahutamine
-
-
E - 0 → E
-
- Korrutamine
-
-
E * 1 → E
1 * E → E
E * 0 → 0
0 * E → 0
-
- Jagamine
-
-
E / 1 → E
-
- Astendamine
-
-
E ^ 1 → E
1 ^ E → 1
-
Lihtsustamise protsess
Ülalkirjeldatud lihtsustusi tuleb teostada nii kõige välimisel avaldisel (nt 0*(x+1) → 0
) kui ka alamavaldistel (nt 2*(x+0) → 2*x
).
Kasutaja sisestatud avaldist tuleb lihtsustada nii palju kui võimalik, nt (x+0)+(y*1) → x+(y*1) → x+y
.
NB! Ühe lihtsustamise tulemus võib võimalikuks teha järgmise lihtsustuse, mida eelnevalt teha ei saanud, ning seda tuleb samuti arvestada, nt (5-5)*x^2+8 → 0*x^2+8 → 0+8 → 8
.
Lihtsustamine ei pea hakkama saama keerulisemate juhtumitega kui ülal kirjeldatud. Näiteks 2+x+2
saaks lihtsustada avaldiseks x+4
, kuid sellist lihtsustust programm toetama ei pea, sest ühegi antud reegliga selleni jõuda pole võimalik.
Väljund
Kasutajaliideses peab ilusalt infiksselt kuvama sisestatud avaldise ja selle lihtsustatud kuju.
MathML
Üheks standardseks matemaatiliste valemite kirjeldamise keeleks on MathML. Avaldiste ilusaks kuvamiseks peaks need teisendama MathML-i, mida saab olemasolevate lahendustega kuvada.
Valemite teisendamisel tuleks järgida Presentation MathML reegleid ja võimalusi:
- Arvulised konstandid paikenvad
<mn>
märgendite vahel. - Muutujad paikenvad
<mi>
märgendite vahel. - Tehtemärgid paikenvad
<mo>
märgendite vahel. - Jagamiseks kasutada
<mfrac>
märgendeid. - Astendamiseks kasutada
<msup>
märgendeid.
NB! Infiksses MathML väljundis on teatud olukordades vaja kasutada sulgusid (<mfenced>
märgenditega), nt (* 2 (+ x 1))
infikssel kujul on 2*(x+1)
mitte 2*x+1
.
WebView
Kasutajaliideses peaks kasutama ScalaFX-i WebView-d, et MathML-is avaldisi ilusal kujul kuvada. Nimelt avaldiste MathML-i saab <math>
märgendite vahel paigutada lihtsale HTML veebilehele, mida WebView'us kuvada.
Kuna ScalaFX-i (JavaFX-i) WebView-l võib olla probleeme keerulisemate MathML konstruktsioonide (<mfrac>
, <msup>
) korrektse kuvamisega, siis võib genereeritavasse HTML-i lisada MathJax teegi, mis sellega automaatselt hakkama saab.