Predavanje 1: Glave 1 do 3

FlipView[{Text[Style[" Branko Urošević, imqfbrankourosevic@gmail.com ",20,"Text",Italic]],Text[Style[" Faculty of Economics, University of Belgrade, NBS and CESIfo Munich",20,"Text", Italic]]}]

1. Prosta aritmetika

Na ovoj web adresi ćete naći odlična kratka predavanja o ovome što pričamo u prvih 16 predavanja, dakle o programiranju u WL

http://www.wolfram.com/broadcast/c?c=418

Sabiranje brojeva (number addition)

Sada ćemo da naučimo da koristimo Input cells. To su one cool, aktivne ćelije koje nam omogućavaju da nešto izračunamo, nacrtamo, itd. U Input cell kucate izraze koji treba da budu izvršeni (izračunati). Kada ste ih ukucali, kursor treba da je i dalje u toj ćeliji i vi onda pritisnete kombinaciju ⇧+⌤ (dok držite ⇧ pritisnete ⌤). To će proizvesti output ćeliju koja je vezana za tu input ćeliju

2+3

WL je u Output cell izbacila rezultat primene svojih unutrašnjih pravila i uprostila izraz koliko je znala i umela - to će uvek da radi osim ako joj posebno ne naredimo da to ne radi (ali o tome sada nećemo da mislimo). Na taj način, možemo da mislimo o WL softveru između ostalog i kao o gigantskom digitronu. Primetimo da ako samo pritisnemo ⌤ input ćelija neće biti izvršena nego ćemo ući samo u drugi red da dodatno ubacujemo tekst u input ćeliju. Znači, kada želimo da izvršimo input moramo da držimo oba tastera, a ne samo jedan! Evo i malo komplikovanijeg primera sabiranja.

59100+889192

Možemo da sabiramo i simbole, bez da deklarišemo njihovu vrednost

a+b+a

Množenje brojeva

53901*432018

U WL nije neophodno da eksplicitno uneste znak za množenje. Naime, dovoljno je da ostavite razmak između dva množioca i program će podrazumevati da želite da množite (ako ne ostavite razmak, program će misliti da je to jedan broj). Ta je sintaksa ista kao i u običnoj matematici.

920912 512039

Možemo da množimo i realne (decimalne) brojeve

13.091*14.41

kao i simbole

3 a+4 a +2 b

Oduzimanje

6-28

3209092-1209019311

Do sada smo radili sa celim brojevima. Ali, možemo da radimo i takozvanim realnim brojevima, odnosno brojevima sa decimalnom tačkom (kod nas bi to bio decimalni zarez)

12091.3131-123.23090291

A evo i kako možemo da oduzimamo i simbole

a+2 b -5 a-3 b

Deljenje

19/3

Deljenje možemo da predstavimo kako ovako kao gore tako i u takozvanoj 2d input formi (primetimo da 2d forme trenutno ne rade u online verziji Wolfram Language nego samo na desktopu). Ovakav način predstavljanja formula ih čine da liče na način koji koristimo u školi kad učimo razlomke. Da biste napravili razlomak u 2d formatu, koristitie Palettes, pa zatim Basic Math Assistant.

(\[Placeholder]/\[Placeholder])

(19/3)

Alternativno, možete to uneti tako što biste otkucali 19 pa onda Ctrl +/ (to je pritisnete Ctrl i držite dok pritiskate /) pa onda 3.

(19/3)

Stepenovanje

2^10

Da bismo napravili stepenovanje u 2d formatu, možete da koristitie Palettes, pa Basic Math Assistant.

(\[SelectionPlaceholder]^\[Placeholder])

(2^10)

Umesto toga, možete to uraditi i ovako: 2 Ctrl+6  10.

(2^\[Placeholder])

Kvadratni koren

Kvadratni koren je, naravno, nešto na stepen 1/2. Na primer, kvadratni koren iz broja 5 je:

5^(1/2)

Ali za to postoji i 2d input. Možete koristiti ili Palettes Basic Mathematical Inputs ili prečicu Ctrl+2 da napravite

