Yorick

Yorick

Avtor: Niko Oblak

Kratek opis

Yorick je programski jezik, namenjen za analizo ali obdelavo podatkov, predvsem n-razsežnih matrik. Je odprtokodna programska oprema, kar pomeni, da ga lahko brezplačno uporabljamo, spreminjamo...

Zmožnosti:

  • Ustvarjanje novih funkcij
  • Pogojni stavki
  • Zanke
  • Računanje osnovnih matematičnih operacij
  • Računanje z matrikami
  • Računanje s kompleksnimi števili
  • Delo z datotekami
  • Risanje grafov
  • ...

Več na sicer neuradni strani klik.

Izgled

(osnovnookno.png)
Osnovno okno

Terminal deluje zelo podobno kot Python Shell. V njim se izvajajo poljubni trenutni ukazi. Za pisanje daljše kode, pa je bolj priporočljivo pisati v novem oknu.

Trigonometrične funkcije

Yorick ima vgrajen tudi skupek trigonometričnih, hiperboličnih funkcij:

  • sin
  • cos
  • tan
  • asin
  • acos
  • atan
  • sinh
  • cosh
  • tanh
  • ...

Primeri uporabe:

(trig.PNG)

Več vgrajenih funkcij

Poleg osnovnih trigonometričnih funkcij ima Yorick vgrajene tudi druge funkcije:

  • abs (absotulna vrednost)
  • sqrt (kvadratni koren)
  • floor (odreže decimalni del)
  • ceil (zaokroži navzgor)
  • conj (konjugirana vrednost kompleksnega števila)
  • pi (število pi 3.14159265358...)
  • exp (eksponentna funkcija)
  • log, log10 (logaritemska funkcija)
  • min (minimun)
  • max (maksimum)
  • sum (vsota)
  • avg (povprečje)
  • random (naključno število med 0 in 1)
  • ...

Pogojni stavki, komentarji in ukaz print

Print

Če izpisujemo v oklepajih, recimo print(10) , je izhod izpisa oblike ["10"] . Na vsaki strani besedila, tipa  "besedilo"  , pa se doda še  \"  .

Primer:

(print.PNG)

Lahko pa izpisujemo brez (...). V tem primeru ne bo stranskih [" "] . Še vseeno pa morajo biti podatki ločeni z vejico.

Primer:

(print1.PNG)


Komentarji

Tudi v Yoricku lahko poleg kode, dodajamo komentarje. Ločimo dve vrsti:

1) /* Komentar */

Tak komentar se začne z /* in obvezno konča z */ . Če ta komentar nima svojega konca */ , pride do napake.

2) // Komentar

Tak komentar se začne z // in velja do konca vrstice (podobno kot v Pythonu # ).


Pisanje pogojnih stavkov

Princip pogojnih stavkov je povsem enak tistemu v Pythonu. Razlika je predvsem le v sintaksi. V Yoricku je, za razliko od Pythona, zamikanje stavkov estetskega pomena. Pogoju lahko sledi več stavkov. Pogoj mora biti obvezno v oklepaju, kateremu sledi stavek, ali več stavkov. V tem primeru pa moramo stavke napisati v {...}. Vsak stavek mora biti v svoji vrstici.

if (pogoj) stavek

oziroma:

if (pogoj1) {stavek1
stavek2
stavek3
...
}
else if (pogoj2) stavekN
...
else stavekM

Lahko jih gnezdimo:

if (pogoj1) if (pogoj2) stavek1

Primer:

(pogoj1.PNG)

Opazimo, da mora biti konec jedra funkcije } v novi vrstici. To velja tudi za konec jedra pogojnih stavkov in zank.

Zanke

Yorick vsebuje 3 tipe zank:


while

Deluje podobno kot v Pythonu. Dokler je pogoj izpolnjen, se izvajajo stavki v jedru {...} zanke:

while (pogoj) {stavek1
stavek2
stavek3
...
}


do

Precej podobna zanki while. Tukaj najprej napišemo stavke, kateri se bodo izvajali, dokler bo pogoj izpolnjen. Na koncu pa napišemo še pogoj.