(Sqrt[\[Placeholder]])

Onda u placeholderu stavite 5

(Sqrt[5])

Standardna svojstva kvadratnog korena važe

((((Sqrt[5])))^2)

(Sqrt[5])(Sqrt[2])

Zagrade

Svaki tip zagrade ima posebno značenje u WL, i ne smeju se mešati međusobno. U aritmetici koristimo samo i isključimo malu zagradu (). Na primer:

10-(2+7)2

Poredak izvršenja radnji u WL je isti kao u običnoj aritmetici.

Mnogi specijalni karakteri se mogu dobiti preko prečica sledećeg tipa: Esc characters Esc. Na primer, Esc a Esc daje malo grčko slovo α.

2 α +(10-7)

2. Uvodimo pojam funkcije

O pojmu funkcije

WL je, pre svega, funkcionalni programski jezik. U tom smislu on je idejno blizak, recimo, programskom jeziku R koji se fokusira na statistiku. Šta to znači? To znači da se, tipično, programira tako što se koriste predefinisane funkcije koje se sklapaju u izraze. Najbolje je da to vidimo na primeru.

Kada kucate 2+2, WL to razume kao Plus[2,2]. Plus je funkcija. Primetimo da WL funkcije uvek koriste srednju (uglastu) zagradu posle imena ili glave (Head) funkcije. Te uglaste zagrade ne smeju se koristiti ni za šta drugo nego da definišu mesto gde se ubacuju argumenti funkcije. U ovom slučaju Head je Plus, a 2 i 2 su argumenti funkcije.

Funkcija u WL mora da ima Head ali može imate 0, 1, 2 ili proizvoljno mnogo argumenata (u zavisnosti od toga kako je definišemo). U WL postoji više od 5000 predefinisanih funkcija, a kasnije ćemo učiti kako i sami možemo da ih pravimo odnosno definišemo (Deo 2, odeljak 40). Za aritmetičke operacije potrebno je znati samo mali broj funkcija. Ovde ćemo naučite i o FullForm funkcije. To je način na koji komp zove funkcije i to je zvaničan, rigorozan način da ih zovemo. Sve predefinisane funkcije počinju velikim slovom.

Sabiranje: Plus

Izračunati 3+4 koristeći Plus odnosno koristeću punu formu:

Plus[3,4]

Izračunajte sumu brojeva od 1 do 5 koristeći Plus:

Plus[1,2,3,4,5]

Ovde je Plus glava ili head funkcije a brojevi u srednjoj zagradi su argumenti funkcije Plus. Svaki argument je od drugog odvojen putem zareza. Primetimo da Plus može da ima 0 i više argumenata. Funkcija Head pokazuje glavu nekog izraza.

Head ili glava izraza

Svaki izraz u WL počinje glavom izraza. Evo nekih primera

Head[5]

Head[a]

Head[5.14]

Head[5/14]

Head["ab"]

Head[ab]

Još o funkciji Plus

Šta bismo očekivali da dobijamo u slučaju:

Head[a+b]

Evo i pune forme

FullForm[a+b]

Međutim, ukoliko uradimo

Head[Plus[4,5]]

Zašto je to tako? Zato što u slučaju aritmetičkih radnji WL automatski odmah uprosti izraz (prvo izračuna Plus[4,5], što da ceo broj, ili Integer 9). Pоšto celi brojevi imaju glavu Integer, dobijamo da je glava ovog izraza Integer a ne Plus, kao što bismo očekivali.

Šta se desi ako Plus ima nula argumenata? Ispostavlja se da je to definisano:

Plus[]

Množenje: Times

Funkcija Times služi za množenje brojeva. Pomnožite  3 i 4 koristeći FullForm ili puno formu.

Times[3,4]

Pomnožite 3, 4, and 19 koristeći FullForm

Times[3,4,19]

A šta je defolt za Times ako mu ne damo ni jedan argument?

Times[]

Primetimo razliku između

FullForm[a b]

FullForm[ab]

Oduzimanje: Subtract

A evo kako možemo oduzeti, u FullForm, broj 9 od broja 5

Subtract[5,9]

Primetimo da Subract ima samo 2 argumenta (ni manje ni više). U tom smislu, on je manje fleksibilan nego Plus ili Times koje imaju proizvoljan broj argumenata. Ako bismo probali da stavimo u Subtract 3 argumenta, dobijamo da kompjuter samo oboji u crveno treći argument. Tako nešto nam pokazuje da sintaksa nije dobra.

Subtract[5,9,11]

Šta će biti ako imamo samo jedan argument?

Subtract[5]

Pokazuje nam da nešto fali (crveni znak unutak uglaste zagrade):

Još o funkciji Subtract

Kako bismo onda oduzeli od 5 prvo 9 pa onda 11? Ima puno raznih načina. Na primer, koristeći standardnu matematičku notaciju to je trivijalno:

5-9-11

A kako bismo to uradili u FullForm? Jedan način je da prvo saberemo dva umanjenika (9 i 11) pa ih onda oduzmemo od 5.

Subtract[5,Plus[9,11]]

ili, alternativno, da primernimo Subtract dva puta.

Subtract[Subtract[5,9],11]

Deljenje: Divide

Ako želimo da podelimo dva broja koristimo Divide[]. Ova funkcija takođe ima samo dva moguća argumenta.

Divide[11,2]

Na primer, ovo vodi u sintaksnu grešku:

Divide[11,2,3]

Divide[11]

Poredak deljenja

Podeliti 11 sa 2 a onda taj rezultat podeliti sa 3. Možemo da to uradimo na puno načina:

(11/2)/3

U FullForm to se postiže na sledeći način:

Divide[Divide[11,2],3]

Šta bi se desilo ako izostavimo zagradu? Vidimo da dobijamo isti rezultat.

11/2/3

Ovako možemo da uradimo isto to u 2d formi.

((11/2)/3)

(11/2)

To se može otkucati na sledeći način. Prvo otkucamo 11 Ctrl+/ 2. Onda kursor stavimo van razlomka i dodamo  Ctrl+/ 3.

Nastavak o Divide

Primetimo da se to razlikuje od izraza

(11/(2/3))

Šta je puna forma ovo poslednjeg izraza?

Divide[11,Divide[2,3]]

Drugim rečima, tu se prvo podeli 2 sa tri, pa se tim brojem deli broj 11. Jasno je da je rezultat ove operacije dručaiji od toga kada podelimo prvo 11 sa 2 pa tako dobijeni broj podelimo sa 3. Još jedan način da napravimo Divide[11,Divide[2,3]] jeste da iskoristimo zagradu () koja nam omogućava da odredimo šta se prvo izračunava. Naime:

11/(2/3)

Na osnovu prethodnih primera vidimo da

11/2/3

implicitno podrazumeva da je u pitanju zagrada na početku a ne na kraju, to je da imamo (11/2)/3 a ne 11/(2/3).

Stepenovanje: Power

Podignite 3 na stepen 2:

3^2

U FullForm to glasi:

Power[3,2]

Power[] može da ima proizvoljan broj argumenata veći ili jednak dva. Šta nam daje ovo?

Power[3,]

Još o Power funkciji

Evo raznih načina da izračunamo jedno isto

Power[a,2,3]

a^2^3

(a^(2^3))

A šta bi ovo trebalo da bude?

Times[2,Plus[2,3]]

Kako smo prethodno rekli, sve funkcije u WL imaju Head (glavu) i koriste uglaste ili srednje zagrade za argumente.

Korišćenje zagrada ( )  u aritmetici

Zagrade se u WL mogu koristiti ista kao u običnoj matematici da promene redosled izračunavanja. Za to se uvek koriste isključimo male zagrade ( ). Naime srednja zagrada služi samo za argumente funkcije dok velika zagrada { } služi samo za definisanje liste (o tome malo kasnije). Ovo je veoma važno da znate. Evo primera korišćenja zagrada

4 (5+7)

To je ekvivalentno

Times[4,Plus[5,7]]

Šta bi bilo ako izostavimo zagradu?