do {stavek1
stavek2
stavek3
...
} while (pogoj)


for

Zanki for moramo v oklepaju navesti začetno stanje, pogoj in spremembo stanja na korak (podatki v oklepaju so ločeni z ;). Nato pa sledijo stavki, ki se bodo v jedru zanke {...} izvajali.

for (začetno stanje; pogoj; sprememba na korak) {stavek1
stavek2
stavek3
...
}

Primeri

(zanke.PNG)

Vektorji in matrike

V Yoricku lahko delamo tudi z vektorji in matrikami. Ampak pogrešam nekaj vgrajenih metod. Recimo izračun determinante, vektorski produkt,...

Kako definiramo:

  • vektor: v = [1,2,3,4]
  • matriko: A = [[3,4,5], [5,3,2]] 2×3 matrika


Dostop do komponent

Vektorji in matrike so indeksirani od 1 naprej. Pri matrikah se indeksira po vrsticah. Lahko pa navedemo stolpec in vrstico komponente.

> v=[1,3,2,5,4]
> v(3) // vrednost tretje komponente
2
> A=[[2,4,3], [5,3,2]]
> A(4) // vrednost četrte komponente
5
> A(3,2) // vrednost komponente v tretjem stolpcu in drugi vrstici
2
> A(2:4) // rezina od druge do četrte komponente
[4,3,5]
> A(2:6:2) // rezina od druge do šeste komponente s korakom 2
[4,5,2]
> v1=[3,4,2,1,6]
> v*v1 // operacije se izvajajo po komponentah
[3,12,4,5,24]
> sin(v)
[0.841471,0.14112,0.909297,-0.958924,-0.756802]
> C = [[2,3,1],[4,7,2],[5,3,6]]
> C(2,3) = 10 // spremenimo vrednost komponente v drugem stolpcu in tretji vrstici.
> C
[[2,3,1],[4,7,2],[5,10,6]]
> dimsof(3)
[0]
> dimsof("besedilo")
[0]
> dimsof(v)
[1,5]
> dimsof(A)
[2,3,2]
> numberof(v) // vrne število komponent
5
> numberof(A) // vrne število komponent
6

Zgoraj sem uporabil ukaz dimsof() , ki nam pove dimenzije. Pri številih in besedilu nam vedno vrne [0] , saj ju obravnava kot skalar. Za dani vektor nam vrne [1, število stolpcev] , saj je sestavljen le iz ene vrstice in n-stolpcev. Pri matriki pa nam vrne [2, število stolpcev, število vrstic] , saj je sestavljena iz n-stolpcev in m-vrstic.

Obstaja še drug način dostopa. Recimo, da bi radi le prvi stolpec matrike C.

> C
[[2,3,1],[4,7,2],[5,10,6]]
> C(..) // vrne celotno matriko C
[[2,3,1],[4,7,2],[5,10,6]]
> C(1,..) // vrne prvi stolpec matrike C
[2,4,5]
> C(..,2) // vrne drugo vrstico matrike C
[4,7,2]
> C(1,..,3) // vrne komponento v prvem stolpcu in tretji vrstici matrike C.
5


Posebno indeksiranje

S Simboloma + in - zagotovimo nadzor nad tem, kako se bodo izvedli določeni ukazi. Simbol + uporabljamo na množenju vektorjev ali matrik. Precej uporaben je za izračun skalarnega produkta. Dimenzije faktorjev (matrik) se morajo, pri uporabi simbola + ujemati.

> v=[1,2,3,4]
> b=[3,4,2,3]
> v(+)*b(+) // v(1)*b(1) + v(2)*b(2) + v(3)*b(3) + v(4)*b(4)
29

Recimo da imamo dve 2×3 matriki A in B. Izračunajmo A(+)*B(+):

> A=[[2,4,3],[5,3,2]]
> B=[[2,3,4],[1,2,3]]
> A(+)*B(+) // A(1)*B(1) + A(2)*B(2) + A(3)*B(3)
28