4 5+7

To je ekvivalentno

Plus[Times[4,5],7]

Funkcije za maksimum i minimum skupa brojeva: Max i Min

Evo i funkcije koja izracunava maksimum skupa brojeva.

Max[9,2,3,11,6]

Min[9,2,3,11,6]

Primetimo da Max može imati proizvoljan broj argumenata. Probajte ovo:

Max[]

A šta je ovo?

Min[]

Generalno važno je znati ovakvo svojstvo maximuma. Šta bi bilo ovo?

Max[9,2,3,11,c,6]

Kombinovanje Max i Min sa drugim funkcijama

Max i Min možemo kombinovati sa drugim funkcijama. Na primer, da li je veće 7/8 ili 13/15?

Max[7/8, 13/15]

U punoj formi:

Max[Divide[7,8],Divide[13,15]]

Primetimo da se, kao i uvek u običnoj matematici, prvo izračunaju izrazi sa Divide, pa onda se nađe njihov maximum. A šta ako napišemo ovako nešto:

Max[7/8,Min[]]

Naravno, prvo se izračuna 7/8 i Min[]. Pošto je Min[] plus beskonačno, to je naravno veće od 7/8.

Generisanje slučajnog celog broja

A evo i jednostavnog načina da generišemo slučajni ceo broj u dijapazonu od 0 do 100.

RandomInteger[100]

Šta ako izostavimo argument?

RandomInteger[]

U tom slučaju dobijamo slučajne cele brojeve koji su ili 0 ili 1. Da li možemo dobiti više slučajnih celih brojeva odjednom? Možemo ali ćemo se time pozabaviti posle.

O pojmu funkcionalnog programiranja

Primetimo da, kao i u običnoj matematici, mogu da budu u argumentu neke druge funkcije. To su, dakle, složene funkcije. U WL upravo tako se većinom i radi: koristi se, sklapanjem kao Lego kockica, onoliko funkcija koliko nam treba da dobijemo to što želimo. Takav način programiranja naziva se funkcionalno programiranja i WL je taj programski stil doveo do savršenstva.

Funkcionalno programiranje omogućava da se veoma jednostavno rade i najkompleksnije stvari (to ćete svakako imati priliku da vidite kasnije).

3. Prvo upoznavanje sa listama (List)

Šta su liste

Liste su osnovni način da se u WL napravi skup nekih objekata (brojeva, slika, simbola ili neke proizvoljne mešavine svega toga) sa kojim se posle nešto može raditi. List[] je stoga jedna od fundamentalnih funkcija u ovom jeziku. Liste se obično predstavljaju kao skupovi elemenata u velikoj zagradi. Na primer,  {1,2,3} je skup tri broja. Primetimo da se veliku zagrada { }  isključivo koristi za predstavljanje liste i ni zašta drugo u WL. Same po sebi, liste ništa ne rade, samo čuvaju skup nekih stvari. Tako da ako izvrštimo sledeći Input  dobićemo isto što i pre:

{1,2,3,4,a,b,c}

Naravno, ovo je samo uobičajen način da predstavimo listu. FullForm za isto to je:

List[1,2,3,4,a,b,c]

Elementi liste mogu biti bukvalno bilo koji validni izrazi u WL uključujući tu brojeve, simbole, slike, zvuke, filmove, stringove (tekstove) itd. Za sada radimo sa listom brojeva. Možemo lako da ih vizualizujemo.

Grafička za liste: ListPlot

ListPlot je funkcija koja predstavlja listu brojeva kao tačke u 2d. Pri tome, ako se drugačije ne naglasi, pretpostavlja se brojevi sa liste y koordinate tačaka, a implicitno x koordinate su brojevi 1,2,3,... Predstavimo pretko ListPlot listu {1, 1, 2, 2, 3, 4, 4}:

ListPlot[{1,1,2,2,3,4,4}]

Eksplicitnije

ListPlot[List[1,1,2,2,3,4,4]]