Opazimo, da dobimo skalarni produkt prve vrstice matrike A in prve vrstice matrike B.

Na ta način lahko izračunamo skalarni produkt poljubnih dveh vrstic.

Izračunajmo skalarni produkt prve vrstice matrike A in druge vrstice matrike B.

> A(+,1)*B(+,2)
19

Izračunajmo skalarne produkte obeh matrik po vrsticah

> A(+,)*B(+,) // (dobimo 2×2 matriko) [[A(+,1)*B(+,1), A(+,2)*B(+,1)],[A(+,1)*B(+,2), A(+,2)*B(+,2)]]
[[28,27],[19,17]]


Podobno velja za stolpce, le da v tem primeru damo vejico pred +.

> A(1,+)*B(2,+) // A(1,1)*B(2,1) + A(1,2)*B(2,2) ; M(stolpec, vrstica)
16
> A(,+)*B(,+)
[[9,11,8],[16,18,13],[23,25,18]]

Iz matrike lahko naredimo vektor dolžine vseh členov matrike (*). Vektor je sestavljen iz vrstic matrike.

> [[1,2,3],[5,7,3]](*)
[1,2,3,5,7,3]

Na matriki lahko, z uporaba simbola (-), izvajamo tudi drugačne operacije.

> [[1,2,3],[6,5,3],[7,9,6]](-) //vrne vektor, ki vsebuje prvo komponento matrike
[1]
> [[1,2,3],[6,5,3],[7,9,6]](-,-) // vrne 2x vgnezdeno prvo komponento
[[1]]
> [[1,2,3],[6,5,3],[7,9,6]](-,-,1:3) // vrne v vektor 2x vgnezdene komponente prve vrstice
[[[1]],[[2]],[[3]]]
> [[1,2,3],[6,5,3],[7,9,6]](-,) // vrne matriko, ki vsebuje, enake komponente, le da so te vgnezdene (stolpec iz komponent matrike)
[[[1],[2],[3]],[[6],[5],[3]],[[7],[9],[6]]]
> [[1,2,3],[6,5,3],[7,9,6]](-,2:6) // vrne v vektor vgnezdene od druge do šeste komponente matrike (stolpec)
[[2],[3],[6],[5],[3]]
> [[1,2,3],[6,5,3],[7,9,6]](,-) // vrne matriko, ki vsebuje vektor s komponentami prve vrstice
[[1,2,3]]
> [[1,2,3],[6,5,3],[7,9,6]](2:6,-) // vrne matriko, ki vsebuje vektor od druge do šeste komponente matrike
[[2,3,6,5,3]]

Ta operacija je uporabna za operiranje med vsemi pari komponent. Recimo, da imamo dva vektorja različnih dolžin. Radi pa bi po parih zmnožili vse njune komponente.

> a=[1,2,3]
> b=[5,2,4,3]
> a*b(-,) // po parih zmnožimo vse komponente, dobimo 4×3 matriko [[a(1)*b(1),a(2)*b(1),a(3)*b(1)],[a(2)*b(1),...
[[5,10,15],[2,4,6],[4,8,12],[3,6,9]]
> b(-,)*a // tako množenje je komutativno
[[5,10,15],[2,4,6],[4,8,12],[3,6,9]]
> a(-,)*b // podobno kot zgoraj, le da sedaj dobimo 3×4 matriko
[[5,2,4,3],[10,4,8,6],[15,6,12,9]]

Namesto množenja bi lahko uporabili tudi kakšno drugo operacijo

> a(-,)+b // komponente seštejemo po parih
[[6,3,5,4],[7,4,6,5],[8,5,7,6]]

Matriko lahko s pomočjo metode span, definiramo tudi na drug način.

> x=span(1,2,3)(-,:1:4) // ustvari 4×3 matriko. Vsaka vrstica je sestavljena iz števil od 1 do 2, razdeljena na 3 dele
[[1,1.5,2],[1,1.5,2],[1,1.5,2],[1,1.5,2]]


Druge metode

Obstaja skupek vgrajenih metod za delo z matrikami:

  • min (najmanjši člen matrike)
  • max (največji člen matrike)
  • ptp (razlika med največjim in najmanjšim členom, lahko tudi negativna)
  • sum (vsota členov)
  • avg (povprečje členov)
  • mnx (indeks najmanjšega člena)
  • cum (kumulativne vsote)
  • ...

Primeri:

> min([[1,2,3],[6,5,3],[7,9,6]]) // vrne najmanjši člen matrike
1
> [[1,2,3],[6,5,3],[7,9,6]](,min) // vrne vektor najmanjših členov po stolpcih
[1,2,3]
> [[1,2,3],[6,5,3],[7,9,6]](min,) // vrne vektor najmanjših členov po vrsticah
[1,3,6]
> [[1,2,3],[6,5,3],[7,9,6]](min,1:2) // vrne vektor najmanjših členov prvih dveh vrstic
[1,3]
> [[1,2,3],[6,5,3],[7,9,6]](1:2,ptp) // vrne vektor razlik med največjim in najmanjšim členom prvih dveh stolpcev
[6,7]

Ostale metode delujejo na enak način.

Fibonaccijevo zaporedje

Recimo, da bi radi s pomočjo Yoricka izračunali poljuben člen Fibonaccijevega zaporedja (1, 1, 2, 3, 5, 8, 13, 21, 34, ...).

Odpremo novo okno in najprej definiramo funkcijo s parametrom n (func fib(n)). Zamikanje v funkciji nima posebnega pomena. Funkcija se začne z { in konča z }. Podobno velja za pogojne stavke in zanke. Napišemo kodo funkcije, ki bo vrnila n-ti člen Fibonaccijevega zaporedja. V zanki (for) bo i tekel od 2 do n. Povečeval se bo za 1 (++i). Na koncu ne smemo pozabiti na konec funkcije }. Datoteko shranimo in jo uvozimo v terminal (#include "datoteka.i"). Nato pa kličemo funkcijo fib(n) (fib(5): 8).

Več si lahko pogledate v filmčku:

Rekurzija

Poljubni člen Fibonaccijevega zaporedja lahko izračunamo tudi rekurzivno.

Več v filmčku:

Približek števila pi

Sestavimo funkcijo, ki izračuna približek za konstanto pi s pomočjo metode Monte Carlo. Funkcija določi n naključnih točk v kvadratu [0,1]×[0,1] in prešteje, koliko jih leži v krogu s središčem v točki (0,0) in polmerom 1. Razmerje med številom točk v krogu in številom vseh točk, za dovolj velike n, mora biti približno pi/4.

(pi.PNG)

Tokrat smo namesto zanke for uporabili zanko while, katera deluje zelo podobno kot v Pythonu. Tudi tukaj je jedro zanke v {...}.

Po klicu funkcije priblizek(n), opazimo, da je približek res skoraj enak številu pi.

Kepanje

Trije otroci Andrej, Borut in Cene mečejo kepe drug v drugega. Kepe mečejo istočasno. Ko je otrok zadet, je izločen iz igre. V tabeli imamo podane verjetnosti prehodov med stanji, ki predstavljajo otroke, ki so pri različnih možnih variantah, še v igri. Izračunajmo povprečno število metov, do zaključka igre.



        ABC      AB      AC      BC

ABC    6/75    10/75    8/75    15/75

AB      0       3/15     0        0

AC      0         0     6/25      0

BC      0         0      0      2/15


Uporabimo matrično metodo. Q odštejemo od identitete I. Nato izračunamo inverz dobljene matrike, katero pomnožimo s stolpcem iz samih enic. Rezultat je prvi člen (saj z igro začnejo vsi trije) dobljenega vektorja.

S pomočjo Yorick-a

(kepanje.PNG)

Zaključek

Prednosti

  • brezplačen
  • veliko vgrajenih funkcij
  • hitro spreminjanje in dostopanje do elementov matrike

Slabosti

  • lahko pride do nepreglednosti kode (vse v črni barvi, zamikanje ni obvezno)
  • dostikrat se "sesuje" (samovoljno zapre)
0%
0%