Kao defolt, ako damo funkciju ListPlot neku prostu listu, ona podrazumeva da su elementi te liste y (vertikalne) koordinate. A šta su u tom slučaju x koordinate? Sa slike se vidi da je to prosta enumeracija rednog broja podatka iz liste (to jest brojevi 1,2,3,..).

Kako izgleda FullForm ovog izraza?

FullForm[ListPlot[List[1,1,2,2,3,4,4]]]

Glava izraza je Graphics. To je slučaj kada god imamo grafičke objekte u 2 dimenzije.

Range

Jedan moćan način da se pravi lista jeste pomoću Range. To je funkcija koja stvara listu uzastopnih brojeva.

Range[10]

ListPlot[Range[10]]

Reverse obrće redosled elemenata u bilo kojoj listi.Na primer:

Reverse[Range[5]]

ListPlot[Reverse[Range[10]]]

Spajanje lista pomoću Join

Join spaja dve liste praveći jednu listu iz dve. Pri tome, svi elementi ostaju takvi kakvi su bili u posebnim listama. Primetimo da je Join funkcija koja kao argumente uzima jednu ili više lista, a ne brojeve. Na primer

Join[{1,2,3},{4,5},{6,7}]

Join[{1,2,3,2},{2,4,5},{6,2,7}]

Ali zato ovo ne radi:

Join[1,2]

Ovo, međutim, radi. Ovo spaja listu samu sa sobom (to jest ne menja ništa u listi)

Join[{1,2}]

Radi i ovo - spaja dve liste od kojih se svaka sastoji samo od jednog elementa:

Join[{1},{2}]

Napraviti Reverse neke liste

Polazeći od neke liste možemo da je obrnemo u redosledu. Evo primera:

Reverse[{1,17,3}]

U punoj formi to bi bilo:

Reverse[List[1,17,3]]

To možemo primeniti i sa Range

Range[3]

Reverse[Range[3]]

Jedan način da saznamo više o nekoj funkciji: ?ImeFunkcije

Važno je da za svaku funkcija znamo za kakve argumente je definisana. Ali, naravno, ne treba da takve stvari memorišemo. Prost način da to saznamo jeste da otkucamo ?Function. Na primer

?Join

Evo na primer nešto o prethodnim funkcijama koje smo učili:

?Plus

?Subtract

?Divide

?RandomInteger

?Max

?ListPlot

Spajanje lista u punoj formi

U FullForm, Join tri liste bismo predstavili na sledeći način:

Join[List[1,2,3,2],List[2,4,5],List[6,2,7]]

Kada radimo Join dve liste, napomenimo još jednom, ne gubimo ni jedan element listi koji smo imali.

Join[Range[3],Range[5]]

Grafičko predstavljanje spojenih lista pomoću ListPlot

ListPlot[Join[Range[3],Range[5]]]

ListPlot[Join[Range[20],Range[20],Range[30]]]

U ovom primeru, lista u sredini je reverzna:

ListPlot[Join[Range[20],Reverse[Range[20]],Range[30]]]

Join pretvara više lista u jednu listu. Onda ih iscrtava po rednom broju elemenata.

Malo više o ListPlot

A šta bi se desilo ako ne stavimo Join nego probamo, na primer:

ListPlot[Range[20],Reverse[Range[20]]]

To ne radi. Naime, argument ListPlot mora biti lista, a kad stavimo ovako argument NIJE lista. Hajde umesto toga da probamo ovako nešto:

ListPlot[List[Range[20],Reverse[Range[20]]]]

To sada radi. Naime, pošto imamo listu koja se sastoji od dve liste, ListPlot plavom bojom (po defoltu) crta prvu listu, to jest Range[20] a crvenom listu Reverse[Range[20]]. Obe liste se iscrtavaju sada po rednim brojevima nezavisno jedna od druge. Šta bi se desilo ako imamo

ListPlot[List[Reverse[Range[20]],Range[30]]]

A šta bi bilo ako imamo

ListPlot[List[Range[20],Reverse[Range[20]],Range[30]]]

Primetimo da se prva lista (Range[20]) preklopila sa trećom (Range[30]) pa se vidimo sa Range[30].