102
Programski jezici http://www.programskijezici.matf.bg.ac.rs/

Programskijezici · 58 # Naredba iskace iz bloka, isto kao i u C-u # Naredba je ista kao naredba u C-u 60 # Funkcije

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

Programski jezicihttp://www.programskijezici.matf.bg.ac.rs/

Page 2: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

Univerzitet u BeograduMatematički fakultet

Programske paradigmeMaterijali za vežbe

Nastavnik: Milena Vujošević JaničićAsistent: Branislava Živković

Beograd2016.

Page 3: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

Priprema materijala:dr Milena Vujošević Janičić, docent na Matematičkom fakultetu u BeograduMarjana Šolajić, asistent na Matematičkom fakultetu u BeograduBranislava Živković, asistent na Matematičkom fakultetu u Beogradu

Page 4: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije
Page 5: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

Sadržaj

1 Skript programiranje 31.1 Uvod, kolekcije, matematičke funkcije . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.1.1 Uvodni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.1.2 Zadaci za samostalni rad sa rešenjima . . . . . . . . . . . . . . . . . . . . . 71.1.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.2 Datoteke, niske, JSON format, datum . . . . . . . . . . . . . . . . . . . . . . . . . 81.2.1 Uvodni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.2.2 Zadaci za samostalni rad sa rešenjima . . . . . . . . . . . . . . . . . . . . . 101.2.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

1.3 Argumenti komandne linije, sortiranje, obilazak direktorijuma . . . . . . . . . . . . 121.3.1 Uvodni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.3.2 Zadaci za samostalni rad sa rešenjima . . . . . . . . . . . . . . . . . . . . . 141.3.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

1.4 Rešenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2 Programiranje ograničenja - Python 212.1 Programiranje ograničenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.1.1 Uvodni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212.1.2 Zadaci za samostalni rad sa rešenjima . . . . . . . . . . . . . . . . . . . . . 222.1.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.2 Rešenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

3 Funkcionalno programiranje 353.1 Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

3.1.1 Uvodni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353.1.2 Zadaci za samostalni rad sa rešenjima . . . . . . . . . . . . . . . . . . . . . 373.1.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

3.2 Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383.2.1 Uvodni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383.2.2 Zadaci za samostalni rad sa rešenjima . . . . . . . . . . . . . . . . . . . . . 393.2.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

3.3 Funkcije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403.3.1 Uvodni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403.3.2 Zadaci za samostalni rad sa rešenjima . . . . . . . . . . . . . . . . . . . . . 433.3.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

3.4 Rešenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

4 Konkurentno programiranje 494.1 Scala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

4.1.1 Uvod u jezik Scala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494.1.2 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524.1.3 Zadaci za vežbu sa rešenjima . . . . . . . . . . . . . . . . . . . . . . . . . . 544.1.4 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

4.2 Rešenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

v

Page 6: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5 Distribuirano programiranje 715.1 Scala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

5.1.1 Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715.1.2 Zadaci sa rešenjima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 735.1.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

5.2 Rešenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

6 Logičko programiranje 836.1 Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

6.1.1 Uvodni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 836.1.2 Zadaci za samostalni rad sa rešenjima . . . . . . . . . . . . . . . . . . . . . 876.1.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

6.2 Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 896.2.1 Uvodni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 896.2.2 Zadaci za samostalni rad sa rešenjima . . . . . . . . . . . . . . . . . . . . . 906.2.3 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

6.3 Razni zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 916.3.1 Zadaci sa rešenjima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 916.3.2 Zadaci za vežbu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

6.4 Rešenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

1

Page 7: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2

Page 8: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1

Skript programiranje

Potrebno je imati instaliran Python 2.7 na računaru.Literatura:

(a) https://www.python.org/

(b) http://www.tutorialspoint.com/python

(c) https://wiki.python.org/moin/

1.1 Uvod, kolekcije, matematičke funkcije1.1.1 Uvodni primeri

Zadatak 1.1 Ispisivanje pozdravne poruke, komentari.1 # Ovako se pisu komentari

#3 # Pokretanje programa iz terminala:

# $python hello.py5 #

print "Hello world! :)"

Zadatak 1.2 Promenljive, niske, formatiran ispis, učitavanje sa standardnog ulaza, aritmetičkei logičke operacije, naredbe grananja.

2 # Promenljive se dinamicki tipizirajua = 45

4 b = 67.45istina = True

6 # Niske su konstantne tj. nisu promenljive.# To znaci da se menjanjem nekog karaktera u niski

8 # pravi nova niska u memoriji.niska = "I believe i can fly!"

10

# Ispis na standardni izlaz12 print a

print b14 print a, b, istina

16 # Formatiran ispisprint "\n------Formatiran ispis ------\n"

18 print "Ceo broj: {0:d} \nBroj u pokretnom zarezu {1:f}\nBulovska vrednost: {2:b}\nNiska: {3:s}\n".format(a,b,istina,niska)

20

# Ucitavanje niske sa standardnog ulaza22 print "\n------Ucitavanje sa standardnog ulaza ------\n"

string_broj = raw_input("Unesite ceo broj: ")24 broj = int(string_broj) # vrsi se konverzija stringa u ceo broj, slicno: float, str

3

Page 9: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1 Skript programiranje

26 # Osnovne aritmeticke operacije:# +, -, *, /, %, ** (stepenovanje)

28 print "\n------Osnovne aritmeticke operacije ------\n"print broj+4

30

# Osnovne logicke operacije:32 # not, and, or

print "\n------Osnovne logicke operacije ------\n"34 print istina or False

36 # Blokovi se ne ogranicavaju viticastim zagradama kao sto je u C-u# vec moraju biti uvuceni tabulatorom.

38

# Naredba grananja40 print "\n------Naredba granjanja ------\n"

if broj%2 == 0:42 print "Unet je paran broj \n"

elif broj%3 == 0:44 print "Unet je broj deljiv sa 3\n"

# Naredbi <<elif>> moze biti vise46 else:

print "Unet je broj koji nije ni paran ni deljiv sa 3\n"48

# Naredba <<switch>> ne postoji50

# Petlja52 print "\n------Petlja <<while >>------\n"

i=154 while i<=10:

print i56 i=i+1 # i++ ne postoji, moze ili ovako ili i+=1

58 # Naredba <<break>> iskace iz bloka, isto kao i u C-u# Naredba <<pass>> je ista kao naredba <<continue>> u C-u

60

# Funkcije62 #

# def ime_funkcije(argumenti):64 # telo funkcije

#66

def f1(x,y):68 return x+y

70 print f1(2,2)

72 def f2(a):return [a,2*a,3*a]

74

print f2(11.1)

Zadatak 1.3 Moduli math i random.1 # Matematicke funkcije

3 # Ukljucujemo modul <<math>>import math

5

# U ovom moduli se nalaze brojne funkcije kao sto su:7 #

# math.sqrt(broj)9 # math.log(broj, osnova)

# math.sin(ugao_u_radijanima), math.cos(), ...11 # math.exp(stepen)

# math.factorial(broj)13 # i druge...

print "\n------Matematicke funkcije ------\n"15 print math.factorial(6)

print math.log(125, 5)17

# Pseudo slucajni brojevi19

# Ukljucujemo modul <<random>>

4

Page 10: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1.1 Uvod, kolekcije, matematičke funkcije

21 import random

23 # Funkcija random() vraca pseudo slucajan broj tipa float iz opsega [0.0, 1.0)print "\n------Pseudo slucajni brojevi ------\n"

25 print "Pseudo slucajan broj iz opsega [0.0,1.0)\n"print random.random()

27

# Korisne funkcije:29 #

# randint(a,b) - vraca pseudo slucajan ceo broj n iz opsega [a,b]31 # choice(lista) - vraca pseudo slucajan element iz liste

#

Zadatak 1.4 Liste.# LISTA

2 ## Notacija: [element1, element2, ...]

4 ## Liste mogu sadrzati razlicite tipove podataka

6 lista = [1,2,3.4,"Another brick in the wall",True,[5,False,4.4,'Layla']]

8 print "\n------Lista ------\n"print lista

10

# Prazna lista12 prazna = []

14 # Pristupanje elementima listeprint "\n------Pristupanje elementima liste ------\n"

16 # Indeksiranje elemenata listeprint lista[0]

18 print lista[3][1]print lista[0:3]

20 # Mozemo indeksirati liste unazad, pozicija -1 odgovara poslednjem elementuprint lista[-1]

22 # Ukoliko pokusama da pristupimo elementu liste# koji se nalazi na poziciji van opsega interpreter ce nam prijaviti gresku

24 # IndexError: list index out of range# print lista[100]

26

print "\n------Provera da li se element nalazi u listi -----\n"28 if 1 in lista:

print "1 se nalazi u listi\n"30

print "\n------Korisne funkcije za rad sa listama ------\n"32 # Ubacivanje elementa na kraj

print "Ubacivanje elementa na kraj liste\n"34 lista.append(3.14)

print lista36

# Ubacivanje elementa na odredjenu poziciju u listi38 print "\nUbacivanje elementa na odredjenu poziciju u listi\n"

# list.insert(pozicija, element)40 lista.insert(2, "Jana")

print lista42

#44 # Korisne funkcije:

#46 # list.remove(x) - izbacuje prvo pojavljivanje elementa x iz liste

# list.count(x) - vraca broj koliko puta se element x nalazi u listi48 # list.index(x) - vraca indeks prvog pojavljivanja elementa x u listi

# len(lista) - vraca broj elemenata liste50 # del lista[a:b] - brise elemente liste od pozicije a do b

#52 # Nadovezvivanje dve liste

print "\n------Nadovezvivanje dve liste ------\n"54 lista = lista+["Plava", "Zuta", "Crna"]

print lista56

58 # Prolazak kroz listu

5

Page 11: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1 Skript programiranje

print "\n------Prolazak kroz listu petljom <<for>>------\n"60 for i in lista:

print i62

# Poredjenje listi64 #

# Dve liste se porede tako sto se njihovi elementi porede redom leksikografski66 print "\n------Poredjenje listi ------\n"

print "[1,2,3] < [1,2,5]"68 print [1,2,3] < [1,2,5]

print "\n['abc','abc','abc'] < ['abc', 'ab', 'abcd']"70 print ['abc','abc','abc'] < ['abc', 'ab', 'abcd']

print "\n['a','b','c'] > ['a', 'b']"72 print ['a','b','c'] > ['a', 'b']

74

# Koriscenje liste kao stek strukture podataka76 stek = [9,8,7]

# Operacija push je implementirana funkcijom append78 stek.append(6)

stek.append(5)80 print "\n------Ispisujemo stek ------\n"

print stek82 # Operacija pop je implementirana funkcijom pop

print "\n------Ispisujemo element dobijem funkcijom pop------\n"84 print stek.pop()

print "\n------Ispisujemo znanje nakon pozivanja funkcije pop------\n"86 print stek

Zadatak 1.5 Skup, katalog, uređene n-torke.

2 # SKUP#

4 # Pravljenje skupa od listeprint "\n------Pravljenje skupa od liste ------\n"

6 lista1 = [4,56,34,2,5,6,4,4,6]skup = set(lista1)

8

for i in skup:10 print i

12

# Funkcija <<range>>14 #

# range(kraj)16 # range(pocetak, kraj[, korak])

print "\n------Funkcija <<range >>------\n"18 brojevi = range(10)

for i in brojevi:20 print i

22 # KATALOG#

24 # Katalog je kolekcija uredjenih parova oblika (kljuc, vrednost)#

26 # Notacija: {kljuc:vrednost, kljuc:vrednost, ...}print "\n------Katalog ------\n"

28 prazna_mapa = {} # prazna mapa

30 mapa1 = {'a' : 3, 'b' : 4, 'c' : 5}

32 print mapa1

34 mapa = {"kljuc1":67.7, 6:"Vrednost 2"}

36 # Pristupanje elementima u mapiprint "\n------Pristupanje elementima u katalogu ------\n"

38 print mapa['kljuc1']

40 # Prolazak kroz mapuprint "\n------Prolazak kroz katalog ------\n"

42 for kljuc in mapa:

6

Page 12: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1.1 Uvod, kolekcije, matematičke funkcije

print "'{0:s}' => {1:s}\n".format(str(kljuc),str(mapa[kljuc]))44

# Korisne funkcije46 #

# map.keys() - vraca listu kljuceva iz kataloga48 # map.values() - vraca listu vrednosti iz kataloga

# map.has_key(kljuc) - vraca True/False u zavisnosti od toga da li se element50 # sa kljucem kljuc nalazi u katalogu

52 # Uredjene N-TORKEprint "\n------Torke ------\n"

54 torka = ("Daffy","Duck",11)

56 # Pristupanje elementima u torkiprint "\n------Pristupanje elementima u torki ------\n"

58 print torka[1]

60 print "\n------Ispisivanje torke ------\n"print torka

62

# Poredjenje torki64 #

# Dve torke se porede tako sto se njihovi elementi porede redom leksikografski66 print "\n------Poredjenje torki ------\n"

print "(1,2,'a') < (1,2,'b')"68 print (1,2,'a') < (1,2,'b')

print "\n([1,2,3], 'Bugs', 4) < ([1,1,1], 'Bunny', 6)"70 print ([1,2,3], 'Bugs', 4) < ([1,1,1], 'Bunny', 6)

# Ukoliko torke ne sadrze elemente istog tipa na istim pozicijama, i dalje ih mozemoporediti,

72 # ali poredjenje se vrsi na osnovu imena tipa elementa leksikografski# npr. element tipa List < element tipa String < element tipa Tuple i slicno

74 print "\n(1,2,['a','b']) < (1,2,'ab')"print (1,2,['a','b']) < (1,2,'ab')

1.1.2 Zadaci za samostalni rad sa rešenjima

Zadatak 1.6 Pogodi broj Napisati program koji implementira igricu ”Pogodi broj”.Na početku igre računar zamišlja jedan slučajan broj u intervalu [0,100]. Nakon toga igrač unosisvoje ime i započinje igru. Igrač unosi jedan po jedan broj sve dok ne pogodi koji broj je računarzamislio. Svaki put kada igrač unese broj, u zavisnosti od toga da li je broj koji je unet veći ilimanji od zamišljenog broja ispisuje se odgovarajuća poruka. Igra se završava u trenutku kada igračpogodio zamišljen broj.

[Rešenje 1.6]

Zadatak 1.7 Aproksimacija broja PI metodom Monte Karlo Napisati programkoji aproksimira broj PI koriscenjem metode Monte Karlo. Sa standardnog ulaza unosi se broj N.Nakon toga N puta se bira tačka na slučajan način tako da su obe koordinate tačke iz intervala[0,1]. Broj PI se računa po sledecoj formuli:

PI = 4 ∗A/B

• A je broj slučajno izabranih tačaka koje pripadaju krugu poluprečnika 0.5, sa centrom utački (0.5, 0.5)

• B je broj slučajno izabranih tačaka koje pripadaju kvadratu čija temena su tačke (0, 0), (0, 1), (1, 1), (1, 0).

[Rešenje 1.7]

Zadatak 1.8 X-O Napisati program koji implementira igricu X-O sa dva igrača.

[Rešenje 1.8]

7

Page 13: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1 Skript programiranje

1.1.3 Zadaci za vežbu

Zadatak 1.9 Anjc Napisati program koji implementira igricu Anjc sa jednim igračem.Igra se sa špilom od 52 karte. Na početku igrač unosi svoje ime nakon čega računar deli dve karteigraču i dve karte sebi. U svakoj sledećoj iteraciji računar deli po jednu kartu igraču i sebi. Ciljigre je sakupiti karte koje u zbiru imaju 21 poen. Karte sa brojevima nose onoliko bodova koliki jebroj, dok žandar, dama, kralj nose 10 bodova. Karta As može da nosi 1 ili 10 bodova, u zavisnostiod toga kako igraču odgovara. Igrač koji sakupi 21 je pobedio. Ukoliko igrač premaši 21 bod,pobednik je njegov protivnik. https://en.wikipedia.org/wiki/Blackjack

Zadatak 1.10 4 u liniji Napisati program koji implementira igricu 4 u nizu sa dvaigrača. Tabla za igru je dimenzije 8x8. Igrači na početku unose svoja imena, nakon čega računarnasumično dodeljuje crvenu i žutu boju igračima. Igrač sa crvenom bojom igra prvi i bira kolonuu koju ce da spusti svoju lopticu. Cilj igre je da se sakupe 4 loptice iste boje u liniji. Prvi igračkoji sakupi 4 loptice u liniji je pobedio. https://en.wikipedia.org/wiki/Connect_Four

1.2 Datoteke, niske, JSON format, datum1.2.1 Uvodni primeri

Zadatak 1.11 Funkcije za rad sa niskama.

# Niske2 #

# Mozemo ih pisati izmedju jednostrukih i dvostrukih navodnika4

niska1 = 'Ovo je neka niska.'6 niska2 = "People are strange when you're a stranger ."

8 print "\n------Niske ------\n"print niska1

10 print niska2

12 # Karakterima u niski mozemo pristupati koristeci notaciju [] kao kod listiprint "\n------Pristupanje karakterima u niski ------\n"

14 print niska2[4]print niska2[6:10]

16

# Duzinu niske racunamo koristeci funkciju len(niska)18 print "\n------Duzina niske ------\n"

print len(niska1)20

# Funkcija count22 # niska.count(podniska [, pocetak [, kraj]]) - vraca broj koliko se puta

# podniska nalazi u niski (u intervalu od pocetak do kraj)24 print "\n------Funkcija <<count >>------\n"

print niska2.count("strange")26

# Funkcija find28 # niska.find(podniska [, pocetak [, kraj]]) - vraca poziciju prvog pojavljivanja

# podniska u niski (u intervalu od pocetak do kraj), -1 ukoliko se podniska ne nalaziu niski

30 print "\n------Funkcija <<find>>------\n"print niska2.find("are")

32

# Funkcija join34 # niska_separator.join([niska1,niska2,niska3 ,...]) - spaja listu niski separatorom

print "\n------Funkcija <<join>>------\n"36 print ' '.join(["Olovka",'pise','srcem.'])

38

# Korisne funkcije za rad sa niskama:40 #

# niska.isalnum()42 # isalpha()

# isdigit()44 # islower()

8

Page 14: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1.2 Datoteke, niske, JSON format, datum

# isspace()46 # isupper()

# niska.split(separator) - razlaze nisku u listu koristeci separator48 # niska.replace(stara, nova [, n]) - zamenjuje svako pojavljivanje niske stara

# niskom nova (ukoliko je zadat broj n, onda zamenjuje najvise n pojavljivanja)

Zadatak 1.12 Datoteke.1 # Datoteke

#3 # Datoteku otvaramo koristeci funkciju

#5 # open(ime_datoteke, mod)

#7 # mod: "r" -> read, "w" -> write, "a" -> append, "r+" -> read + append

#9 # Datoteku zatvaramo koristeci funkciju

#11 # datoteka.close()

13 f = open("dat1.txt","r")

15 # f.read(n) cita n karaktera iz datotekeprint "\n-----Funkcija <<read >>-----\n"

17 while True:c = f.read(2)

19 if c == '':break

21 print c

23 # f.readline() cita jednu liniju iz Datotekef.close()

25

g = open("dat2.txt","r")27

# Liniju po liniju mozemo ucitavati koristeci petlju29 # tako sto 'iteriramo' kroz Datoteku

print "-----Iteriranje kroz datoteku <<for>> petljom -----\n"31 for linija in g:

print linija33

g.close()35 # f.readlines() i list(f)

# vracaju listu linija datoteke37 #

# f.write(niska) upisuje nisku u datoteku39 print "-----Upisivanje u datoteku -----\n"

h = open("dat3.txt","r+")41 h.write("water\n")

43 print h.readlines()

45 h.close()

Zadatak 1.13 Modul datetime.1 # Datumi

3 # Ukljucujemo klasu datetime iz modula datetime

5 from datetime import datetime

7 # Nov objekat datuma:#

9 # datetime.datetime(godina, mesec, dan [, sat [, minut [, sekund]]])#

11 # Korisne funkcije:#

13 # datetime.now() - vraca trenutno vreme odnosno datum# datetime.strptime(datum_niska, format)

15 # datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute,datetime.second,

9

Page 15: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1 Skript programiranje

# datetime.strftime(format) - vraca string reprezentaciju objekta datuma na osnovuzadatog formata

17 # datetime.strptime(niska, format) - vraca objekat datetime konstruisan na osnovuniske u zadatom formatu

# datetime.time([sat [, minut [, sekund]]]) - vraca objekat koji predstavlja vreme19 # datetime.date(dan, mesec, godina) - vraca objekat datuma

# format:21 # %A - dan u nedelji (Monday, Tuesday ,...)

# %w - dan u nedelji (0, 1, 2,..., 6)23 # $d - dan (01, 02, 03,...)

# %B - mesec (January, February ,...)25 # %m - mesec (01, 02, ...)

# %Y - godina (1992, 1993,...)27 # %H - sat (00, 01, ..., 23)

# %M - minut (00, 01, ..., 59)29 # %S - sekund (00, 01, ..., 59)

#31

33

print "\n-----Datumi -----\n"35 print datetime.now().strftime("Dan u nedelji: %a/%w, Dan: %d, Mesec: %b/%m, Godina: %

y, Vreme: %H:%M:%S\n")print datetime.now().time()

37 print datetime.now().date()

Zadatak 1.14 JSON format.

1 # JSON format#

3 # Funkcije za rad sa JSON formatom se nalaze u modulu jsonimport json

5

# json.dumps(objekat) vraca string koji sadrzi JSON reprezentaciju objekta x7

print "\n-----JSON reprezentacija objekta -----\n"9 junak = {"Ime":"Dusko", "Prezime":"Dugousko", "Godine":11}

print json.dumps(junak)11

# json.dump(x,f) upisuje string sa JSON reprezentacijom objekta x u datoteku f13

f = open("dat4.json","w")15 json.dump(junak,f)

f.close()17

# json.load(f) ucitava iz datoteke string koji sadrzi JSON format objekta i vracaobjekat

19 print "\n-----Ucitavanje objekta iz datoteke -----\n"f = open("dat4.json","r")

21 x = json.load(f)print x['Ime']

23 print x['Prezime']print x['Godine']

25 f.close()

1.2.2 Zadaci za samostalni rad sa rešenjima

Zadatak 1.15 Napisati program koji sa standardnog ulaza učitava ime datoteke i broj n iračuna broj pojavljivanja svakog n-grama u datoteci koji su sačinjeni od proizvoljnih karaktera irezultat upisuje u datoteku rezultat.json.

Na primer:

Listing 1.1: dat.txt

1 Ovo je datoteka dat

Listing 1.2: rezultat.json

10

Page 16: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1.2 Datoteke, niske, JSON format, datum

1 {2 'a ': 1, 'ka': 1, 'ot': 1, 'ek': 1,3 ' d': 2, ' j': 1, 'da': 2, 'e ': 1,4 'o ': 1, 'to': 1, 'at': 2, 'je': 1,5 'Ov': 1, 'te': 1, 'vo': 16 }

[Rešenje 1.15]

Zadatak 1.16U datoteci korpa.json se nalazi spisak kupljenog voća u json formatu:

1 [ { 'ime' : ime_voca, 'kolicina' : broj_kilograma } , ...]

U datotekama maxi_cene.json, idea_cene.json, shopngo_cene.json se nalaze cene voća u jsonformatu:

1 [ { 'ime' : ime_voca, 'cena' : cena_po_kilogramu } , ...]

Napisati program koji izračunava ukupan račun korpe u svakoj prodavnici i ispisuje cene na stan-dardni izlaz.

[Rešenje 1.16]

1.2.3 Zadaci za vežbu

Zadatak 1.17 Napisati program koji iz datoteke ispiti.json učitava podatke o ispitimai njihovim datumima. Ispisati na standardni izlaz za svaki ispit njegovo ime i status ”Prosao”ukoliko je ispit prosao, odnosno ”Ostalo je jos n dana.”, gde je n broj dana od trenutnog datumado datuma ispita.

Listing 1.3: ispiti.json

1 [ {'ime': 'Relacione baze podataka',2 'datum': '21.09.2016.'},3 {'ime': 'Vestacka inteligencija ',4 'datum': '17.06.2017.'},5 {'ime': 'Linearna algebra i analiticka geometrija ',6 'datum': '08.02.2017.'} ]

Zadatak 1.18 Napisati program koji izdvaja sve jednolinijske i višelinijske komentare iz .cdatoteke čije ime se unosi sa standardnog ulaza, listu jednih i drugih komentara upisuje u datotekukomentari.json. Jednolinijski komentari se navode nakon // a višelinijski između /∗ i ∗/.

Listing 1.4: program.c

#include <stdio.h>2

// Primer jednolinijskog komentara4

int main(){6 /*

Na ovaj nacin ispisujemo tekst8 na standardni izlaz koristeci jezik C.

*/10 printf("Hello world!");

12 // Na ovaj nacin se ispisuje novi redprintf("\n");

14 /*Ukoliko se funkcija uspesno zavrsila

16 vracamo 0 kao njen rezultat.

11

Page 17: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1 Skript programiranje

*/18 return 0;

}

Listing 1.5: komentari.json

1 {2 'jednolinijski ' : ['Primer jednolinijskog komentara ',3 'Na ovaj nacin se ispisuje novi red'],4 'viselinijski ' : ['Na ovaj nacin ispisujemo tekst na standardni5 izlaz koristeci jezik C.',6 'Ukoliko se funkcija uspesno zavrsila7 vracamo 0 kao njen rezultat.']8 }

Zadatak 1.19 Napisati program upoređuje dve datoteke čija imena se unose sa standardnogulaza. Rezultat upoređivanja je datoteka razlike.json koja sadrži broj linija iz prve datotekekoje se ne nalaze u drugoj datoteci i obratno. Napomena Obratiti pažnju na efikasnost.

Listing 1.6: dat1.txt

//netacno2

same=1;4

for(i=0;s1[i]!='\0' && s2[i]!='\0';i++) {6 if(s1[i]!=s2[i]) {

same=0;8 break;

}10 }

return same;

Listing 1.7: dat2.txt

1 //tacno

3 for(i=0;s1[i]!='\0' && s2[i]!='\0';i++){

5 if(s1[i]!=s2[i])return 0;

7 }return s1[i]==s2[i];

Listing 1.8: razlike.json

1 {2 'dat1.txt' : 7,3 'dat2.txt' : 44 }

1.3 Argumenti komandne linije, sortiranje, obilazak direk-torijuma

1.3.1 Uvodni primeri

Zadatak 1.20 Modul sys i argumenti komandne linije# modul sys ima definisan objekat argv koji predstavlja listu argumenata komandne

linije (svi argumenti se cuvaju kao niske karaktera)2

12

Page 18: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1.3 Argumenti komandne linije, sortiranje, obilazak direktorijuma

import sys4

if len(sys.argv)==1:6 print "Niste naveli argumente komandne linije"

# funkcija exit() iz modula sys prekida program8 # (ukoliko se ne prosledi argument, podrazumevano

# se salje None objekat)10 exit()

12 # ispisujemo argumente komandne linije# prvi argument, tj. sys.argv[0] je uvek ime skript fajla koji se pokrece

14 for item in sys.argv:print item

16

# korisnik moze da zada ime datoteke kao prvi argument komandne linije18 # u tom slucaju datoteku otvaramo sa f = open(sys.argv[1], "r")

Zadatak 1.21 Modul os# Prolazak kroz direktorijume

2

import os4 # ispisuje oznaku za tekuci direktorijum

print os.curdir6 # ispisuje oznaku za roditeljski direktorijum tekuceg direktorijuma

print os.pardir8 # ispisuje separator koji koristi za pravljenje putanja

print os.sep10

12 # funkcija za prosledjenu putanju direktorijuma vraca listu imena svih fajlova u tomdirektorijumu, . je zamena za putanju tekuceg direktorijuma

14 print os.listdir(".")

16 ## os.walk() - vraca listu torki (trenutni_direktorijum , poddirektorijumi, datoteke)

18 # os.path.join(putanja, ime) - pravi putanju tako sto nadovezuje na prosledjenuputanju zadato ime odvojeno /

20 print "\n-----Prolazak kroz zadati direktorijum -----\n"for (trenutni_dir , poddirektorijumi , datoteke) in os.walk("."):

22 print trenutni_dirfor datoteka in datoteke:

24 print os.path.join(trenutni_dir , datoteka)

26 # os.path.abspath(path) - vraca apsolutnu putanju za zadatu relativnu putanju nekogfajla

# os.path.isdir(path) - vraca True ako je path putanja direktorijuma, inace vracaFalse

28 # os.path.isfile(path) - vraca True ako je path putanja regularnog fajla, inace vracaFalse

30 print "\n-----Regularni fajlovi zadatog direktorijuma -----\n"for ime in os.listdir("."):

32 # ako je regularan fajl u pitanju ispisujemo njegovu apsolutnu putanjuif os.path.isfile(os.path.join(".", ime)):

34 print os.path.abspath(os.path.join(".", ime))

Zadatak 1.22 Sortiranje1 # Sortiranje

#3 # sorted(kolekcija [, poredi [, kljuc [, obrni]]]) - vraca sortiranu kolekciju

#5 # kolekcija - kolekcija koju zelimo da sortiramo

# poredi - funkcija poredjenja7 # kljuc - funkcija koja vraca kljuc po kome se poredi

# obrni - True/False (opadajuce/rastuce)9 #

# za poziv sorted(kolekcija) koristi se funkcija cmp za poredjenje11 # cmp(x, y) -> integer

13

Page 19: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1 Skript programiranje

# vraca negativnu vrednost za x<y, 0 za x==y, pozitivnu vrednost za x>y13 # ako su x i y niske, cmp ih leksikografski poredi

#15

import json17 import math

19 l = ["A", "C", "D", "5", "1", "3"]print l

21 print "sortirana lista: ", sorted(l)

23 # u sledecem primeru je neophodno da definisemo svoje funkcije za poredjenje ivracanje kljuca jer je kolekcija lista recnika i za to cmp nema definisanoponasanje

tacke = [{"teme":"A" , "koordinate": [10.0, 1.1]}, {"teme":"B" , "koordinate": [1.0,15.0]}, {"teme":"C" , "koordinate": [-1.0, 5.0]}]

25

27 # funkcija koja tacke x i y poredi po njihovoj udaljenosti od koordinatnog pocetkadef poredi(x,y):

29 if (x[0]*x[0] + x[1]*x[1]) > (y[0]*y[0] + y[1]*y[1]):return 1

31 else:return -1

33 # funkcija kljuc kao argument ima element kolekcije koja se poredi, u ovom slucaju jeto jedan recnik

# povratna vrednost funkcije kljuc je u stvari tip argumenata funkcije poredi35 def kljuc(x):

return x["koordinate"]37

sortirane_tacke = sorted(tacke, poredi, kljuc) # ili sorted(tacke, poredi, kljuc,True) ako zelimo opadajuce da se sortira

39 print "Tacke pre sortiranja:"for item in tacke:

41 print item["teme"],print "\nTacke nakon sortiranja: "

43 for item in sortirane_tacke:print item["teme"],

45 print

1.3.2 Zadaci za samostalni rad sa rešenjima

Zadatak 1.23 Napisati program koji računa odnos kardinalnosti skupova duže i šire za za-dati direktorijum. Datoteka pripada skupu duže ukoliko ima više redova od maksimalnog brojakaraktera po redu, u suprotnom pripada skupu šire. Sa standardnog ulaza se unosi putanja dodirektorijuma. Potrebno je obići sve datoteke u zadatom direktorijumu i njegovim poddirektoriju-mima (koristiti funkciju os.walk()) i ispisati odnos kardinalnosti skupova duže i šire.

[Rešenje 1.23]

Zadatak 1.24 Napisati program koji obilazi direktorijume rekurzivno i računa broj datotekaza sve postojeće ekstenzije u tim direktorijumima. Sa standardnog ulaza se unosi putanja dopočetnog direktorijuma, a rezultat se ispisuje u datoteku rezultat.json. Na primer:

Listing 1.9: rezultat.txt

1 {2 'txt' : 14,3 'py' : 12,4 'c' : 105 }6

[Rešenje 1.24]

Zadatak 1.25 U datoteci radnici.json nalaze se podaci o radnom vremenu zaposlenih upreduzeću u sledecem formatu:

14

Page 20: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1.4 Rešenja

1 [ { 'ime' : 'Pera Peric',2 'odmor' : ['21.08.2016.', '31.08.2016.'],3 'radno_vreme ' : ['08:30', '15:30'] }, ...]

Napisati program koji u zavisnosti od unete opcije poslodavcu ispisuje trenutno dostupne radnikeodnosno radnike koji su na odmoru. Moguće opcije su ’d’ - trenutno dostupni radnici i ’o’ - radnicikoji su na odmoru. Radnik je dostupan ukoliko nije na odmoru i trenutno vreme je u okvirunjegovog radnog vremena.

[Rešenje 1.25]

Zadatak 1.26 Napisati program koji učitava ime datoteke sa standardnog ulaza i na stan-dardni izlaz ispisuje putanje do svih direktorijuma u kojima se nalazi ta datoteka.

[Rešenje 1.26]

1.3.3 Zadaci za vežbu

Zadatak 1.27 Napisati program koji ispisuje na standardni izlaz putanje do lokacija svihApache virtuelnih hostova na računaru. Smatrati da je neki direktorijum lokacija Apache virtuel-nog hosta ukoliko u sebi sadrži index.html ili index.php datoteku.

Zadatak 1.28 Napisati program koji realizuje autocomplete funkcionalnost. Sa standardnogulaza korisnik unosi delove reči sve dok ne unese karakter !. Nakon svakog unetog dela reči ispisujuse reči koje počinju tim karakterima. Spisak reči koje program može da predloži se nalazi u datotecireci.txt.

1.4 Rešenja

Rešenje 1.6 Pogodi broj

1 # Pogodi broj

3 import random

5 print "-------- IGRA: Pogodi broj ---------\n"

7 zamisljen_broj = random.randint(0,100)

9 ime = raw_input("Unesite Vase ime: ")

11 print "Zdravo {0:s}. :) \nZamislio sam neki broj od 1 do 100. Da li mozes da pogodiskoji je to broj? ".format(ime)

13 pogodio = 0;while not pogodio:

15 print "Unesi broj:"broj = int(raw_input())

17 if broj == zamisljen_broj:pogodio = 1

19 elif broj > zamisljen_broj:print "Broj koji sam zamislio je MANJI od {0:d}.".format(broj)

21 else:print "Broj koji sam zamislio je VECI od {0:d}.".format(broj)

23

print "BRAVO!!! Pogodio si! Zamislio sam {0:d}. Bilo je lepo igrati se sa tobom. :)".format(zamisljen_broj)

Rešenje 1.7 Aproksimacija broja PI metodom Monte Karlo

15

Page 21: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1 Skript programiranje

# Aproksimacija broja PI metodom Monte Karlo2

4 import random

6 print "Izracunavanje broja PI metodom Monte Karlo \n"N = int(raw_input("Unesite broj iteracija: "))

8 # Broj tacaka koje se nalaze u kruguA = 0

10 # Broj tacaka koje se nalaze u kvadratuB = 0

12

i = N14 while i >= 0:

tacka = (random.random(), random.random())16 print "Tacka: "

print tacka18 # Ukoliko se tacka nalazi u krugu, povecavamo broj tacaka u krugu

if ((float(tacka[0])-0.5)**2 + (float(tacka[1])-0.5)**2) < (0.5**2):20 A = A + 1

B = B + 122 i = i - 1

24 print "Broj PI aproksimiran metodom Monte Karlo: "print 4.0*A/B

Rešenje 1.8 X-O

1 # X-O#

3 # - | O | X# --- --- ---

5 # X | - | -# --- --- ---

7 # - | X | O

9 import random

11 def ispisi_tablu(tabla):print "\n TABLA \n"

13 print " 1 2 3 "print " --- --- --- "

15 indeks = 1for i in tabla:

17 print indeks,"|",i[0],"|",i[1],"|",i[2],"|"print " --- --- --- "

19 indeks = indeks + 1print "\n"

21

def pobedio(tabla):23 if (tabla[0][0] != "-" and tabla[0][2] != "-") and ((tabla[0][0] == tabla[1][1]

== tabla[2][2]) or (tabla[0][2] == tabla[1][1] == tabla[2][0])):return True

25 for i in range(3):if (tabla[0][i] != "-" and tabla[i][0] != "-") and ((tabla[0][i] == tabla[1][

i] == tabla[2][i]) or (tabla[i][0] == tabla[i][1] == tabla[i][2])):27 return True

return False29

def ucitaj_koordinate(ime):31 while True:

print "{0:s} unesite koordinate polja koje zelite da popunite u posebnimlinijama:\n".format(ime)

33 x = int(raw_input("Unesite vrstu: "))y = int(raw_input("Unesite kolonu: "))

35 if 1<=x<=3 and 1<=y<=3:return x-1,y-1

37 else:"Morate uneti brojeve 1,2 ili 3\n"

39

def korak(igrac):

16

Page 22: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1.4 Rešenja

41 while True:x,y = ucitaj_koordinate(igrac[0])

43 if tabla[x][y] == "-":tabla[x][y] = igrac[1]

45 ispisi_tablu(tabla)break

47 else:print tabla[x][y]

49 print "Uneto polje je popunjeno!\n"

51 print "IGRA: X-O pocinje\n"

53 ime1 = raw_input("Unesite ime prvog igraca: ")print "Zdravo {0:s}!\n".format(ime1)

55 ime2 = raw_input("Unesite ime drugog igraca: ")print "Zdravo {0:s}!\n".format(ime2)

57

indikator = random.randint(1,2)59 if indikator == 1:

prvi_igrac = (ime1, "X")61 drugi_igrac = (ime2, "O")

else:63 prvi_igrac = (ime2, "X")

drugi_igrac = (ime1, "0")65

print "Igrac {0:s} igra prvi. \n".format(prvi_igrac)67 print "X : {0:s}\n".format(prvi_igrac)

print "O : {0:s}\n".format(drugi_igrac)69

tabla = [['-','-','-'],['-','-','-'],['-','-','-']]71

print "Zapocnimo igru \n"73

ispisi_tablu(tabla)75

na_redu = 077 iteracija = 0

igraci = [prvi_igrac , drugi_igrac]79 while iteracija < 9:

korak(igraci[na_redu])81 if pobedio(tabla) == True:

print "BRAVO!!!!!!! {0:s} je pobedio!\n".format(igraci[na_redu][0])83 break

na_redu = (na_redu+1)%285 iteracija = iteracija + 1

87 if iteracija == 9:print "NERESENO! Pokusajte ponovo.\n"

Rešenje 1.15

# dat.txt:2 # Ovo je datoteka dat

#4 # rezultat.json:

#6 # {"a ": 1, "ka": 1, "ot": 1, "ek": 1, " d": 2, " j": 1, "da": 2, "e ": 1, "o ": 1, "

to": 1, "at": 2, "je": 1, "Ov": 1, "te": 1, "vo": 1}

8 import json

10 ime_datoteke = raw_input("Unesite ime datoteke: ")n = int(raw_input("Unesite broj n: "))

12

# Otvaramo datoteku i citamo njen sadrzaj14 f = open(ime_datoteke , "r")

sadrzaj = f.read()16 f.close()

18 recnik = {}i = 0

20 # Prolazimo kroz sadrzaj i uzimamo jedan po jedan n-gram

17

Page 23: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1 Skript programiranje

while i < len(sadrzaj) - n:22 ngram = sadrzaj[i : i+n]

# Ukoliko se n-gram vec nalazi u recniku,24 # povecavamo mu broj pojavljivanja

if ngram in recnik:26 recnik[ngram] = recnik[ngram]+1

# Dodajemo n-gram u recnik i postavljamo mu broj na 128 else:

recnik[ngram] = 130 i = i + 1

32 f = open("rezultat.json", "w")json.dump(recnik,f)

34 f.close()

Rešenje 1.16

1 import json

3 def cena_voca(prodavnica , ime_voca):for voce in prodavnica:

5 if voce['ime'] == ime_voca:return voce['cena']

7

# Ucitavamo podatke iz datoteka9 f = open('korpa.json', "r")

korpa = json.load(f)11 f.close()

13 f = open('maxi_cene.json', "r")maxi_cene = json.load(f)

15 f.close()

17 f = open('idea_cene.json', "r")idea_cene = json.load(f)

19 f.close()

21 f = open('shopngo_cene.json', "r")shopngo_cene = json.load(f)

23 f.close()

25 maxi_racun = 0idea_racun = 0

27 shopngo_racun = 0i = 0

29 # Za svako voce u korpi dodajemo njegovu cenu u svaki racun posebnowhile i < len(korpa):

31 ime_voca = korpa[i]['ime']maxi_racun = maxi_racun + korpa[i]['kolicina']*cena_voca(maxi_cene, ime_voca)

33 idea_racun = idea_racun + korpa[i]['kolicina']*cena_voca(idea_cene, ime_voca)shopngo_racun = shopngo_racun + korpa[i]['kolicina']*cena_voca(shopngo_cene ,ime_voca)

35 i += 1

37 print "Maxi: " + str(maxi_racun) + " dinara"print "Idea: " + str(idea_racun) + " dinara"

39 print "Shopngo: " + str(shopngo_racun) + " dinara"

Rešenje 1.23

1

import os3

dat_u_duze = 05 dat_u_sire = 0

7 # Funkcija koja obilazi datoteku i vraca 1 ukoliko datoteka pripada skupu duze# odnosno 0 ukoliko datoteka pripada skupu sire

9 def obilazak(ime_datoteke):br_linija = 0

18

Page 24: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1.4 Rešenja

11 najduza_linija = 0f = open(ime_datoteke , "r")

13 for linija in f:br_linija = br_linija + 1

15 if len(linija) > najduza_linija:najduza_linija = len(linija)

17 f.close()if br_linija > najduza_linija:

19 return 1else:

21 return 0

23 ime_direktorijuma = raw_input("Unesite putanju do direktorijuma: ")

25 for (tren_dir, pod_dir, datoteke ) in os.walk(ime_direktorijuma):for dat in datoteke:

27 if obilazak(os.path.join(tren_dir, dat)) == 0:dat_u_sire += 1

29 else:dat_u_duze += 1

31

print "Kardinalnost skupa duze: kardinalnost skupa sire"33 print str(dat_u_duze)+":"+str(dat_u_sire)

Rešenje 1.24

1

import os3 import json

5 ime_direktorijuma = raw_input("Unesite putanju do direktorijuma: ")

7 ekstenzije = {}

9 for (tren_dir, pod_dir, datoteke ) in os.walk(ime_direktorijuma):for dat in datoteke:

11 pozicija = dat.find(".")# Ukoliko datoteka ima ekstenziju, pretpostavljamo da su datoteke imenovane

tako da posle . ide ekstenzija u ispravnom obliku13 if pozicija >= 0:

# Ukoliko ekstenzija postoji u mapi, povecavamo njen broj15 if dat[pozicija:] in ekstenzije:

ekstenzije[dat[pozicija:]] += 117 else:

# Dodajemo novu ekstentiju u mapu i postavljamo njen broj na 119 ekstenzije[dat[pozicija:]] = 1

21 f = open("rezultat.json","w")json.dump(ekstenzije , f)

23 f.close()

Rešenje 1.25

1 import json, osfrom datetime import datetime

3

f = open("radnici.json", "r")5 radnici = json.load(f)

f.close()7

opcija = raw_input("Unesite opciju koju zelite (d - dostupni radnici , o - radnici naodmoru): \n")

9

if opcija != "d" and opcija != "o":11 print "Uneta opcija nije podrzana."

exit()13

tren_dat = datetime.now()15

19

Page 25: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

1 Skript programiranje

# funkcija datetime.strptime(string, format) pravi objekat tipa datetime na osnovuzadatih podataka u stringu i odgovarajuceg formata, na primer ako je datumzapisan kao "21.08.2016" odgovarajuci format je "%d.%m.%Y." pa se funkcija pozivasa datetime.strptime("21.08.2016", "%d.%m.%Y.")

17

for radnik in radnici:19 kraj_odmora = datetime.strptime(radnik['odmor'][1],"%d.%m.%Y.").date()

pocetak_odmora = datetime.strptime(radnik['odmor'][0],"%d.%m.%Y.").date()21 kraj_rad_vrem = datetime.strptime(radnik['radno_vreme'][1],"%H:%M").time()

pocetak_rad_vrem = datetime.strptime(radnik['radno_vreme'][0],"%H:%M").time()23 if opcija == "o":

# Ukoliko je radnik trenutno na odmoru ispisujemo ga25 if pocetak_odmora < tren_dat.date() < kraj_odmora:

print radnik["ime"]27 else:

# Ukoliko je radnik trenutno dostupan i nije na odmoru, ispisujemo ga29 if not (pocetak_odmora < tren_dat.date() < kraj_odmora) and pocetak_rad_vrem

< tren_dat.time() < kraj_rad_vrem:print radnik["ime"]

Rešenje 1.26

import os2

ime_datoteke = raw_input("Unesite ime datoteke: ")4

# pretrazujemo ceo fajl sistem, odnosno pretragu krecemo od root direktorijuma /6 # imajte u vidu da ce vreme izvrsavanja ovog programa biti veliko posto se pretrazuje

ceo fajl sistem, mozete ga prekinuti u svakom trenutku sa CTRL+Cfor (tren_dir, pod_dir, datoteke ) in os.walk("/"):

8 # objekat datoteke predstavlja listu imena datoteka iz direktorijuma# ta imena poredimo sa zadatim

10 for dat in datoteke:# ako smo naisli na trazenu datoteku, pravimo odgovarajucu putanju

12 if dat == ime_datoteke:print os.path.join(os.path.abspath(tren_dir), ime_datoteke)

20

Page 26: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2

Programiranje ograničenja -Python

Potrebno je imati instaliran Python 2.7 i biblioteku python-constraint. Na Ubuntu 14.04 ope-rativnom sistemu, biblioteka python-constraint se moze instalirati pomocu Pip alata:sudo apt-get -y install python-pipsudo pip install python-constraint

Korisni linkovi i literatura:http://labix.org/doc/constraint/https://pypi.python.org/pypi/python-constrainthttp://www.hakank.org/constraint_programming_blog/

2.1 Programiranje ograničenja

2.1.1 Uvodni primeri

Zadatak 2.1 Modul constraint, osnovne funkcije

1 # Programiranje ogranicenja

3 # Ukljucujemo modul za rad sa ogranicenjimaimport constraint

5

# Definisemo problem7 problem = constraint.Problem()

# Dodajemo promenljive9 #

# problem.addVariable(ime_promenljive, domen_lista)11 # problem.addVariables(lista_imena_promenljivih , domen_lista)

problem.addVariable('x',[1,2,3])13 problem.addVariable('y',['a','b','c'])

# Ispisujemo resenja15 # print problem.getSolutions()

17 problem.addVariable('z',[0.1,0.2,0.3])# Dodajemo ogranicenja

19 ## problem.addConstraint(ogranicenje [, redosled_promenljivih])

21 ## ogranicenje moze biti:

23 # constraint.AllDifferentConstraint() - razlicite vrednosti svih promenljivih# constraint.AllEqualConstraint() - iste vrednosti svih promenljivih

25 # constraint.MaxSumConstraint(s [,tezine]) - suma vrednosti promenljivih (pomnozenasa tezinama) ne prelazi s

# constraint.MinSumConstraint(s [,tezine]) - suma vrednosti promenljivih (pomnozenasa tezinama) nije manja od s

27 # constraint.ExactSumConstraint(s [,tezine]) - suma vrednosti promenljivih (pomnozena sa tezinama) je s

# constraint.InSetConstraint(skup) - vrednosti promenljivih se nalaze u skupu skup

21

Page 27: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2 Programiranje ograničenja - Python

29 # constraint.NotInSetConstraint(skup) - vrednosti promenljivih se ne nalaze u skupuskup

# constraint.SomeInSetConstraint(skup) - vrednosti nekih promenljivih se nalaze uskupu skup

31 # constraint.SomeNotInSetConstraint(skup) - vrednosti nekih promenljivih se nenalaze u skupu skup

#33 # redosled_promenljivih predstavlja listu promenljivih

# i zadaje se zbog definisanja tacnog redosleda35 # ogranicenja koja se primenjuju na promenljive

#37 # Mozemo napraviti i svoju funkciju ogranicenja

def ogranicenje(x,z):39 if x / 10.0 == z:

return True41

# Prosledjujemo funkciju ogranicenja i redosled promenljivih koji treba da odgovararedosledu argumenata funkcije ogranicenja

43 problem.addConstraint(ogranicenje ,['x','z'])resenja = problem.getSolutions()

45 print "\n-----Resenja -----\n"for resenje in resenja:

47 print resenje

2.1.2 Zadaci za samostalni rad sa rešenjima

Zadatak 2.2 Napisati program koji pronalazi trocifren broj ABC tako da je količnik ABC /(A + B + C) minimalan i A, B i C su različiti brojevi.

[Rešenje 2.2]

Zadatak 2.3 Dati su novčići od 1, 2, 5, 10, 20 dinara. Napisati program koji pronalazi svemoguće kombinacije tako da zbir svih novčića bude 50.

[Rešenje 2.3]

Zadatak 2.4 Napisati program koji ređa brojeve u magičan kvadrat. Magičan kvadratje kvadrat dimenzija 3x3 takav da je suma svih brojeva u svakom redu, svakoj koloni i svakojdijagonali jednak 15 i svi brojevi različiti. Na primer:

4 9 23 5 78 1 6

[Rešenje 2.4]

Zadatak 2.5 Napisati program koji pronalazi sve vrednosti promenljivih X, Y i Z za kojevaži da je X >= Z i X ∗2+Y ∗X+Z <= 34 pri čemu promenljive pripadaju narednim domenimaX ∈ {1, 2, ..., 90}, Y ∈ {2, 4, 6, ...60} i Z ∈ {1, 4, 9, 16, ..., 100}

[Rešenje 2.5]

Zadatak 2.6 Napisati program koji dodeljuje različite vrednosti različitim karakterima takoda suma bude zadovoljena:

TWO+TWO---------FOUR

[Rešenje 2.6]

22

Page 28: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2.1 Programiranje ograničenja

Zadatak 2.7 Napisati program koji pronalazi sve vrednosti promenljivih X, Y, Z i W za kojevaži da je X >= 2 ∗ W , 3 + Y <= Z i X − 11 ∗ W + Y + 11 ∗ Z <= 100 pri čemu promenljivepripadaju narednim domenima X ∈ {1, 2, ..., 10}, Y ∈ {1, 3, 5, ...51}, Z ∈ {10, 20, 30, ..., 100} iW ∈ {1, 8, 27, ..., 1000}.

[Rešenje 2.7]

Zadatak 2.8 Napisati program koji raspoređuje brojeve 1-9 u dve linije koje se seku u jednombroju. Svaka linija sadrži 5 brojeva takvih da je njihova suma u obe linije 25 i brojevi su u rastućemredosledu.

1 32 456 8

7 9

[Rešenje 2.8]

Zadatak 2.9 Pekara Kiflica proizvodi hleb i kifle. Za mešenje hleba potrebno je 10 minuta,dok je za kiflu potrebno 12 minuta. Vreme potrebno za pečenje ćemo zanemariti. Testo za hlebsadrži 300g brašna, a testo za kiflu sadrži 120g brašna. Zarada koja se ostvari prilikom prodajejednog hleba je 7 dinara, a prilikom prodaje jedne kifle je 9 dinara. Ukoliko pekara ima 20 radnihsati za mešenje peciva i 20kg brašna, koliko komada hleba i kifli treba da se umesi kako bi seostvarila maksimalna zarada (pod pretpostavkom da će pekara sve prodati)?

[Rešenje 2.9]

Zadatak 2.10 Napisati program pronalazi vrednosti A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S(svako slovo predstavlja različit broj) koje su poređane u heksagon na sledeći način:

A,B,CD,E,F,GH,I,J,K,LM,N,O,PQ,R,S

tako da zbir vrednosti duž svake horizontalne i dijagonalne linije bude 38 ( A+B+C = D+E+F+G= ... = Q+R+S = 38, A+D+H = B+E+I+M = ... = L+P+S = 38, C+G+L = B+F+K+P =... = H+M+Q = 38).

[Rešenje 2.10]

Zadatak 2.11 Kompanija Start ima 250 zaposlenih radnika. Rukovodstvo kompanije jeodlučilo da svojim radnicima obezbedi dodatnu edukaciju. Da bi se radnik obučio programskomjeziku Elixir potrebno je platiti 100 evra po osobi za kurs, ali bi njegovo produktivno znanje ovogprogramskog jezika donelo 150 projekat/sati mesečno, što bi za kompaniju značilo dobit od 5 evrapo projekat/satu. Da bi se radnik obučio programskom jeziku Dart potrebno je platiti 105 evra poosobi za kurs, ali bi njegovo produktivno znanje ovog programskog jezika donelo 170 projekat/satimesečno, koji bi za kompaniju značili dobit od 6 evra po satu. Ukoliko Start ima na raspolaganju26000 evra za obuku i maksimalan broj 51200 mogućih projekat/sati mesečno, odrediti na kojinacin kompanija treba da obuči svoje zaposlene kako bi ostvarila maksimalnu dobit.

[Rešenje 2.11]

Zadatak 2.12 Napisati program koji raspoređuje 8 topova na šahovsku tablu tako da senikoja dva topa ne napadaju.

[Rešenje 2.12]

Zadatak 2.13 Napisati program koji raspoređuje 8 dama na šahovsku tablu tako da se nikojedve dame ne napadaju.

23

Page 29: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2 Programiranje ograničenja - Python

[Rešenje 2.13]

Zadatak 2.14 Napisati program koji učitava tablu za Sudoku iz datoteke čije ime se zadajesa standardnog ulaza i korišćenjem ograničenja rešava Sudoku zagonetku.

[Rešenje 2.14]

2.1.3 Zadaci za vežbu

Zadatak 2.15 Za svaku narednu zagonetku, napisati program koji dodeljuje različite vrednostirazličitim karakterima tako da suma bude zadovoljena:

GREEN + ORANGE = COLORSMANET + MATISSE + MIRO + MONET + RENOIR = ARTISTSCOMPLEX + LAPLACE = CALCULUSTHIS + IS + VERY = EASYCROSS + ROADS = DANGERFATHER + MOTHER = PARENTWE + WANT + NO + NEW + ATOMIC = WEAPONEARTH + AIR + FIRE + WATER = NATURESATURN + URANUS + NEPTUNE + PLUTO = PLANETSSEE + YOU = SOONNO + GUN + NO = HUNTWHEN + IN + ROME + BE + A = ROMANDONT + STOP + THE = DANCEHERE + THEY + GO = AGAINOSAKA + HAIKU + SUSHI = JAPANMACHU + PICCHU = INDIANSHE + KNOWS + HOW + IT = WORKSCOPY + PASTE + SAVE = TOOLS

Zadatak 2.16 Za svaku narednu zagonetku, napisati program koji dodeljuje različite vrednostirazličitim karakterima tako da suma bude zadovoljena:

THREE + THREE + ONE = SEVENNINE + LESS + TWO = SEVENONE + THREE + FOUR = EIGHTTHREE + THREE + TWO + TWO + ONE = ELEVENSIX + SIX + SIX = NINE + NINESEVEN + SEVEN + SIX = TWENTYONE + ONE + ONE + THREE + THREE + ELEVEN = TWENTYEIGHT + EIGHT + TWO + ONE + ONE = TWENTYELEVEN + NINE + FIVE + FIVE = THIRTYNINE + SEVEN + SEVEN + SEVEN = THIRTYTEN + SEVEN + SEVEN + SEVEN + FOUR + FOUR + ONE = FORTYTEN + TEN + NINE + EIGHT + THREE = FORTYFOURTEEN + TEN + TEN + SEVEN = FORTYONENINETEEN + THIRTEEN + THREE + TWO + TWO + ONE + ONE + ONE = FORTYTWOFORTY + TEN + TEN = SIXTYSIXTEEN + TWENTY + TWENTY + TEN + TWO + TWO = SEVENTYSIXTEEN + TWELVE + TWELVE + TWELVE + NINE + NINE = SEVENTYTWENTY + TWENTY + THIRTY = SEVENTYFIFTY + EIGHT + EIGHT + TEN + TWO + TWO = EIGHTYFIVE + FIVE + TEN + TEN + TEN + TEN + THIRTY = EIGHTYSIXTY + EIGHT + THREE + NINE + TEN = NINETYONE + NINE + TWENTY + THIRTY + THIRTY = NINETY

Zadatak 2.17 Za svaku narednu zagonetku, napisati program koji dodeljuje različite vrednostirazličitim karakterima tako da jednakost bude zadovoljena:

24

Page 30: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2.2 Rešenja

MEN * AND = WOMENCOGITO = ERGO * SUM((JE + PENSE) - DONC) + JE = SUISFERMAT * S = LAST + THEOREM.WINNIE / THE = POOHTWO * TWO + EIGHT = TWELVE

Zadatak 2.18 Uraditi sve zadatke koji su pobrojani ovde:http://www.primepuzzle.com/leeslatest/alphameticpuzzles.html

Zadatak 2.19 Napisati program koji učitava ceo broj n i ispisuje magičnu sekvencu S brojevaod 0 do n − 1. S = (x0, x1, ..., xn−1) je magična sekvenca ukoliko postoji xi pojavljivanja broja iza i = 0, 1, ..., n− 1.

Zadatak 2.20 Čistačica Mica sređuje i čisti kuće i stanove. Da bi sredila i počistila jedan stanpotrebno joj je 1 sat, dok joj je za kuću potrebno 1.5 sati. Prilikom čišćenja, Mica potroši nekukoličinu deterdženta, 120ml po stanu, odnosno 100ml po kući. Mica zaradi 1000 dinara po svakomstanu, odnosno 1500 dinara po kući. Ukoliko Mica radi 40 sati nedeljno i ima 5l deterdženta naraspolaganju, koliko stanova i kuća je potrebno da očisti kako bi imala najveću zaradu?

Zadatak 2.21 Marija se bavi grnčarstvom i pravi šolje i tanjire. Da bi se napravila šolja,potrebno je 6 minuta, dok je za tanjir potrebno 3 minuta. Pri pravljenju šolje potroši se 75 gr,dok se za tanjir potroši 100 gr gline. Ukoliko ima 20 sati na raspolaganju za izradu svih proizvodai 250 kg gline, a zarada koju ostvari iznosi 2 evra po svakoj šolji i 1.5 evra po tanjiru, koliko šoljai tanjira treba da napravi kako bi ostvarila maksimalnu zaradu?

Zadatak 2.22 Jovanin komšija preprodaje računare i računarsku opremu. Očekuje isporukuračunara i štampača. Pri tom, računari su spakovani tako da njihova kutija zauzima 360 kubnihdecimetara prostora, dok se štampači pakuju u kutijama koje zauzimaju 240 kubnih decimetaraprostora. Komšija se trudi da mesečno proda najmanje 30 računara i da taj broj bude bar za 50%veći od broja prodatih štampača. Računari koštaju 200 evra po nabavnoj ceni, a prodaju se poceni od 400 evra, dok štampači koštaju u nabavci 60 evra i prodaju se za 140 evra. Magacin kojimkomšija raspolaže ima svega 30000 kubnih decimetara prostora i mesečno može da nabavi robu uiznosu od najviše 14000 evra. Koliko računara, a koliko štampača komšija treba da proda kako bise maksimalno obogatio?

2.2 Rešenja

Rešenje 2.2

1

import constraint3

problem = constraint.Problem()5 # Definisemo promenljive i njihove vrednosti

problem.addVariable('A',range(1,10))7 problem.addVariable('B',range(10))

problem.addVariable('C',range(10))9 # Dodajemo ogranicenje da su vrednosti svih promenljivih razlicite

problem.addConstraint(constraint.AllDifferentConstraint())11 resenja = problem.getSolutions()

# Znamo da minimalni kolicnik mora biti manji od 99913 min_kolicnik = 999

min_resenje = {}15 for resenje in resenja:

a = resenje['A']17 b = resenje['B']

c = resenje['C']19 kolicnik = (float)(a*100 + b*10 + c) / (a+b+c)

if kolicnik < min_kolicnik:21 min_kolicnik = kolicnik

min_resenje = resenje

25

Page 31: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2 Programiranje ograničenja - Python

23 print min_resenje['A']*100 + min_resenje['B']*10 + min_resenje['C']

Rešenje 2.3

1 import constraint

3 problem = constraint.Problem()# Definisemo promenljive za svaki novcic

5 # ako bi se zahtevalo da u kombinaciji bude od svake vrednosti bar po jedan novcicsamo treba promeniti da domen za svaku promenljivu krece od 1

problem.addVariable("1 din",range(0,51))7 problem.addVariable("2 din",range(0,26))

problem.addVariable("5 din",range(0,11))9 problem.addVariable("10 din",range(0,6))

problem.addVariable("20 din",range(0,3))11

# Problem koji je uocen pri ispisu resenja je sledeci, redosled u kom ce biti dodatepromenljive problemu ne mora uvek da odgovara redosledu kojim smo mi definisalipromenljive, u konkretnom primeru (videti oblik u kom ispisuje resenje),promenljive ce se dodati u sledecem redosledu:'1 din', '2 din', '10 din', '20 din', '5 din' (nacin na koji se kljucevi organizuju u recniku nije striktnodefinisan, primetimo da niske nisu sortirane)

13 # posledica je da postavljanje ogranicenja# problem.addConstraint(constraint.ExactSumConstraint(50,[1,2,5,10,20]))

15 # nece ispravno dodeliti tezine, na primer, tezinu 5 dodeli promenljivoj '10 din'umesto '5 din' kako bismo ocekivali

17 # I nacin da se resi ovaj problem je da redosled promenljivih koji odgovara redosledutezina za ExactSumConstraint prosledimo kao dodatni argument za funkciju

addConstraint

19 problem.addConstraint(constraint.ExactSumConstraint(50,[1,2,5,10,20]), ["1 din", "2din", "5 din","10 din", "20 din"])

21 # II nacin je da definisemo svoju funkciju koja predstavlja ogranicenje, samo ce sadasolver nesto sporije da radi posto ugradjene funkcije imaju optimizovanu

pretragu i brze dolaze do resenja#

23 #def o(a, b, c, d, e):# if a + 2*b + 5*c + 10*d + 20*e == 50:

25 # return True#

27 #problem.addConstraint(o, ["1 din", "2 din", "5 din","10 din", "20 din"])#

29 resenja = problem.getSolutions()

31 for r in resenja:print r

33 # Provera da je suma bas 50print r["1 din"] + r["2 din"]*2 + r["5 din"]*5 + r["10 din"]*10 + r["20 din"]*20

Rešenje 2.4

# 4 9 22 # 3 5 7

# 8 1 64 #

6 import constraint

8 def o(x,y,z):if x+y+z == 15:

10 return True

12 problem = constraint.Problem()# Promenljive:

14 # a b c# d e f

16 # g h iproblem.addVariables("abcdefghi", range(1,10))

26

Page 32: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2.2 Rešenja

18 problem.addConstraint(constraint.AllDifferentConstraint())# Dodajemo ogranicenja za svaku vrstu

20 problem.addConstraint(o,"abc")problem.addConstraint(o,"def")

22 problem.addConstraint(o,"ghi")# Dodajemo ogranicenja za svaku kolonu

24 problem.addConstraint(o,"adg")problem.addConstraint(o,"beh")

26 problem.addConstraint(o,"cfi")#Dodajemo ogranicenja za dijagonale

28 problem.addConstraint(o,"aei")problem.addConstraint(o,"ceg")

30

resenja = problem.getSolutions()32 for r in resenja:

print " ------- "34 print "| {0:d} {1:d} {2:d} |".format(r['a'],r['b'],r['c'])

print "| {0:d} {1:d} {2:d} |".format(r['d'],r['e'],r['f'])36 print "| {0:d} {1:d} {2:d} |".format(r['g'],r['h'],r['i'])

print " ------- "

Rešenje 2.5

1 # X,Y,Z#

3 # X >= Z# X*2 + X*Y + Z <= 34

5 ## X <- {1,2,3,...90}

7 # Y <- {2,4,6,...60}# Z <- {1,4,9,16,...100}

9 ##

11

import constraint13

problem = constraint.Problem()15

# Dodajemo promenljivu X i definisemo njen domen17 problem.addVariable('X', range(1,91))

19 # Dodajemo promenljivu Y i definisemo njen domenproblem.addVariable('Y', range(2,61,2))

21

domenZ = [];23 for i in range(1,11):

domenZ.append(i*i)25

# Dodajemo promenljivu Z i definisemo njen domen27 problem.addVariable('Z', domenZ)

29 def o1(x,z):if x >= z:

31 return True

33 def o2(x,y,z):if x*2 + x*y + z <= 34:

35 return True;

37 # Dodajemo ogranicenjaproblem.addConstraint(o1, 'XZ')

39 problem.addConstraint(o2, 'XYZ')

41 resenja = problem.getSolutions()

43 for r in resenja:print "------------------------"

45 print "X = {0:d} , Y = {1:d} , Z = {2:d}".format(r['X'],r['Y'],r['Z'])print "------------------------"

27

Page 33: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2 Programiranje ograničenja - Python

Rešenje 2.6

# TWO2 # +TWO

# ------4 # FOUR

#6

import constraint8

problem = constraint.Problem()10 # Definisemo promenljive i njihove vrednosti

problem.addVariables("TF",range(1,10))12 problem.addVariables("WOUR",range(10))

14 # Definisemo ogranicenje za cifredef o(t, w, o, f, u, r):

16 if 2*(t*100 + w*10 + o) == f*1000 + o*100 + u*10 + r:return True

18

# Dodajemo ogranicenja za cifre20 problem.addConstraint(o,"TWOFUR")

# Dodajemo ogranicenje da su sve cifre razlicite22 problem.addConstraint(constraint.AllDifferentConstraint())

24 resenja = problem.getSolutions()

26 for r in resenja:print "-----"

28 print " "+str(r['T'])+str(r['W'])+str(r['O'])print " +"+str(r['T'])+str(r['W'])+str(r['O'])

30 print "="+str(r['F'])+str(r['O'])+str(r['U'])+str(r['R'])

Rešenje 2.7

# Dati sistem nejednacina nema resenje, tj. metog getSolutions() vraca praznu listu2 # Ukoliko se za promenljivu W domen promeni na {1,...,100} sistem ce imati resenje

import constraint4

problem = constraint.Problem()6

# Dodajemo promenljivu X i definisemo njen domen8 problem.addVariable('X', range(1,11))

10 # Dodajemo promenljivu Y i definisemo njen domenproblem.addVariable('Y', range(1,52,2))

12

domenZ = []14 domenW = []

16 for i in range(1,11):domenZ.append(i*10)

18 domenW.append(i**3)

20 # Dodajemo promenljivu Z i definisemo njen domenproblem.addVariable('Z', domenZ)

22

# Dodajemo promenljivu W i definisemo njen domen24 problem.addVariable('W', domenW)

26 # Za ovako definisan domen za promenljivu W sistem ce imati resenje# problem.addVariable('W', range(1,101))

28

30 def o1(x,w):if x >= 2*w:

32 return True

34 def o2(y,z):if 3 + y <= z:

36 return True

28

Page 34: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2.2 Rešenja

38 def o3(x,y,z,w):if x - 11*w + y + 11*z <= 100:

40 return True;

42 # Dodajemo ogranicenjaproblem.addConstraint(o1, 'XW')

44 problem.addConstraint(o2, 'YZ')problem.addConstraint(o3, 'XYZW')

46

resenja = problem.getSolutions()48 # Proveravamo da li postoji resenje za sistem nejednacina

if resenja==[]:50 print "Sistem nema resenje."

else:52 for r in resenja:

print "------------------------"54 print "X = {0:d} , Y = {1:d} , Z = {2:d}, W = {3:d}".format(r['X'],r['Y'],r['

Z'], r['W'])print "------------------------"

Rešenje 2.8

1 # 1 3# 2 4

3 # 5# 6 8

5 # 7 9#

7

import constraint9

# Definisemo ogranicenje za jednu dijagonalu11 def o(a,b,c,d,e):

if a<b<c<d<e and a+b+c+d+e==25:13 return True

15 problem = constraint.Problem()# Definisemo promenljive za svaku poziciju

17 problem.addVariables('abcdeABDE',range(1,10))# Dodajemo ogranicenja za obe dijagonale

19 problem.addConstraint(o,'abcde')problem.addConstraint(o,'ABcDE')

21 # Dodajemo ogranicenje da su vrednosti svih promenljivih razliciteproblem.addConstraint(constraint.AllDifferentConstraint())

23

resenja = problem.getSolutions()25 for r in resenja:

print "-------------"27 print "{0:d} {1:d}".format(r['a'],r['A'])

print " {0:d} {1:d} ".format(r['b'],r['B'])29 print " {0:d} ".format(r['c'])

print " {0:d} {1:d} ".format(r['D'],r['d'])31 print "{0:d} {1:d}".format(r['E'],r['e'])

print "-------------"

Rešenje 2.9

#2 # Potrebno je napraviti H komada hleba i K komada kifli

#4 # Zarada iznosi:

# - 7din/hleb, tj. zarada za H komada hleba bice 7*H6 # - 9din/kifla tj. zarada za K komada kifli bice 9*K

#8 # Ukupna zarada iznosi:

# 7*H + 9*K - funkcija koju treba maksimizovati10 #

# Ogranicenja vremena:12 # - vreme potrebno za mesenje jednog hleba je 10min,

# tj. za mesenje H komada hleba potrebno je 10*H minuta

29

Page 35: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2 Programiranje ograničenja - Python

14 # - vreme potrebno za mesenje jedne kifle je 12min,# tj. za mesenje K komada kifli potrebno je 12*K minuta

16 ## Ukupno vreme koje je na raspolaganju iznosi 20h, tako da je:

18 # 10*H + 12*K <= 1200#

20 # Ogranicenje materijala:# - za jedan hleb potrebno je 300g brasna, a za H komada hleba potrebno je H*300

grama22 # - za jednu kifli potrebno je 120g brasna, a za K komada kifli potrebno je K*120

grama#

24 # Ukupno, na raspolaganju je 20kg brasna, tako da je:# 300*H + 120*K <= 20000

26 ## Broj kifli i hleba je najmanje 0, tako da:

28 # H>=0# K>=0

30 ## S obzirom na to da imamo 20kg brasna na raspolaganju, mozemo napraviti:

32 # - najvise 20000/120 kifli# - najvise 20000/300 hleba

34 ## H <= 20000/120 ~ 167

36 # K <= 20000/300 ~ 67#

38 # S obzirom na to da imamo 20h na raspolaganju, mozemo napraviti:# - najvise 1200/12 kifli

40 # - najvise 1200/10 hleba#

42 # H <= 1200/10 = 120# K <= 1200/12 = 100

44 ## najoptimalnije je za gornju granicu domena postaviti minimum od dobijenih vrednosti

, tj. sve ukupno H <= 120, K <= 6746

import constraint48

problem = constraint.Problem()50

# Dodajemo promenljivu H i definisemo njen domen52 problem.addVariable('H', range(0,121))

54 # Dodajemo promenljivu K i definisemo njen domenproblem.addVariable('K', range(0,68))

56

def ogranicenje_vremena(h,k):58 if 10*h + 12*k <= 1200:

return True60

def ogranicenje_materijala(h,k):62 if 300*h + 120*k <= 20000:

return True;64

# Dodajemo ogranicenja vremena i matrijala66 problem.addConstraint(ogranicenje_vremena , 'HK')

problem.addConstraint(ogranicenje_materijala , 'HK')68

resenja = problem.getSolutions()70

# Pronalazimo maksimalnu vrednost funkcije cilja72 max_H = 0

max_K = 074

for r in resenja:76 if 7*r['H'] + 9*r['K'] > 7*max_H + 9*max_K:

max_H = r['H']78 max_K = r['K']

80 print "----------------------------------------------------------------"print "Maksimalna zarada je {0:d}, komada hleba je {1:d}, a komada kifli {2:d}".

format(7*max_H + 9*max_K, max_H, max_K)82 print "----------------------------------------------------------------"

30

Page 36: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2.2 Rešenja

Rešenje 2.10

1

import constraint3

def o1(x,y,z):5 if x+y+z == 38:

return True7 def o2(x,y,z,w):

if x+y+z+w == 38:9 return True

def o3(x,y,z,w,h):11 if x+y+z+w+h == 38:

return True13

problem = constraint.Problem()15 problem.addVariables("ABCDEFGHIJKLMNOPQRST", range(1,38))

problem.addConstraint(constraint.AllDifferentConstraint())17 # Dodajemo ogranicenja za svaku horizontalnu liniju

# A,B,C19 # D,E,F,G

#H,I,J,K,L21 # M,N,O,P

# Q,R,S23 problem.addConstraint(o1,"ABC")

problem.addConstraint(o2,"DEFG")25 problem.addConstraint(o3,"HIJKL")

problem.addConstraint(o2,"MNOP")27 problem.addConstraint(o1,"QRS")

29 # Dodajemo ogranicenja za svaku od glavnih dijagonala# A,B,C

31 # D,E,F,G#H,I,J,K,L

33 # M,N,O,P# Q,R,S

35

problem.addConstraint(o1,"HMQ")37 problem.addConstraint(o2,"DINR")

problem.addConstraint(o3,"AEJOS")39 problem.addConstraint(o2,"BFKP")

problem.addConstraint(o1,"CGL")41

# Dodajemo ogranicenja za svaku od sporednih dijagonala43 # A,B,C

# D,E,F,G45 #H,I,J,K,L

# M,N,O,P47 # Q,R,S

49 problem.addConstraint(o1,"ADH")problem.addConstraint(o2,"BEIM")

51 problem.addConstraint(o3,"CFJNQ")problem.addConstraint(o2,"GKOR")

53 problem.addConstraint(o1,"LPS")

55 resenja = problem.getSolutions()for r in resenja:

57 print " -----------------"print " {0:d},{1:d},{2:d}".format(r['A'],r['B'],r['C'])

59 print " {0:d},{1:d},{2:d},{3:d}".format(r['D'],r['E'],r['F'],r['G'])print "{0:d},{1:d},{2:d},{3:d},{4:d}".format(r['H'],r['I'],r['J'],r['K'],r['L'])

61 print " {0:d},{1:d},{2:d},{3:d}".format(r['M'],r['N'],r['O'],r['P'])print " {0:d},{1:d},{2:d}".format(r['Q'],r['R'],r['S'])

63 print " -----------------"

Rešenje 2.11

1 import constraint

3 problem = constraint.Problem()# Kompanija ima 250 zaposlenih radnika

31

Page 37: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2 Programiranje ograničenja - Python

5 # za sve njih organizuje dodatnu obuku# ako je E promenjiva za Elixir, a D za Dart

7 # mora da vazi E<=250, D<=250 i E + D = 250#

9 # Dodajemo promenljivu E i definisemo njen domenproblem.addVariable('E', range(0,251))

11

# Dodajemo promenljivu D i definisemo njen domen13 problem.addVariable('D', range(0,251))

15 def ukupno_radnika(e,d):if e+d == 250:

17 return True

19 def ogranicenje_projekat_sati(e,d):if 150*e + 170*d <= 51200:

21 return True

23 def ogranicenje_sredstava(e,d):if 100*e + 105*d <= 26000:

25 return True;

27 # Dodajemo ogranicenja za broj projekat/sati i ukupna sredstva# na raspolaganju kao i za broj radnika u firmi

29 problem.addConstraint(ogranicenje_projekat_sati , 'ED')problem.addConstraint(ogranicenje_sredstava , 'ED')

31 problem.addConstraint(ukupno_radnika , 'ED')

33 resenja = problem.getSolutions()

35 # Pronalazimo maksimalnu vrednost funkcije ciljamax_E = 0

37 max_D = 0# Od ostvarene dobiti preko broja projekat/sati oduzimamo gubitak za placanje kurseva

radnicima39 for r in resenja:

if 150*5*r['E'] + 170*6*r['D'] - (100*r['E'] + 105*r['D']) > 150*5*max_E + 170*6*max_D - (100*max_E + 105*max_D) :

41 max_E = r['E']max_D = r['D']

43

45 print "Maksimalna zarada je {0:d}, broj radnika koje treba poslati na kurs Elixir je{1:d}, a broj radnika koje treba poslati na kurs Dart je {2:d}.".format(170*6*max_E + 150*5*max_D - (100*max_E + 150*max_D) , max_E, max_D)

Rešenje 2.12

1 # Jedan od mogucih rasporeda# sva ostala resenja su permutacije

3 # takve da je u svakoj vrsti i koloni samo jedan top#

5 # 8 T - - - - - - -# 7 - T - - - - - -

7 # 6 - - T - - - - -# 5 - - - T - - - -

9 # 4 - - - - T - - -# 3 - - - - - T - -

11 # 2 - - - - - - T -# 1 - - - - - - - T

13 # 1 2 3 4 5 6 7 8#

15

import constraint17

problem = constraint.Problem()19 # Dodajemo promenljive za svaku kolonu i njihove vrednosti 1-8

problem.addVariables("12345678", range(1,9))21 # Dodajemo ogranicenje da se topovi ne napadaju medjusobno po svakoj vrsti

problem.addConstraint(constraint.AllDifferentConstraint())23 resenja = problem.getSolutions()

32

Page 38: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2.2 Rešenja

25 # Broj svih mogucih permutacija je 8! = 40320# Za prikaz svih najbolje pozvati program sa preusmerenjem izlaznih podataka

27 # python 2_12.py > izlaz.txtprint "Broj resenja je: {0:d}.".format(len(resenja))

29

for r in resenja:31 print "---------------"

for i in "12345678":33 for j in range(1,9):

if r[i] == j:35 print "T",

else:37 print "-",

print ""39 print "---------------"

Rešenje 2.13

1 # 8 D - - - - - - -# 7 - - - - D - - -

3 # 6 - D - - - - - -# 5 - - - - - D - -

5 # 4 - - D - - - - -# 3 - - - - - - D -

7 # 2 - - - D - - - -# 1 - - - - - - - D

9 # 1 2 3 4 5 6 7 8#

11

import constraint13 import math

15 problem = constraint.Problem()# Dodajemo promenljive za svaku kolonu i njihove vrednosti 1-8

17 problem.addVariables("12345678", range(1,9))# Dodajemo ogranicenje da se dame ne napadaju medjusobno po svakoj vrsti

19 problem.addConstraint(constraint.AllDifferentConstraint())

21 for k1 in range(1,9):for k2 in range(1,9):

23 if k1 < k2:# Definisemo funkciju ogranicenja za dijagonale

25 def o(vrsta1, vrsta2, kolona1=k1, kolona2=k2):if math.fabs(vrsta1 - vrsta2) != math.fabs(kolona1 - kolona2):

27 return Trueproblem.addConstraint(o, [str(k1),str(k2)])

29

resenja = problem.getSolutions()31 # Za prikaz svih najbolje pozvati program sa preusmerenjem izlaznih podataka

# python 2_13.py > izlaz.txt33 print "Broj resenja je: {0:d}.".format(len(resenja))

for r in resenja:35 print "---------------"

for i in "12345678":37 for j in range(1,9):

if r[i] == j:39 print "D",

else:41 print "-",

print ""43 print "---------------"

Rešenje 2.14

1 # 9 - - - - - - - - -# 8 - - - - - - - - -

3 # 7 - - - - - - - - -# 6 - - - - - - - - -

5 # 5 - - - - - - - - -# 4 - - - - - - - - -

33

Page 39: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

2 Programiranje ograničenja - Python

7 # 3 - - - - - - - - -# 2 - - - - - - - - -

9 # 1 - - - - - - - - -# 1 2 3 4 5 6 7 8 9

11 #

13 import constraintimport json

15

problem = constraint.Problem()17

# Dodajemo promenljive za svaki red i njihove vrednosti 1-919 for i in range(1, 10):

problem.addVariables(range(i * 10 + 1, i * 10 + 10), range(1, 10))21

# Dodajemo ogranicenja da se u svakoj vrsti nalaze razlicite vrednosti23 for i in range(1, 10):

problem.addConstraint(constraint.AllDifferentConstraint(), range(i * 10 + 1, i *10 + 10))

25

# Dodajemo ogranicenja da se u svakoj koloni nalaze razlicite vrednosti27 for i in range(1, 10):

problem.addConstraint(constraint.AllDifferentConstraint(), range(10 + i, 100 + i,10))

29

# Dodajemo ogranicenja da svaki podkvadrat od 3x3 promenljive ima razlicite vrednosti31 for i in [1,4,7]:

for j in [1,4,7]:33 pozicije = [10*i+j,10*i+j+1,10*i+j+2,10*(i+1)+j,10*(i+1)+j+1,10*(i+1)+j

+2,10*(i+2)+j,10*(i+2)+j+1,10*(i+2)+j+2]problem.addConstraint(constraint.AllDifferentConstraint(),pozicije)

35

37 ime_datoteke = raw_input("Unesite ime datoteke sa tablom za sudoku: ")f = open(ime_datoteke , "r")

39 tabla = json.load(f)f.close()

41

# Dodajemo ogranicenja za svaki broj koji je zadat na tabli43 for i in range(9):

for j in range(9):45 if tabla[i][j] != 0:

def o(vrednost_promenljive , vrednost_na_tabli = tabla[i][j]):47 if vrednost_promenljive == vrednost_na_tabli:

return True49

problem.addConstraint(o, [((i+1)*10 + (j+1))])51

resenja = problem.getSolutions()53

for r in resenja:55 print "========================="

for i in range(1,10):57 print "|",

for j in range(1,10):59 if j%3 == 0:

print str(r[i*10+j])+" |",61 else:

print str(r[i*10+j]),63 print ""

if i%3 == 0 and i!=9:65 print "-------------------------"

print "========================="

34

Page 40: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3

Funkcionalno programiranje

Potrebno je imati instaliran GHC kompajler na računaru.Literatura:

(a) https://www.haskell.org/

(b) https://wiki.haskell.org/Haskell

3.1 Uvod3.1.1 Uvodni primeri

Zadatak 3.1 Korišćenje kompilatora i interpretera.-- Ovako pisemo jednolinijske komentare

2

{-4 Ovako pisemo

viselinijske6 komentare

-}8

{-10 Interpreter pokrecemo iz terminala komandom:

12 ghci

14 i otvorice nam se interaktivni interpreter:

16 GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for helpPrelude>

18

Sa interpreterom mozemo direktno komunicirati, npr20 Prelude> print "Zdravo! :)"

"Zdravo! :)"22

Interpretatoru dodajemo mogucnost izvrsavanja funkcija iz izvorne24 ime_programa.hs komandom:

26 :load ime_programa.hs

28 Nakon toga mozemo pokrenuti sve funkcije koje su u toj datotecidefinisane, npr.

30

Prelude> main32 "Zdravo! :)"

34 Iz interpretera se izlazi komandom :quitPrelude> :quit

36

Haskell programe mozemo kompajlirati komandom:38

ghc ime_programa.hs

35

Page 41: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3 Funkcionalno programiranje

40

koja ce napraviti izvrsni program koji pokrecemo sa42

./ime_programa44

-}46

main = print "Zdravo! :)"

Zadatak 3.2 Tipovi podataka. Tipski razredi. Funkcije.1 {-

Osnovni tipovi:3 Bool

Char5 String

Int7 Integer

Float9 Double

11 Tipski razredi (definisu funkcije koje neki tip mora da implementira):Eq - tipovi sa jednakoscu (==,/=)

13 Ord - tipovi sa uredjenjem (<,<=,>,>=,...)Num - numericki tipovi (+,-,*,...)

15 Integral - celobrojni tipovi (div, mod,...)Fractional - razlomacki tipovi (/, recip,...)

17

Funkcije preslikavaju vrednosti jednog tipa (ili tipskog razreda) u vrednost drugogtipa (ili tipskog razreda):

19

duplo :: Int -> Int21

Informacije o bilo kom objektu mozete dobiti naredbom:23 :info ime_objekta

-}25

duplo :: Int -> Int27 duplo x = x+x

29 {-Aritmeticke operacije nad tipovima Int, Integer, Float:

31 +, -, *, /,^^ - stepen (tip Int)

33 ** - stepen (tip Float)

35 Funkcije:mod, div, log, sqrt, sin, cos, tan

37

-}39

ostatak3 x = mod x 341 -- ekvivalentno sa x `mod` 3

43 -- ukoliko koristimo funkcije koje su definisane za realne tipove nad argumentimakoji su celobrojnog tipa potrebno je prevesti vrednost u nadklasu Num koriscenjemfunkcije fromIntegral, nece se izvrsiti eksplicitno kastovanje

-- primer: funkcija racuna vrednost korena samo za celobrojni argument45 korenCeli :: Int -> Double

korenCeli n = sqrt (fromIntegral n)47

-- Blokovi se u Haskelu odvajaju tabulatorom.49 -- Uslovni izraz (mora imati else granu)

51 jedan n = if n == 1then True

53 else False

55 -- Ogradjene jednacine (guarded equations) - mozemo ih koristiti umesto uslovnihizraza, bitan je redosled navodjenja

57 sumaPrvih n| n == 0 = 0

36

Page 42: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3.1 Uvod

59 | otherwise = n + sumaPrvih(n-1)

Zadatak 3.3 Liste. N-torke.1 {-

Lista je niz vrednosti istog tipa:3

[element1,element2 ,...]5

Operacije:7

x : lista - dodaje element x na pocetak liste9 lista1 ++ lista1 - nadovezuje dve liste

lista !! pozicija - vraca element liste koji se nalazi na poziciji pozicija11 [a..b] - konstruise listu sa elementima od a do b (u zavisnosti od tipa)

-}13

lista = [1..5]15 obrnutaLista = [5,4..1]

17 {-Korisne funkcije:

19 head lista - vraca prvi element listetail lista - vraca rep liste

21 length lista - vraca broj elemenata listetake n lista - vraca listu prvih n elemenata

23 drop n lista - vraca listu bez prvih n elemenatanull lista - vraca True ukoliko je lista prazna, False inace

25 -}

27 -- Niske su liste karaktera

29 niska1 = ['A','l','a','d','d','i','n']niska2 = "Aladdin"

31

{-33 N-torke su nizovi vrednosti razlicitog tipa:

('a',1,[1.2, 2.3],"torka")35

Funkcije definisane za parove (n=2):37 fst () - vraca prvi element

snd () - vraca drugi element39 -}

3.1.2 Zadaci za samostalni rad sa rešenjima

Zadatak 3.4 Napisati sledeće funkcije:

• proizvodPrvih n - računa proizvod prvih n pozitivnih brojeva (rekurzivno, bez korišćenjaformule)

• prost n - vraća True ako je broj prost, False inače

• nzd a b - računa najmanji zajednički delilac brojeva a i b (koristiti Euklidov algoritam)

• tipJednacine a b c - vraća tip kvadratne jednačine a ∗ x2 + b ∗ x+ c = 0 (đegenerisana”,”jedno resenje”, đva resenja”,”bez resenja”)

• izDekadne x osn - prebacuje broj x iz dekadne u osnovu osn (pretpostaviti da je osn>1 iosn<10)

• uDekadne x osn - prebacuje broj x iz osnove osn u dekadnu osnovu (pretpostaviti da jeosn>1 i osn<10)

• ceoDeo x - računa ceo deo korena broja x (bez korišćenja ugrađenih funkcija za koren i/ilistepen)

[Rešenje 3.4]

37

Page 43: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3 Funkcionalno programiranje

Zadatak 3.5 Napisati sledeće funkcije koristeći liste:

• harm n - vraća listu prvih n elemenata harmonijskog reda

• delioci n - vraća listu svih delilaca pozitivnog broja n

• nadovezi lista1 lista2 n - nadovezuje na lista1 n puta lista2

[Rešenje 3.5]

3.1.3 Zadaci za vežbu

Zadatak 3.6 Napisati sledeće funkcije:

• sumaKvadrata n - računa sumu kvadrata prvih n brojeva (rekurzivno, bez korišćenja formule)

• brojDelilaca n - vraća broj delilaca broja n

• fib n - računa n-ti element Fibonačijevog reda

• osnova x osn1 osn2 - prebacuje broj x iz osnove osn1 u osnovu osn2 (pretpostaviti da suosn1 i osn2 brojevi veći od 1 i manji od 10)

Zadatak 3.7 Napisati sledeće funkcije koristeći liste:

• parni n - vraća listu prvih n parnih brojeva

• fibLista n - vraća listu prvih n elemenata Fibonačijevog niza

• jednocifreniDelioci n - vraća listu svih jednocifrenih delilaca broja n

3.2 Liste3.2.1 Uvodni primeri

Zadatak 3.81 {-

Uparivanje sablona (pattern matching)3

not :: Bool -> Bool5 not False = True

not True = False7

Ako pozovemo not True uparice se prvi sablon,9 a ako pozovemo not False uparice se drugi sablon

11 Dzoker (wildcard)

13 prvi nacin (ako bismo zamenili redosled sablona, javlja pattern match overlapped)(&&) :: Bool -> Bool -> Bool

15 True && True = True_ && _ = False --- moglo bi i: n && m = False, bitno je samo da su razlicito

imenovani17

drugi nacin, efikasniji:19 (&&) :: Bool -> Bool -> Bool

True && x = x21 False && _ = False

23 _ predstavlja dzoker, tj. sablon koji odgovara bilo kojoj vrednosti (obratitipaznju na redosled definisanja sablona!)

25 Sabloni lista:

27 length [_] = 1 - [_] predstavlja listu sa jednim elementom

38

Page 44: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3.2 Liste

length x = 1 + length (tail x) - x predstavlja listu29

-}31

length1 [] = 033 length1 x = 1 + length1 (tail x)

35 -- (x:xs) - predstavlja sablon liste, x je glava, xs je rep

37 length2 [] = 0length2 (_:xs) = 1 + length2 xs

39

-- preslikava iz liste elemenata u jedan element41 glava :: [a] -> a

glava (x:_) = x43

-- preslikava iz liste u listu45 rep :: [a] -> [a]

rep (_:xs) = xs47

-- restrikcija na liste elemenata koji pripadaju numerickim tipovima49 glavaNum :: (Num a) => [a] -> a

glavaNum (x:_) = x51

-- Generatori liste (list comprenhension)53

-- even proverava da li je argument paran, a odd da li je neparan55 -- elementi listi pripadaju skupu od 1 do 50

parni = [x | x<-[1..50], even x]57 neparni = [x | x<-[1..50], odd x]

59 deljiviPet = [x | x<-[1..50], mod x 5 == 0] -- elementi liste pripadaju skupu od 1 do50 i deljivi su sa 5

61 kvadrati = [x^2 | x<-[1..10]]

63 -- Mozemo imati vise generatora

65 torke1 = [(x,y) | x<-[1..5], y<-[6..9]]

67 -- obratiti paznju kako utice zamena mesta generatoratorke2 = [(x,y) | y<-[6..9], x<-[1..5]]

69

-- sa negativnim korakom71 torke3 = [(x,y) | y<-[9,8..6], x<-[1..5]]

73 -- Generatori mogu zavisiti jedni od drugih

75 -- kasniji generatori mogu zavisiti samo od promenljivih koje su uvedene ranijimgeneratorima citajuci sa leva na desno

torke4 = [(x,y) | x<-[1..10], y<-[x..10]]77

{-79 Sekcija where

81 where ime = vrednost- imena koja definisemo u where sekciji su vidljiva samo u okviru funkcije

83 u kojoj su definisana-}

85

bmiIzracunaj tezina visina87 | bmi <= 18.5 = "Mrsavko"

| bmi <= 25.0 = "Sportista"89 | bmi > 25.0 = "Bucko"

where bmi = tezina / visina ^ 2

3.2.2 Zadaci za samostalni rad sa rešenjima

Zadatak 3.9 Napisati sledeće funkcije:

• bezbedanRep lista - ukoliko je lista prazna vraća praznu listu, inače vraća rep liste, kori-

39

Page 45: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3 Funkcionalno programiranje

steći: a) uslovne izraze b) ograđene jednačine c) uparivanje šablona

• savrseni n - vraća listu savršenih brojeva manjih od n (broj je savršen ako je jednak sumisvojih faktora (tj. delilaca), ne uključujući taj broj)

• zbirPar n - vraća listu parova (a,b) takvih da su a i b prirodni brojevi i da je zbir a i bjednak n

• polovina lista - deli listu na dve polovine

• poslednji lista - vraca poslednji element liste

• spoji lista - spaja listu listi u jednu listu

• sufiksi lista - vraca listu svih sufiksa liste

• obrni lista - obrce listu

• izbaci k lista - izbacuje k-ti element iz liste

• duplira lista - duplira svaki element iz liste

• ubaci k x lista - ubacuje u listu na poziciju k element x

• izbaciSvaki n lista - izbacuje svaki n-ti element iz liste (broji se od 1)

[Rešenje 3.9]

3.2.3 Zadaci za vežbu

Zadatak 3.10 Napisati sledeće funkcije:

• prosti n - vraća listu prvih n prostih brojeva

• pitagorineTrojke n - vraća listu Pitagorinih trojki (a,b,c) takvih da su a,b,c<=n

• proizvodPar n - vraća listu parova (a,b) takvih da su a i b prirodni brojevi i da je proizvoda i b manji od n

• podeli n lista - deli listu na dve liste, prva lista sadrži prvih n elemenata, a druga listasadrži ostatak

• pretposlednji lista - vraća pretposlednji element liste

• izbrisiPrvi x lista - briše prvo pojavljivanje broja x u listi

• palindrom lista - ispituje da li je lista palindrom

• pozNeg lista - vraća par (a, b) takav da a predstavlja broj True elemenata u listi, a bpredstavlja broj False elemenata u listi

• izmedju a b lista - vraca listu elemenata koji su veći od a, a manji od b

3.3 Funkcije

3.3.1 Uvodni primeri

Zadatak 3.11

40

Page 46: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3.3 Funkcije

1 {-Karijeve funkcije (uzimaju jedan po jedan element)

3

add :: (Int, Int) -> Int5 Karijeva verzija:

add1 :: Int -> Int -> Int7 -}

9 add1 :: Int -> Int -> Int{-

11 -> je desno asocijativnaadd1 :: Int -> (Int -> Int)

13 -}add1 x y = x + y

15

{-17 Primena funkcije je levo asocijativna

19 add1 x y === ((add1 x) y)

21 Polimorfne funkcije - sadrze jednu ili vise tipskih promenljivih

23 length1 :: [a] -> Int (a je tipska promenljiva, moze da bude bilo kog tipa)

25 Preopterecene funkcije (overloaded) - sadrze jednu ili vise tipskih promenljivihkoje propadaju nekom tipskom razredu

27 sum :: Num a => [a] -> a (a mora biti numerickog tipa)-}

29

sum1 :: Num a => [a] -> a31 sum1 [x] = x

sum1 (x:xs) = x + sum1 xs33

{-35 Lambda (anonimne) funkcije

37 \ x = x + x-}

39

add2 = \x -> (\y -> x + y )41

{-43 Sekcije

45 Operatore mozemo zapisati kao Karijeve funkcije:(+) x y <-> x+y

47 (+2) x <-> x+2

49 Generalno ako je op operator(op), (x op), (op y) nazivamo sekcijama

51 -}

53 duplo x = (*2) x

55

{-57 Funkcija zip pravi listu torki od dve liste

tako sto spaja elemente prve liste sa elementima druge liste59 -}

61 spojeno1 = zip ['a', 'b', 'c'] [1,2,3]spojeno2 = zip ['a', 'b', 'c'] [1,2,3,4,5,6]

63 spojeno3 = zip ['a', 'b', 'c'] [1,2]

Zadatak 3.12

1 {-Funkcije viseg reda

3 -funkcije koje uzimaju funkciju kao argument ili vracaju funkciju kao rezultat

5 Funkcija map

41

Page 47: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3 Funkcionalno programiranje

- kao prvi argument uzima funkciju koju primenjuje na sve elemente liste7 koju uzima kao drugi argument

9 map :: (a -> b) -> [a] -> [b]

11 -}

13 povecaj lista = map (+1) lista

15 {-Funkcija filter

17 - kao prvi argument uzima funkciju uslova (funkcija koja vraca logicku vrednost)i izdvaja iz liste koju uzima kao drugi argument

19 sve elemente koji zadovoljavaju zadat uslov

21 filter :: (a -> Bool) -> [a] -> [a]

23 -}

25 pozitivni lista = filter (>0) lista

27 {-Jos neke funkcije viseg reda za rad sa listama:

29

any uslov lista - vraca True ako postoji element u listi koji zadovoljava uslov,False inace

31 all uslov lista - vraca True ako svi elementi u listi zadovoljavaju uslov, Falseinace

takeWhile uslov lista - izdvaja jedan po jedan element liste sve dok ne stigne doelementa koji ne zadovoljava uslov

33 dropWhile uslov lista - izbacuje jedan po jedan element liste sve dok ne stigne doelementa koji ne zadovoljava uslov

sum lista - sabira elemente liste35 product lista - mnozi elemente liste

reverse lista - obrce listu37 unzip - spaja listu parova u dve liste

concat lista - spaja liste iz liste listi u jednu listu39 elem e lista - vraca True ako e postoji u listi, False inace

replicate n x - kopira broj x n puta41

-}43

prviNePozitivni lista = takeWhile (<=0) lista45

{-47 Funkcija foldr

- enkapsulira sledeci sablon rekurzije49

f [] = v - f preslikava praznu listu u vrednost v51 f (x:xs) = x op (f xs) - nepraznu listu preslikava u funkciju op

primenjenu na glavu liste (x) i f od repa liste (f xs)53

Npr:55 -}

57 sum1 [] = 0 -- v = 0sum1 (x:xs) = x + sum1 xs -- op = +

59

sum2 lista = foldr (+) 0 lista61

{-63 Kompozicija funkcija

65 (f . g) x <-> f (g x)-}

67

negativneSume liste = map (negate . sum) liste69 -- negativneSume [[1..5], [6..10], [11..15]]

71 {-Cesto nam je potrebno da listu zadamo na sledeci nacin:

73

lista = [f(x) | x<-D, p(x)]

42

Page 48: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3.3 Funkcije

75

to mozemo jednostavno uraditi koristeci funkcije map i filter77

map f(filter p xs)79 -}

81 povecajPozitivne [] = []povecajPozitivne lista = map (+1) (filter (>0) lista)

3.3.2 Zadaci za samostalni rad sa rešenjima

Zadatak 3.13 Napisati sledeće funkcije:

• pozicije x lista - vraća listu pozicija broja x u listi

• qsort lista - sortira listu algoritmom qsort

• brisiPonavljanja lista - briše sva uzastopna ponavljanja elemenata u listi

• podlistePonavljanja lista - pakuje sva uzastopna ponavljanja nekog elementa u podlistutako da rezultat bude lista listi

• imaDuplikata lista - ispituje da li u listi postoje duplikati

• uzastopniParovi lista - vraća listu uzastopnih parova

• broj lista - vraća broj određen ciframa koje se nalaze u listi u obrnutom poretku

• broj1 lista - vraća broj određen ciframa koje se nalaze u listi

[Rešenje 3.13]

Zadatak 3.14 Napisati sledeće funkcije (koristiti funkcije map, foldr ili filter):

• sumaKvNeg lista - računa sumu kvadrata negativnih elemenata iz liste (koristiti funkciju

• malaSlova lista - računa broj malih slova unutar liste

• sume lista - vraća listu suma elemenata svake podliste

• spoji lista - spaja sve podliste u jednu listu

• listaUPar lista - pretvara listu parova u par dve liste, tako da prva lista sadrži sve prveelemente parova a druga sve druge (implementacija funkcije unzip)

• parOdListi lista1 lista2 - pravi listu parova od dve liste, tako da prvi element svakogpara bude iz prve liste, a drugi element svakog para bude iz druge liste (implementacijafunkcije zip)

• ucesljaj lista1 lista2 - pravi listu naizmeničnim učešljavanjem elemenata listi

[Rešenje 3.14]

3.3.3 Zadaci za vežbu

Zadatak 3.15 Napisati sledeće funkcije:

• paroviPonavljanja lista - pravi listu parova (x,k) takvih da je x element iz liste, a k brojkoliko se puta x uzastopno pojavljuje u listi

• sortirana lista - ispituje da li je lista sortirana

• permutacija lista1 lista2 - ispituje da li je lista1 permutacija liste2

• izdvoji a b lista - izdvaja elemente liste od pozicije a do pozicije b

43

Page 49: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3 Funkcionalno programiranje

• izbrisi x lista - brise sva pojavljivanja broja x u listi

• ponovi n lista - svaki element iz liste ponavlja n puta

Zadatak 3.16 Napisati sledeće funkcije (koristiti funkcije map, foldr ili filter):

• brojPoz lista - računa broj pozitivnih elemenata liste

• eliminisiProste lista - eliminiše sve proste brojeve iz listi

• saberiAbs lista - sabira apsolutne vrednosti elemenata iz liste

• nadoveziProizvod lista - svakoj podlisti nadovezuje proizvod njenih elemenata

• prosek lista - računa prosek liste

• brojPojavljivanja x lista - vraća broj pojavljivanja broja x u listi

3.4 Rešenja

Rešenje 3.4

1 -- Pretpostavljamo da funkciju koristimo samo za n>=1proizvodPrvih n

3 | n == 1 = 1| otherwise = n * proizvodPrvih (n-1)

5

-- Ispitujemo da li je broj prost tako sto pozovemo pomocnu funkciju7 -- koja ispituje da li postoji neki broj pocev od 2 do n koji deli broj n

prost n = prost1 n 29

-- Proveravamo da li postoji broj koji deli n (pocev od broja 2 - poziv iz prethodnefunkcije)

11 -- ukoliko je k == n to znaci da smo proverili za svaki broj od 2 do n-1-- i ustanovili da nijedan od njih ne deli n tako da vracamo True kao indikator da

broj n jeste prost13 -- ukoliko je n deljivo sa k, vracamo False (n nije prost)

-- ukoliko n nije deljivo sa k, pozovemo funkciju rekurzivno za sledeci broj (k+1)15 prost1 n k

| n == k = True17 | n `mod` k == 0 = False

| otherwise = prost1 n (k+1)19

nzd a b21 | b == 0 = a

| otherwise = nzd b (a `mod` b)23

tipJednacine a b c25 | a == 0 = "Degenerisana"

| (b*b - 4*a*c) == 0 = "Jedno resenje"27 | (b*b - 4*a*c) > 0 = "Dva resenja"

| otherwise = "Nema resenja"29

uDekadnu x osn = if x==0 then 0 else uDekadnu (x `div` 10) osn * osn + (mod x 10)31

izDekadne x osn = if x==0 then 0 else izDekadne (x `div` osn) osn * 10 + (mod x osn)33

-- Trazimo ceo deo korena broja x35 -- trazimo prvi broj (pocev od 1) ciji je kvadrat veci od kvadrata naseg broja x

-- i kao rezultat vracamo broj koji je za jedan manji37 ceoDeo x = ceoDeo1 x 1

39 ceoDeo1 x i| (i*i) > x = (i-1)

41 | otherwise = ceoDeo1 x (i+1)

44

Page 50: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3.4 Rešenja

Rešenje 3.5

1 -- Pravimo listu prvih n elemenata harmonijskog reda (n>0)-- ukoliko je n = 1, vracamo listu koja sadrzi prvi element harmonijskog reda

3 -- inace pozovemo funkciju rekurzivno za n-1-- i na rezultat nadovezemo reciprocnu vrednost broja n

5 harm n| n == 1 = [1.0]

7 | otherwise = harm (n-1) ++ [recip n]

9 -- Pravimo listu delioca broja n-- ukoliko je n = 1, vracamo listu koja sadrzi samo 1

11 -- inace pozivamo pomocnu funkciju sa jos jednim parametrom-- koji nam govori do kog potencijalnog delioca smo stigli

13 delioci n| n == 1 = [1]

15 | otherwise = delioci1 n 2

17 -- Pravimo listu delioca broja n pocev od broja k-- ukoliko smo stigli do broja n (k==n) vracamo praznu listu

19 -- inace proveravamo da li je k delioc broja n-- ako jeste, stavljamo ga u listu i pozivamo funkciju rekurzivno

21 -- za k+1 (sledeci potencijalni delilac)-- inace samo pozivamo funkciju rekurzivno za k+1

23 delioci1 n k| k == n = []

25 | n `mod` k == 0 = [k] ++ (delioci1 n (k+1))| otherwise = delioci1 n (k+1)

27

-- Nadovezujemo listu2 na listu1 n puta29 -- ukoliko je n == 1 na listu1 nadovezemo listu2 operatorom ++

-- inace pozovemo funkciju rekurzivno za n-1 i na rezultat nadovezemo listu231 nadovezi lista1 lista2 n

| n == 1 = lista1 ++ lista233 | otherwise = (nadovezi lista1 lista2 (n-1)) ++ lista2

Rešenje 3.9

bezbedanRep1 lista = if lista == [] then [] else tail lista2

bezbedanRep2 lista4 | lista == [] = []

| otherwise = tail lista6

bezbedanRep3 [] = []8 bezbedanRep3 (x:xs) = xs

-- bezbedanRep3 lista = tail lista10

savrseni n = [x | x<-[1..n], sum(faktori x) == x]12 faktori x = [i | i<-[1..x-1], x `mod` i ==0]

14 zbirPar n = [(a,b)| a<-[1..n], b<-[1..n], a+b==n]-- drugi, efikasniji nacin

16 zbirPar2 n = [(a,b)| a<-[1..n], b<-[n-a], b/=0]

18 polovina [] = ([],[])polovina lista = (take n lista, drop n lista)

20 where n = length lista `div` 2

22 poslednji lista = lista !! pozwhere poz = length lista - 1 -- moze i: length(tail lista) -1

24

spoji [] = [] -- nije neophodno, prolazi drugi sablon i za praznu listu26 spoji lista = [x | podlista <- lista, x <- podlista]

28 sufiksi [] = [[]]-- lista je sama svoj sufiks, a ostali sufiksi su sufiksi njenog repa

30 sufiksi (x:xs) = (x:xs) : sufiksi xs

32 obrni [] = []obrni (x:xs) = obrni xs ++ [x]

34

45

Page 51: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3 Funkcionalno programiranje

izbaci _ [] = []36 izbaci 0 (x:xs) = xs

izbaci k (x:xs) = x : (izbaci (k-1) xs)38

duplira [] = []40 duplira (x:xs) = [x,x] ++ duplira xs

42 ubaci 0 n lista = n : listaubaci k n [] = [n]

44 ubaci k n (x:xs) = x : (ubaci (k-1) n xs)

46 izbaciSvaki n [] = []izbaciSvaki n lista = take (n-1) lista ++ izbaciSvaki n (drop n lista)

Rešenje 3.13

-- Racunamo sve pozicije broja x u listi2 -- tako sto spajamo listu sa listom brojeva od 0 do n

-- i od liste parova (broj, pozicija)4 -- izdvajamo one pozicije kod kojih je broj = x

pozicije :: Eq a => a -> [a] -> [Int]6 pozicije x [] = []

pozicije x lista = [i | (x1,i) <- zip lista [0..n], x == x1]8 where n = length lista - 1

10 qsort :: Ord a => [a] -> [a]qsort [] = []

12 qsort (x:xs) = qsort manji ++ [x] ++ qsort veciwhere manji = [a | a<-xs, a <= x]

14 veci = [b | b<-xs, b > x]

16 -- Pravimo listu bez uzastopnih ponavljanja-- tako na glavu nadovezemo rezultat rekurzivnog poziva funkcije nad korigovanim

repom18 -- sa pocetka repa izbacujemo sve elemente koji su jednaki glavi

-- [1,1,1,1,1,2]20 -- 1 : brojPonavljanja [2]

-- [1,2]22 brisiPonavljanja :: Eq a => [a] -> [a]

brisiPonavljanja [] = []24 brisiPonavljanja (x:xs) = x : brisiPonavljanja(dropWhile (==x) xs)

26 -- Pravimo listu koja sadrzi sva uzastopna pojavljivanja elemenata u posebnim listama-- [1,1,1,2,2,3] -> [[1,1,1], [2,2], [3]]

28 -- tako sto pravimo listu uzastopnih pojavljivanja glave-- i pozivamo funkciju rekurzivno pocev od elementa koji nije jednak glavi

30 -- [[1,1,1] , podlistePonavljanja [2,2,3]]-- [[1,1,1], [2,2], podlistePonavljanja [3]]

32 -- [[1,1,1], [2,2], [3], podlistePonavljanja []]podlistePonavljanja :: Eq a => [a] -> [[a]]

34 podlistePonavljanja [] = []podlistePonavljanja (x:xs) = (x : (takeWhile (==x) xs)) : podlistePonavljanja(

dropWhile (==x) xs)36

-- Ispitujemo da li lista sadrzi duplikate38 -- ukoliko je lista prazna vracamo False

-- inace, ukoliko se glava nalazi jos negde u repu vracamo True40 -- odnosno pozivamo funkciju rekurzivno za rep

imaDuplikata :: Eq a => [a] -> Bool42 imaDuplikata [] = False

imaDuplikata (x:xs) = elem x xs || imaDuplikata xs44

-- Pravimo listu uzastopnih parova tako sto spajamo svaki element liste46 -- sa elementima iz repa

-- [1,2,3,4] [2,3,4] -> [(1,2), (2,3), (3,4)]48 uzastopniParovi :: [a] -> [(a,a)]

uzastopniParovi [] = []50 uzastopniParovi lista = zip lista (tail lista)

52 -- [1,2,3] -> 321broj :: Num a => [a] -> a

54 broj [] = 0

46

Page 52: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3.4 Rešenja

broj (x:xs) = (broj xs)*10 + x56

-- [1,2,3] -> 12358 broj1 [] = 0

broj1 (x:xs) = x*10^(length xs) + broj xs60

-- Drugi nacin koriscenjem funkcije broj62 -- broj1 lista = broj (reverse lista)

Rešenje 3.14

-- Racunamo sumu kvadrata negativnih elemenata liste2 -- tako sto izdvajamo negativne elemente funkcijom filter u listu negativni

-- i primenjujemo operaciju kvadriranja nad svim elementima liste negativni4 -- koristeci funkciju map i rezultat nazivamo kvadrati

-- nakon toga sabiramo elemente liste kvadrati u akumulator cija je pocetna vrednost= 0

6 -- Podsetnik: celobrojni stepen - ^ , realni stepen - ^^sumaKvNeg1 :: (Ord a, Fractional a) => [a] -> a

8 sumaKvNeg1 [] = 0sumaKvNeg1 lista = foldr (+) 0 kvadrati

10 where kvadrati = map (^2) negativninegativni = filter (<0) lista

12

-- Drugi nacin: pravimo kompoziciju funkcija filter, map i fold14 sumaKvNeg2 :: [Double] -> Double

sumaKvNeg2 [] = 016 sumaKvNeg2 lista = suma lista

suma = (foldr (+) 0 ) . (map (^2)) . (filter (<0))18

-- Racunamo broj malih slova u listi tako sto primenjujemo kompoziciju funkcija20 -- filter - filtriramo karaktere tako da nam ostanu samo mala slova

-- i nakon toga racunamo duzinu rezultujuce liste - funkcija length22 malaSlova :: [Char] -> Int

malaSlova [] = 024 malaSlova lista = (length . (filter (\x -> if x>='a' && x<='z' then True else False)

)) lista

26 -- Pravimo listu suma svih elemenata podlisti-- tako sto primenjujemo funkciju sum nad svakom podlistom koristeci funkciju map

28 sume :: Num a => [[a]] -> [a]sume [] = []

30 sume lista = map (sum) lista

32 -- Spajamo podliste u jednu listu-- tako sto nadovezujemo svaku podlistu na akumulator cija je pocetna vrednost

jednaka []34 -- koristeci funkciju foldr

-- [[1,1], [2,2,2], [3,3,3]] - []36 -- [[2,2,2], [3,3,3]] - [1,1]

-- [[3,3,3]] - [1,1,2,2,2]38 -- [] - [1,1,2,2,2,3,3,3]

spoji :: [[a]] -> [a]40 spoji [] = []

spoji lista = foldr (++) [] lista42

-- Pravimo par listi od liste parova kao sto radi funkcija unzip44 -- [(1,2), (1,2), (1,2)] -> ([1,1,1], [2,2,2])

-- tako sto svaki par iz liste dodajemo u akumulator cija je pocetna vrednost parpraznih listi

46 -- [(1,2), (1,2), (1,2)] - ([],[])-- [(1,2), (1,2)] - ([1],[2])

48 -- [(1,2)] - ([1,1],[2,2])-- [] - ([1,1,1],[2,2,2])

50 listaUPar :: [(a,b)] -> ([a],[b])listaUPar [] = ([],[])

52 listaUPar lista = foldr (\ (a,b) (c,d) -> (a:c, b:d)) ([],[]) lista

54 {- Drugi nacin bez foldr:listaUPar [] = ([],[])

56 listaUPar ((a,b):xs) = (a:l1, b:l2)where

47

Page 53: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

3 Funkcionalno programiranje

58 l1 = fst repl2 = snd rep

60 rep = listaUPar xs-}

62

-- Implementacija funkcije zip64 -- [1,2,3] [4,5,6] -> [(1,4), (2,5), (3,6)]

-- Da bi radila po duzini krace liste neophodno je dodati sablone za takve situacije66 parOdListi [] _ = []

parOdListi _ [] = []68 -- Od glava listi pravimo par koji dodajemo na pocetak rezultujuce liste za rep

parOdListi (x:xs) (y:ys) = ( (x, y) : (parOdListi xs ys))70

-- [1,1,1] [2,2,2] -> [1,2,1,2,1,2]72 -- [1,1] [2,2,2,2] -> [1,2,1,2,2,2]

-- Treba obuhvatiti slucajeve listi razlicitih duzina74 -- Sledeca linija koda ne radi jer nije dozvoljeno koriscenje dzoker promenljive u

izrazu kojim definisete vrednost funkcije-- ucesljaj [] _ = _

76 ucesljaj [] lista = listaucesljaj lista [] = lista

78 ucesljaj (x:xs) (y:ys) = [x]++[y]++(ucesljaj xs ys)

48

Page 54: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4

Konkurentno programiranje

4.1 ScalaKoristicemo jezik Scala-u (verzija 2.11) http://www.scala-lang.org/.

Potrebno je imati instalirano:

(a) Jezik Scala-u verziju 2.11

(b) Eclipse Neon razvojno okruzenje https://www.eclipse.org/downloads/

(c) ScalaIDE dodatak za Eclipse razvojno okruzenje http://scala-ide.org/

Korisni linkovi:https://www.scala-lang.org/documentation/http://docs.scala-lang.org/tutorials/scala-for-java-programmers.html http://scalatutorials.com/

4.1.1 Uvod u jezik Scala

Zadatak 4.1 HelloWorld

/**2 * Viselinijske komentare u Scali pisemo ovako (isto kao i u C-u).

*4 * */

6 // Jednolinijske komentare pisemo ovako

8 object HelloWorld {def main(args: Array[String]){

10 // Tacka zapeta na kraju svake naredbe je opcionaprintln("Hello world! :)")

12 }}

Zadatak 4.2 Promenljive, niske, petlje, funkcije

1

object Uvod {3 def main(args: Array[String]){

5 println("------- Promenljive -------")// Promenljive mozemo deklarisati kao konstantne

7 // ili promenljive cija se vrednost moze menjati.// Kljucna rec val deklarise konstantu a var promenljivu.

9 //// kljucnaRec imePromenljive : tipPromenljive = vrednost

11 //val c : Int = 42

13 var x : Int = 6

49

Page 55: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

15 x += 6

17 // Naredba://

19 // c += 4//

21 // prijavljuje gresku.

23

println("Konstanta: " + c)25 println("Promenljiva: " + x)

27 if(x > 6)println("Promenljiva x je veca od 6.")

29 else if(x == 6)println("Promenljiva x je jednaka 6.")

31 elseprintln("Promenljiva x je manja od 6.")

33

println("------- Niske -------")35

val crtani : String = "Maza i Lunja"37 println("Duzina niske: '" + crtani + "' je " + crtani.length())

39 // Viselinijske niske pisemo izmedju trostrukih navodnika:println(""" Likovi:

41 -Alisa-Vendi

43 -Bambi-Had

45 """)// Interpolacija niski

47

// Scala nam dozvoljava da ugnjezdavamo vrednosti promenljivih u niske49 // dodavanjem karaktera s na pocetak niske (npr: s"Moja niska") omogucavamo

// ugnjezdavanje vrednosti promenljivih u nisku dodavajuci karakter $ pre imenapromenljive

51 // (npr s"Kolicina: $kol grama")

53 var trajanje : Int = 76println(s"Crtani film: '$crtani' - $trajanje minuta.")

55

println("------- Petlje -------")57

var sat = 059

while(trajanje >= 60){61 sat += 1

trajanje -= 6063 }

65 println(s"'$crtani' traju $sat sat i $trajanje minuta.")

67 // For petljom mozemo iterirati kroz kolekcije koristeci sintaksu//

69 // for(element <- kolekcija)//

71 // 1 to 5 - pravi kolekciju brojeva [1,5]

73 println("FOR - 1 to 5 ")for(i <- 1 to 5)

75 println(i)

77 // 1 until 5 - pravi kolekciju brojeva [1,5)

79 println("FOR - 1 until 5 ")for(i <- 1 until 5)

81 println(i)

83 // Range(pocetak, kraj, korak) - pravi kolekciju [pocetak, kraj) sa zadatikkorakom.

// Korak moze biti i negativan npr. Range(10,0,-2)85

50

Page 56: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.1 Scala

println("FOR - Range(0,6,2) ")87 for(i <- Range(0,6,2))

println(i)89

91 println("------- Nizovi -------")// Pravimo ih na sledeci nacin:

93 // var niz : Array[tip] = new Array[tip](brojElemenata)var crtaci : Array[String] = new Array[String](5)

95 crtaci(0) = "Petar Pan"crtaci(1) = "Mulan"

97 crtaci(2) = "Aladdin"crtaci(3) = "Herkules"

99 crtaci(4) = "Pocahontas"

101 println("Crtaci: ")for(crtac <- crtaci)

103 println(crtac)

105 println("------- Funkcije -------")ispisiSortirano(crtaci)

107 }

109 // def imeFunkcije([listaArgumenata]) : povratnaVrednost = {// teloFunkcije

111 // }

113 // Povratna vrednost Unit je ekvivalentna void vrednostidef ispisiSortirano(crtaci : Array[String]) : Unit = {

115 println("Sortirani crtaci:")for(crt <- crtaci.sortWith(poredi))

117 println(crt)

119 // Anonimne funkcije//

121 // (listaArgumenata) => {teloFunkcije}

123 println("Sortirani crtaci koristeci anonimnu funkciju:")for(crt <- crtaci.sortWith((c1 , c2) => { if(c1.compareTo(c2) < 0) false else

true} ))125 println(crt)

127 }

129 def poredi(c1 : String, c2 : String) : Boolean = {if(c1.compareTo(c2) < 0)

131 return trueelse

133 return false}

135 }

Zadatak 4.3 Klase, objekti, nasledjivanje

2 // Klase se u Scali konstruisu na sledeci nacin://

4 // class ImeKlase {// teloKlase

6 // }// ili

8 // class ImeKlase (argumentiKonstruktora) {// teloKlase

10 // }//

12

class Film {14 var naslov : String = ""

var trajanje : Int = 016 var godina : Int = 0

18 // Konstruktordef this(nas : String, traj : Int, god : Int) = {

51

Page 57: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

20 this()this.naslov = nas

22 this.trajanje = trajthis.godina = god

24 }

26 // Metodi klase

28 def getNaslov() : String = {return this.naslov

30 }

32 def getTrajanje() : Int = {return this.trajanje

34 }

36 def getGodina() : Int = {return this.godina

38 }

40 override def toString() : String = {return "Film " + this.naslov + ", traje " + this.trajanje + " minuta , napravljenje " + this.godina + " godine"

42 }}

44

// Nasledjivanje46 class CrtaniFilm extends Film {

var animator : String = ""48

def this(nas : String, traj : Int, god : Int, anim : String) = {50 this()

this.naslov = nas52 this.trajanje = traj

this.godina = god54 this.animator = anim

}56

def getAnimator() : String = {58 return this.animator

}60

override def toString() : String = {62 return "Crtani " + super.toString() + ", animator je " + this.animator

}64 }

66 // U Scali mozemo definisati takozvane 'singleton' objekte kljucnom reci object.// Garantuje se da ce postojati tacno jedan 'singleton' objekat na nivou naseg

programa68 // i on se najcesce koristi za implementaciju main metoda

object Program {70

def main(args: Array[String]) {72

val assassinsCreed = new Film("Assassin's Creed", 115, 2016)74 val tarzan = new CrtaniFilm("Tarzan", 88 , 1999, "Walt Disney")

76 println(assassinsCreed)println(tarzan)

78

// Scala nudi brojne korisne kontejnerske i nizovske klase80 // kao sto su Array, ArrayBuffer, Map, HashMap, Queue, Tuple1, Tuple2, i druge

// sa kojima cemo se susretati u narednim primerima82 // gde ce biti vise objasnjene

}84

}

4.1.2 Zadaci

52

Page 58: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.1 Scala

Zadatak 4.4 Restoran Pet konobara radi u restoranu, i nakon što dođu na posao, poslo-vođa im dodeli broj stolova koje moraju da usluže. Napisati program koji učitava sa standardnogulaza broj neusluženih stolova u restoranu i raspoređuje ih konobarima. Nakon što usluže jedansto, konobari šalju poruku tako da poslovođa u svakom trenutku ima uvid u brojčano stanje. Kono-bare implementirati kao posebne niti koje uslužuju sto (spavaju nasumično izabran broj sekundi),ispisuju redni broj stola koji su uslužili i po završetku ispisuju poruku da su završili.

[Rešenje 4.4]

Zadatak 4.5 Nastavno osoblje Koristeći biblioteku HtmlCleaner http://htmlcleaner.sourceforge.net/index.php napisati program koji dohvata imena, prezimena i email naloge na-stavnog osoblja Matematičkog fakulteta sa sledecih stranica:

• http://www.matf.bg.ac.rs/redovni/

• http://www.matf.bg.ac.rs/vanredni/

• http://www.matf.bg.ac.rs/docenti/

• http://www.matf.bg.ac.rs/asistenti/

• http://www.matf.bg.ac.rs/saradnici/

i upisuje ih u odgovarajuće datoteke. Svaku stranicu obraditi u posebnoj niti.

[Rešenje 4.5]

Zadatak 4.6 Množenje matrica Napisati program koji konkurentno množi dve matricečiji se elementi nalaze u datotekama matrica1.txt i matrica2.txt i rezultat upisuje u datotekumatrica3.txt. Svaka nit treba da računa vrednosti za jednu vrstu rezultujuće matrice. Formatpodataka u datotekama je sledeći:

1 n m2 a11 a12 a13 ... a1m3 a21 a22 a21 ... a2m4 ...5 an1 an2 an3 ... anm

[Rešenje 4.6]

Zadatak 4.7 Broj karaktera DNK Napisati program koji konkurentno prebrojava ko-liko puta se koja baza (A, C, G, T) pojavljuje u DNK sekvenci koja se nalazi u višelinijskoj datotecibio_podaci.txt. Sa standardnog ulaza učitati broj niti. Svakoj niti dodeliti određen broj linijakoji ce da obrađuje a rezultate čuvati u deljenoj mapi (pogodno je koristiti klasu ConcurrentHash-Map).

[Rešenje 4.7]

Zadatak 4.8 Krediti Bogoljub otvara banku i poseduje određeni kapital. Kao svakidobar ekonomista on odlučuje da zaradi na davanju kredita. Napisati program koji demonstrirarad službenica i davanje kredita u Bogoljubovoj banci. Sa standardnog ulaza učitati njegov početnikapital, kamatnu stopu i broj zaposlenih službenica. U datoteci red_klijenata.txt se nalazi spisakklijenata koji čekaju na red za razgovor sa službenicom u sledećem formatu:

1 imeKlijenta potrebnaPozajmica

Posao svake službenice se izvršava u posebnoj niti. Službenica poziva sledećeg klijenta iz redana razgovor. Nakon što ustanovi koliko je novca klijentu potrebno, službenica proverava da libanka trenutno poseduje tu količinu novca i daje klijentu kredit tako što umanjuje kapital bankei klijentu računa vrednost duga u skladu sa kamatom. Ukoliko banka nije u mogućnosti da izdakredit, ispisati odgovarajuću poruku. Nakon što službenice završe sa svim klijentima iz reda ispisatiporuku o ukupnoj zaradi banke.

[Rešenje 4.8]

53

Page 59: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

Zadatak 4.9 Kladionica Napisati program koji simulira proces klađenja. Kladioničarise klade na ishod pet fudbalskih utakmica uplaćujuči određenu količinu novca na tiket. U datotecikladionicari.txt se nalazi spisak kladioničara i njihovih tiketa u sledećem formatu:

1 imeKladionicara svotaNovca2 utakmica13 rezultat4 ...5 utakmica56 rezultat7 ...

Ishod može biti 1 - prva ekipa je pobedila, x - nerešeno, 2 - druga ekipa je pobedila. Svaki ishodnosi određenu kvotu kojom se množi novac koji je kladioničar uplatio. U datoteci utakmice.txtse nalazi spisak utakmica sa njihovim kvotama u formatu:

1 imeUtakmice2 kvota1 kvotaX kvota23 ...

Učitati podatke o utakmicama i kladioničarima. Svaki kladioničar čeka na ishod utakmica u poseb-noj niti. Kladionica nakon što dobije ishod utakmica (implementirati nasumično biranje ishoda)obaveštava kladioničare da su utakmice završene. Kladioničari nakon toga računaju sopstvenuzaradu kao zbir kvota pogođenih utakmica pomnoženih sa odgovarajućim delom novca i ispisujuporuku o pogodjenom rezultatu. Na kraju ispisati ukupnu količinu novca koju kladionica treba daisplati kladioničarima.

[Rešenje 4.9]

4.1.3 Zadaci za vežbu sa rešenjima

Zadatak 4.10 Zbir vektora Napisati program koji konkurentno sabira dva vektora.Sa standardnog ulaza se učitava dimenzija vektora, elementi oba vektora i broj niti. Svakoj nitidodeliti indeks početka i kraja vektora nad kojim računa zbir a rezultat smeštati u prvi vektor.Indekse računati na osnovu dimenzije vektora i broja niti. Rezultujući vektor ispisati na standardniizlaz.

[Rešenje 4.10]

Zadatak 4.11 Broj petocifrenih brojeva Napisati program koji konkurentno računabroj pojavljivanja petocifrenih brojeva koji se nalaze u datotekama čija imena se učitavaju sastandardnog ulaza. Svakoj niti dodeliti po jednu datoteku nad kojom će računati. Rezultatebrojanja smeštati u lokalne promenljive unutar niti i po završetku računanja za svaku datotekuispisati broj pojavljivanja petocifrenih brojeva.

[Rešenje 4.11]

Zadatak 4.12 Berba Milovan ima voćnjak u kome gaji trešnje, kajsije, kruške i šljive.Došlo je vreme berbe i mora uposliti mlade studente da oberu voćnjak. U datoteci drvoredi.txtse nalaze podaci o drvoredima voćnjaka u sledećem formatu:

1 vrstaVoca brojStabala

Sa standardnog ulaza učitati broj zaposlenih studenata a iz datoteke učitati podatke o drvoredima.Svaka nit predstavlja jednog studenta. Student odlazi do jednog drvoreda skidajući ga iz reda dr-voreda koje je potrebno obrati i počinje branje. Ako pretpostavimo da jedno stablo voća možeroditi od 30-50 kilograma voća, student za svako stablo iz drvoreda nasumično računa broj kilo-grama voća koji je obran i dodaje ih u skladište. Ukoliko su svi drvoredi obrani studenti prestajusa radom i na standardni izlaz se ispisuje ukupna količina obranog voća svake vrste.

[Rešenje 4.12]

54

Page 60: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.1 Scala

Zadatak 4.13 Turistička agencija Turistička agencija FlyProgrammer organizuje na-gradnu igru i daje pet vaučera od 20% popusta na cenu kupljenje karte svojim klijentima. Udatoteci ucesnici.txt se nalaze podaci o klijentima i cenama u sledećem formatu:

1 ime prezime2 cena

Napisati program koji simulira nagradnu igru. Svaka nit čeka na rezultate nagradne igre za jednogklijenta. Turistička agencija izvlači dobitnike slučajnom selekcijom i nakon završenog izvlačenjaobaveštava niti. Niti proveravaju da li je izvučen odgovarajući klijent i ispisuje poruku o ishodu.

[Rešenje 4.13]

4.1.4 Zadaci za vežbu

Zadatak 4.14 Množenje vektora skalarom Napisati program koji konkurentno množivektor skalarom. Sa standardnog ulaza učitati dimenziju i elemente vektora, skalar i broj niti.Svakoj niti dodeliti deo vektora (indekse početnog i krajnjeg elementa). Nit računa proizvodvektora skalarom za elemente u zadatom opsegu i rezultat smešta u isti vektor. Na kraju ispisatirezultat na standardni izlaz.

Zadatak 4.15 Množenje matrice vektorom Napisati program koji konkurentno množimatricu vektorom. Sa standardnog ulaza učitati dimenziju i elemente vektora, dimenzije i elementematrice i broj niti. Svakoj niti dodeliti deo matrice (indekse početne i krajnje vrste). Nit računaproizvod matrice vektorom za vrste u zadatom opsegu i rezultat smešta u nov vektor. Na krajuispisati rezultat na standardni izlaz.

Zadatak 4.16 Transponovanje matrice Napisati program koji konkurentno transpo-nuje matricu. U datoteci matrica.txt se nalaze dimenzije matrice nakon čega slede elementimatrice. Svaka nit transponuje po jednu vrstu matrice i smešta rezultat u rezultujuću matricu.Na kraju izračunavanja rezultujuću matricu upisati u datoteku transponovana_matrica.txt.

Zadatak 4.17 Matrice (dodatak) Implementirati zadatke 4.6 i 4.16 tako da se brojniti učitava sa standardnog ulaza, i svakoj niti dodeliti broj vrsta koje će obrađivati.

Zadatak 4.18 Seminari konkursi projekti Koristeći biblioteku HtmlCleaner napisatiprogram koji konkurentno dohvata podatke o seminarima, konkursima i projektima Matematičkogfakulteta sa sledecih stranica:

• http://www.matf.bg.ac.rs/nauka-konkursi/

• http://www.matf.bg.ac.rs/seminari/

• http://www.matf.bg.ac.rs/projekti/

i upisuje ih u odgovarajuće datoteke. Svaku stranicu obraditi u posebnoj niti.

Zadatak 4.19 Funkcije nad vektorima Napisati program koji konkurentno računaproizvod, sumu, prosečnu vrednost, broj negativnih i broj pozitivnih elemenata vektora. Sa stan-dardnog ulaza učitavati imena datoteka u kojima se nalaze vektori. Implementirati konkurentnoračunanje na dva načina, koristeći paralelizaciju zadataka i paralelizaciju podataka i uporediti vre-mena izvršavanja (obratiti pažnju na to da je korišćenjem paralelizacije zadataka najveće mogućeubrzanje jednako najsporijem zadatku dok kod paralelizacije podataka ubrzanje zavisi od brojaprocesora, broja niti,...). Na kraju ispisati rezultate svih izračunavanja na standardni izlaz.

Zadatak 4.20 Broj petocifrenih brojeva (dodatak) Implementirati zadatak 4.11uz sledeće izmene. Brojeve učitati iz jedne datoteke brojevi.txt u niz a broj niti učitati sastandardnog ulaza. Svakoj niti dodeliti deo niza brojeva koji će obrađivati a rezultat čuvati udeljenoj promenljivoj tipa AtomicLong.

Zadatak 4.21 Broj karaktera DNK (dodatak) Implementirati zadatak 4.7 tako dase rezultati brojanja baza čuvaju u deljenim promenljivama tipa AtomicLong i na kraju ispisatiprocenat pojavljivanja svake baze u lancu.

55

Page 61: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

Zadatak 4.22 Hotel Hotel Nightlife brine o svojim klijentima i trudi se da im smanjivreme čekanja dok se sređuje soba koju su rezervisali. U datoteci sobe.txt nalaze se brojevi sobakoje je potrebno srediti. Sa standardnog ulaza učitati broj trenutno dostupnih čistačica. Svakanit predstavlja jednu čistačicu. Čistačica skida sobe sa reda soba koje je potrebno srediti i odlazido nje da je sredi (ispisati redni broj sobe u koju je ušla čistačica a nit uspavati na slucajan brojsekundi). Nakon što je sredila sobu, čistačica pronalazi ostavljen bakšiš (slučajan broj od 0-500dinara) i po dogovoru bakšiš ubacuje u zajedničku kutiju. Kada završi sa jednom sobom, čistačicaodlazi do sledeće sobe (skida je sa reda) i nastavlja sve dok red ne postane prazan. Nakon štozavrše sa čišćenjem, čistačice otvaraju kutiju sa bakšišem i dele novac na ravne časti tj. ispisujuna standardan izlaz dobijeni bakšiš.

Zadatak 4.23 Loto Napisati program koji simulira izvlačenje na Loto-u. Izvlače se tribroja iz opsege [1,37] a ukupna vrednost nagradnog fonda se unosi sa standardnog ulaza. Učesniciuplaćuju srećke i pokušavaju da pogode tri broja. U datoteci ucesnici.txt se nalaze informacijeo uplaćenim srećkama u sledećem formatu:

1 ime2 broj1 broj2 broj33 ...

Učitati podatke o učesnicima. Svaki učesnik čeka na kraj izvlačenja u posebnoj niti. Izvlačenjese odvija u glavnoj niti tako što se nasumično biraju tri broja iz opsega [1,37] i po završetku seobaveštavaju niti učesnika. Niti učesnika nakon toga porede izvučene brojeve i ukoliko se svatri poklapaju ispisuju poruku i u ukupnu sumu novca koji je potrebno isplatiti dodaju vrednostnagradnog fonda. Ukoliko se dva od tri broja poklapaju u ukupnu sumu se dodaje 40% nagradnogfonda. Ukoliko se samo jedan broj poklapa u ukupnu sumu se dodaje 10% nagradnog fonda.Na kraju ispisati količinu novca koju je potrebno isplatiti i količinu novca koju je lutrija zaradila(ukoliko zarada postoji).

4.2 Rešenja

Rešenje 4.4 Restoran

1 import java.util.concurrent._import java.util.Scanner

3

// Pravljenje niti5 //

// Da bismo napravili nit potrebno je da definisemo klasu koja nasledjuje klasuThread

7 // i implementiramo metod run cije izvrsavanje pocinje kada nad instancom nase klase// pozovemo metod start.

9 //// Drugi nacin je da nasa klasa implementira interfejs Runnable

11 // i implementira metod run.// Medjutim, da bismo naglasili da zelimo da se metod run nase instance izvrsava kao

posebna nit13 // potrebno je da napravimo instancu tipa Thread kojoj u konstruktoru treba da

prosledimo instancu nase klase// (koja implementira metod run.

15 //

17 class Konobar(ime : String, brStolova : Int) extends Thread {override def run(){

19 for(i <- 0 until brStolova){// Klasa ThreadLocalRandom predstavlja generator slucajnih brojeva

21 // jedinstven na nivou jedne niti.// Metod current() vraca objekat ove klase za trenutnu nit.

23 Thread.sleep(ThreadLocalRandom.current().nextInt(1,10)*1000)println("Konobar " + ime + " je usluzio " + i + ". sto.")

25 }println("Konobar " + ime + " je zavrsio sa posluzivanjem.")

27 }}

56

Page 62: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.2 Rešenja

29

object Restoran {31 def main(args : Array[String]) {

val sc : Scanner = new Scanner(System.in)33

println("Unesite broj neusluzenih stolova u restoranu: ")35 val brojStolova = sc.nextInt()

37 val korak = Math.ceil(brojStolova/5.0).toInt// Pravimo instance niti

39 val stefan = new Konobar("Stefan", korak)val nikola = new Konobar("Nikola", korak)

41 val filip = new Konobar("Filip", korak)val nebojsa = new Konobar("Nebojsa", korak)

43 val djordje = new Konobar("Djordje", brojStolova - 4*korak)

45 // Ukoliko nasa klasa implementira interfejs Runnable//

47 // val stefan = new Thread(new Konobar("Stefan", 10))

49 // Metod start zapocinje izvrsavanje metoda runstefan.start()

51 nikola.start()filip.start()

53 nebojsa.start()djordje.start()

55

57 }}

Rešenje 4.5 Nastavno osoblje

import java.net.URL2 import java.util.concurrent._

import java.io.PrintWriter4 import java.io.File

6 // Dodajemo biblioteku za parsiranje HTML stranica// http://htmlcleaner.sourceforge.net/index.php

8 import org.htmlcleaner._

10 class ParserOsoblja(url : String, datoteka : String) extends Thread {

12 override def run() {// Pravimo novi objekat tipa HtmlCleaner koji parsira HTML datoteku sa zadatim url-

om14 // Neki od korisnih metoda klase HtmlCleaner su:

// - clean(url) - vraca koreni cvor tipa TagNode sadrzaja datog url-a16 // - getInnerHtml(cvor) - vraca string - sadrzaj HTML koda datog cvora

//18 // Neki od korisnih metoda klase TagNode su:

// - getChildTags() - vraca niz dece cvorova tipa TagNode20 // - hasChildren() - vraca true ukoliko cvor ima dece, false inace

// - getAttributeByName(a) - vraca vrednost atributa a22 // - getElementsByName(ime, rekurzivno) - vraca niz dece sa zadatim imenom

// - getElementsByAttValue(a, v, rekurzivno, caseSensitive)24 // - vraca niz dece koja imaju atribut a sa vrednoscu v

// - getElementsHavingAttribute(a,rekurzivno)26 // - vraca niz dece koja imaju atribut a

// ...28 //

val cleaner = new HtmlCleaner()30 val pw : PrintWriter = new PrintWriter(new File(datoteka))

// Dohvatamo korenu etiketu - html32 val root = cleaner.clean(new URL(url))

// Dohvatamo niz etiketa koje imaju klasu employer34 val elements = root.getElementsByAttValue("class", "employer", true, false)

for(el <- elements){36 // Dohvatamo link- a etikete jer se u prvoj nalazi ime osobe

val linkovi = el.getElementsHavingAttribute("href",true)38 // Dohvatamo div etikete jer se u prvoj nalazi korisnicko ime

57

Page 63: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

val divovi = el.getElementsByName("div", true)40 if(linkovi.length != 0 && divovi.length != 0)

pw.append(linkovi(0).getText + " - " + divovi(0).getText + "@matf.bg.ac.rs \n")

42 }pw.close()

44 }}

46

object NastavnoOsoblje {48 def main(args : Array[String]) {

// Pravimo niz niti koje ce da izvlace email adrese nastavnog osoblja na fakultetu50 val niti = new Array[ParserOsoblja](5)

niti(0) = new ParserOsoblja("http://www.matf.bg.ac.rs/redovni/", "redovni_profesori.txt")

52 niti(1) = new ParserOsoblja("http://www.matf.bg.ac.rs/vanredni/", "vanredni_profesori.txt")niti(2) = new ParserOsoblja("http://www.matf.bg.ac.rs/docenti/", "docenti.txt")

54 niti(3) = new ParserOsoblja("http://www.matf.bg.ac.rs/asistenti/", "asistenti.txt")niti(4) = new ParserOsoblja("http://www.matf.bg.ac.rs/saradnici/", "saradnici.txt")

56

// Pokrecemo niti58 for(i <- 0 until 5)

niti(i).start()60 }

}

Rešenje 4.6 Množenje matrica

1 import java.util.concurrent._import java.util.Scanner

3 import java.io.PrintWriterimport java.io.File

5 import scala.Array._

7 class Mnozilac(vrsta1 : Array[Int],matrica2 : Array[Array[Int]],

9 rezultat : Array[Int])extends Thread {

11

var k = matrica2.length*matrica2(1).length / vrsta1.length13 var m = vrsta1.length

15 override def run() {for(i <- 0 until k)

17 rezultat(i) = skProizvod(i)}

19

def skProizvod(j : Int) : Int = {21 var res = 0

for(i <- 0 until m)23 res += vrsta1(i)*matrica2(i)(j)

return res25 }

}27

object MnozenjeMatrica {29 def main(args : Array[String]) {

31 val sc1 : Scanner = new Scanner(new File("matrica1.txt"))val sc2 : Scanner = new Scanner(new File("matrica2.txt"))

33 val pw : PrintWriter = new PrintWriter(new File("matrica3.txt"))

35 // Ucitavamo dimenzije matricaval n = sc1.nextInt()

37 val m1 = sc1.nextInt()val m2 = sc2.nextInt()

39 val k = sc2.nextInt()

41 if(m1 != m2){

58

Page 64: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.2 Rešenja

println("Greska! Dimenzije matrica se moraju poklapati!")43 return

}45

// Funkcija ofDim[Tip](n,m) pravi visedimenzioni niz dimenzija mxn47 val matrica1 = ofDim[Int](n,m1)

val matrica2 = ofDim[Int](m2,k)49 val rezultat = ofDim[Int](n,k)

51 // Ucitavamo elemente prve matricefor(i <- 0 until n)

53 for(j <- 0 until m1)matrica1(i)(j) = sc1.nextInt()

55

// Ucitavamo elemente druge matrice57 for(i <- 0 until m2)

for(j <- 0 until k)59 matrica2(i)(j) = sc2.nextInt()

61 val mnozioci = new Array[Mnozilac](n)

63 // Pravimo niz niti koje ce da racunaju i-tu vrstu rezultata mnozenja matricafor(i <- 0 until n)

65 mnozioci(i) = new Mnozilac(matrica1(i), matrica2, rezultat(i))

67 // Zapocinjemo izvrsavanje nitifor(i <- 0 until n)

69 mnozioci(i).start()

71 // Cekamo da niti zavrse sa izracunavanjemfor(i <- 0 until n)

73 mnozioci(i).join()

75 // Upisujemo rezultujucu matricu u datotekupw.append(s"$n $k \n")

77 for(i <- 0 until n){for(j <- 0 until k)

79 pw.append(s"${rezultat(i)(j)} ")pw.append("\n")

81 }

83 pw.close()}

85 }

Rešenje 4.7 Broj karaktera DNK

1 import java.util.concurrent._import java.util.concurrent.atomic._

3 import java.util.Scannerimport java.io.File

5 import scala.collection.mutable.ArrayBuffer

7 class Brojac(poc : Int, kraj : Int,linije : ArrayBuffer[String],

9 mapaKaraktera : ConcurrentHashMap[Char, Int])extends Thread {

11

override def run() {13 for(i <- poc until kraj){

// Racunamo broj svakog karaktera u liniji15 val a = linije(i).count(_=='a')

val c = linije(i).count(_=='c')17 val g = linije(i).count(_=='g')

val t = linije(i).count(_=='t')19

// Synchronized kljucna rec obelezava kriticnu sekciju21 // i garantuje se da u svakom trenutku tacno jedna nit moze izvsavati naredbe iz

bloka.// Synchronized se moze koristiti na vise nacina:

23 //// Metodi klase

59

Page 65: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

25 //// def f() = synchronized { teloFunkcije }

27 //// Na ovaj nacin smo naglasili da je metod f jedne instance nase klase kriticna

sekcija29 // i u svakom trenutku tacno jedna nit moze izvrsavati ovaj metod te instance.

//31 // Blok instance

//33 // instanca.synchronized { blok }

//35 // Na ovaj nacin smo naglasili da za datu instancu u svakom trenutku

// tacno jedna nit moze izvrsavati naredbe bloka37 // Ovakvo ponasanje mozemo posmatrati i iz drugacijeg ugla.

// Instanca predstavlja monitor objekat.39 // U trenutku kada nit pozeli da izvrsava blok kriticne sekcije,

// ona zakljuca instancu, izvrsi kriticnu sekciju i otkljuca instancu.41 //

// Treba teziti ka tome da kriticna sekcija bude sto manja43 // kako bismo sto vise iskoristili prednosti konkurentnog izvrsavanja

//45 // TODO: Zakomentarisati synchronized blok i videti sta se desava prilikom

pokretanja programa// sa razlicitim brojem niti.

47 // Moguci scenario je da jedna nit procita vrednost iz mape, druga nit nakon togaazurira mapu,

// a prva nit i dalje drzi vrednost koju je procitala pre azuriranja tako da kadaona azurira mapu

49 // rezultat azuriranja nece biti ispravan.//

51 mapaKaraktera.synchronized {mapaKaraktera.replace('a', mapaKaraktera.get('a')+a)

53 mapaKaraktera.replace('c', mapaKaraktera.get('c')+c)mapaKaraktera.replace('g', mapaKaraktera.get('g')+g)

55 mapaKaraktera.replace('t', mapaKaraktera.get('t')+t)}

57 }}

59 }

61 object BrojKarakteraDNK {def main(args : Array[String]) {

63 val sc1 : Scanner = new Scanner(new File("bio_podaci.txt"))val sc2 : Scanner = new Scanner(System.in)

65

println("Unesite broj niti: ")67 println("Broj procesora na racunaru koji su na raspolaganju je : " + Runtime.

getRuntime().availableProcessors())

69 val brojNiti = sc2.nextInt()

71 val brojaci = new Array[Brojac](brojNiti)// Klasa ArrayBuffer predstavlja niz promenljive duzine

73 // Neki od korisnih metoda su:// - append(e) - dodaje element na kraj niza

75 // - isEmpty() - vraca true ukolik je niz prazan, false inace// - insert(i, e) - dodaje element na datu poziciju

77 // ...val linije = new ArrayBuffer[String]()

79

while(sc1.hasNextLine())81 linije.append(sc1.nextLine())

83 val brojLinija = linije.lengthprintln(brojLinija)

85

// Klasa ConcurrentHashMap predstavlja implementaciju mape cije su operacijebezbedne u kontekstu konkurentnog izvrsavanja.

87 // To znaci da u svakom trenutku tacno jedna nit moze izvrsavati operacije nad mapom.

// Medjutim, operacije citanja (get) su neblokirajuce, tako da se mogu preklopiti sadrugim operacijama (npr. azuriranja)

89 // i u takvim slucajevima se ne garantuje azurnost rezultata.

60

Page 66: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.2 Rešenja

//91 // Konstruktor prima tri argumenta:

// - inicijalni kapacitet mape93 // - faktor povecavanja mape

// - broj niti koji se pretpostavlja da ce konkurentno pristupati objektu mape95 //

// Neki od korisnih metoda klase ConcurrentHashMap su:97 // - get(kljuc) - vraca element sa zadatim kljucem, odnosno null ukoliko takav ne

postoji// - put(kljuc, vrednost) - dodaje element sa zadatim parametrima

99 // - remove(kljuc) - uklanja element sa zadatim kljucem// - replace(kljuc, vrednost) - postavlja vrednost elementu sa zadatim kljucem

101 // - size() - vraca velicinu mape// - isEmpty() - vraca true ukoliko je mapa prazna, false inace

103 // ...//

105 val mapaKaraktera = new ConcurrentHashMap[Char, Int](4,4,brojNiti)mapaKaraktera.put('a', 0)

107 mapaKaraktera.put('c', 0)mapaKaraktera.put('g', 0)

109 mapaKaraktera.put('t', 0)

111 val korak = Math.ceil(brojLinija.toDouble/brojNiti.toDouble).toInt

113 for(i <- 0 until brojNiti)brojaci(i) = new Brojac(i*korak, Math.min((i+1)*korak, brojLinija), linije,

mapaKaraktera)115

for(b <- brojaci)117 b.start()

119 for(b <- brojaci)b.join()

121

println("Rezultati konkurentnog izvrsavanja")123 println("A: " + mapaKaraktera.get('a'))

println("C: " + mapaKaraktera.get('c'))125 println("G: " + mapaKaraktera.get('g'))

println("T: " + mapaKaraktera.get('t'))127

println("Pravi rezultati \nA: 1761 \nC: 1577 \nG: 1589 \nT: 1913")129 }

}

Rešenje 4.8 Krediti

1 import java.util.concurrent.atomic._import java.util.concurrent._

3 import java.util.Scannerimport java.io.File

5

class Sluzbenica(kamata : Int,7 kapital : AtomicLong ,

redKlijenata : ConcurrentLinkedQueue[Klijent],9 zaduzeniKlijenti : ConcurrentLinkedQueue[Klijent])

extends Thread {11

override def run() {13 while(true){

// Dohvatamo sledeceg klijenta iz reda15 var k : Klijent = redKlijenata.poll()

// Ukoliko takav ne postoji zavrsavamo17 if(k == null)

return19

println("Klijent " + k.getIme() + " razgovara sa sluzbenicom.")21 Thread.sleep(ThreadLocalRandom.current().nextInt(1,10)*1000)

// Iako je kapital objekat AtomicLong i garantuje se atomicnost operacijaazuriranja

23 // mogu nastati problemi prilikom konkurentnog pristupanja i azuriranja,// i zbog toga je potrebno operacije sa ovim objektom obmotati synchronized

blokom.

61

Page 67: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

25 // Problem moze nastati u delu koda (******).// Pretpostavimo da dve niti izvrsavaju ovaj deo koda konkurentno.

27 // Prva nit procita vrednost kapitala, nakon toga druga nit procita vrednostkapitala

// pre nego sto je prva nit izmenila vrednot, odmah posle prva nit promenivrednost kapitala

29 // i postavi novu vrednot (staraVrednost - prvaPozajmica)/// U ovom trenutku druga nit ima vrednost kapitala koja nije ispravna sa kojom

dalje operise.31 // Druga nit promeni vrednost kapitala i postavi novu vrednost (staraVrednost -

drugaPozajmica)// sto nije realna vrednost (staraVrednost - prvaPozajmica - drugaPozajmica)

33 kapital.synchronized {if(k.getPozajmica() > kapital.get())

35 println("Klijent " + k.getIme() + " ne moze dobiti kredit.")else{

37 k.setDug(k.getPozajmica()*((100+kamata.toFloat)/100))// ******

39 val novKapital = kapital.get() - k.getPozajmica()kapital.set(novKapital)

41 // ******println("Klijent " + k.getIme() + " je dobio kredit u iznosu od "

43 + k.getPozajmica() + "e odnosno sa kamatom " + k.getDug() + "e.")zaduzeniKlijenti.add(k)

45 }}

47 }}

49 }

51 class Klijent(ime : String, pozajmica : Int) {

53 var dug : Float = 0

55 def getIme() : String = {return ime

57 }

59 def getPozajmica() : Int = {return pozajmica

61 }

63 def getDug() : Float = {return dug

65 }

67 def setDug(d : Float) = {dug = d

69 }}

71

object Banka {73 def main(args : Array[String]) {

// Klasa AtomicLong predstavlja enkapsulaciju long integer vrednosti75 // nad kojom se operacije azuriranja izvrsavaju atomicno.

//77 // Neki od korisnih metoda ove klase su:

// - get() - vraca trenutnu vrednost79 // - set(v) - postavlja vrednost v

// - getAndAdd(v) - atomicki dodaje vrednost v i vraca prethodnu vrednost81 // - addAndGet(v) - atomicki dodaje vrednost v i vraca novu vrednost

// - getAndIncrement() - atomicki inkrementira vrednost i vraca prethodnu vrednost83 // - incrementAndGet() - atomicki inkrementira i vraca novu vrednost

// - getAndDecrement() - atomicki dekrementira vrednost i vraca prethodnu vrednost85 // - decrementAndGet() - atomicki dekrementira i vraca novu vrednost

// - compareAndSet(ocekivanaVrednost, novaVrednost) - postavlja novu vrednost87 // ukoliko je stara jednaka ocekivanoj

//89 // U paketu java.util.concurrent.atomic postoje i druge korisne klase kao sto su

// AtomicBoolean, AtomicIntegerArray , AtomicInteger itd.91 val sc1 : Scanner = new Scanner(System.in)

93 println("Unesite pocetni kapital banke: ")

62

Page 68: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.2 Rešenja

val kapital = new AtomicLong(sc1.nextLong())95 val sacuvanKapital : Float = kapital.get()

97 println("Unesite kamatnu stopu: ")val kamata = sc1.nextInt()

99

println("Unesite broj sluzbenica u ekspozituri: ")101 val sluzbenice = new Array[Sluzbenica](sc1.nextInt())

103 val sc2 : Scanner = new Scanner(new File("red_klijenata.txt"))

105 // Klasa ConcurrentLinkedQueue predstavlja implementaciju reda// cije su operacije bezbedne u kontekstu konkurentnog izvrsavanja.

107 //// Neki od korisnih metoda su:

109 // - add(e) - dodaje element u red// - poll() - skida element sa pocetka reda i vraca ga kao rezultat

111 // - peek() - vraca elelent sa pocetka reda (ne skida ga)// - remove(e) - ukljanja element e iz reda

113 // - isEmpty() - vraca true ukoliko je red prazan// ...

115 //val redKlijenata = new ConcurrentLinkedQueue[Klijent]()

117 val zaduzeniKlijenti = new ConcurrentLinkedQueue[Klijent]()

119 while(sc2.hasNextLine())redKlijenata.add(new Klijent(sc2.next(), sc2.nextInt()))

121

for(i <- 0 until sluzbenice.length)123 sluzbenice(i) = new Sluzbenica(kamata, kapital, redKlijenata , zaduzeniKlijenti)

125 for(s <- sluzbenice)s.start()

127

for(s <- sluzbenice)129 s.join()

131 // Iteriramo kroz red zaduzenih klijenata i racunamo ukupno zaduzenjevar ukupnoZaduzenje : Float = 0

133 val iterator = zaduzeniKlijenti.iterator()while(iterator.hasNext())

135 ukupnoZaduzenje += iterator.next().getDug()

137 println(s"Banka je zaradila ${ukupnoZaduzenje -sacuvanKapital}e.")}

139 }

Rešenje 4.9 Kladionica

1 import java.util.concurrent.atomic._import java.util.concurrent._

3 import java.util.Scannerimport java.io.File

5 import scala.collection.mutable.HashMapimport scala.collection.mutable.ArrayBuffer

7

class Kladionicar(ime : String,9 novac : Int,

tiket : HashMap[String, Char],11 utakmice : HashMap[String, Tuple4[Float,Float,Float,Char]])

extends Thread {13

var zarada : Float = 015

override def run(){17 // Cekamo da se odigraju sve utakmice

// Funkcije wait(), notify() i notifyAll()19 // moraju biti zakljucane unutar bloka synchronized

utakmice.synchronized {21 utakmice.wait()

}23

63

Page 69: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

var pogodjeno = 025 var ukupnaKvota : Float = 0

// Racunamo ukupnu zaradu27 for(t <- tiket)

if(t._2 == utakmice(t._1)._4){29 println(ime + " je pogodio utakmicu " + t._1 + " - " + utakmice(t._1)._4)

pogodjeno += 131 if(utakmice(t._1)._4 == '1')

ukupnaKvota += utakmice(t._1)._133 else if(utakmice(t._1)._4 == 'x')

ukupnaKvota += utakmice(t._1)._235 else if(utakmice(t._1)._4 == '2')

ukupnaKvota += utakmice(t._1)._337 }

if(pogodjeno != 0)39 zarada = ukupnaKvota * novac/pogodjeno

}41

def getIme() : String = {43 return ime

}45

def getZarada() : Float = {47 return zarada

}49 }

51 object Kladionica {def main(args : Array[String]) {

53 val sc1 : Scanner = new Scanner(new File("utakmice.txt"))val sc2 : Scanner = new Scanner(new File("kladionicari.txt"))

55 // Klasa HashMap iz paketa scala.collection.mutable// predstavlja implementaciju mape koja se moze azurirati (eng. mutable)

57 //// Neke od korisnih funkcija su:

59 // -put(k,v) - dodaje vrednost u mapu sa zadatim kljucem// -size - vraca velicinu mape

61 // -contains(k) - vraca true ukoliko postoji element sa zadatim kljucem, falseinace

// ...63 //

// Takodje mozemo iterirati kroz elemente mape for petljom65 //

// Klasa Tuple4 je jedna u nizu klasa koje implementiraju torke (Tuple1, Tuple2,Tuple3 ,...)

67 // koje se mogu azurirati.// Elementima torke pristupamo na sledeci nacin - torka._1, torka._2, torka._3,

torka._469 //

val utakmice = new HashMap[String, Tuple4[Float,Float,Float,Char]]()71

// Rezultate utakmica postavljamo da budu karakter '-'73 // kako bismo naglasili da se utakmice jos nisu odigrale

while(sc1.hasNextLine()){75 utakmice.put(sc1.nextLine(),(sc1.nextFloat(), sc1.nextFloat(), sc1.nextFloat(),

'-'))sc1.nextLine()

77 }val kladionicari = new ArrayBuffer[Kladionicar]()

79

while(sc2.hasNextLine()){81 val ime = sc2.next()

val novac = sc2.nextInt()83 val tiket = new HashMap[String, Char]()

for(i <- 0 until 5){85 sc2.nextLine()

tiket.put(sc2.nextLine(), sc2.next()(0))87 }

kladionicari.append(new Kladionicar(ime, novac, tiket, utakmice))89 }

91 for(k <- kladionicari)k.start()

64

Page 70: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.2 Rešenja

93

println("Cekamo da se utakmice odigraju.")95 Thread.sleep(5000)

97 // Racunamo rezultate utakmicaval res = Array('1','x', '2')

99 for(u <- utakmice)utakmice(u._1) = (u._2._1,

101 u._2._2,u._2._3,

103 res(ThreadLocalRandom.current().nextInt(0, 3)))

105

// Ulazimo u kriticnu sekciju107 // i obavestavamo niti koje cekaju

utakmice.synchronized {109 utakmice.notifyAll()

}111

for(k <- kladionicari)113 k.join()

115 var isplata : Float = 0for(k <- kladionicari){

117 isplata += k.getZarada()println(k.getIme() + " ceka na isplatu " + k.getZarada() + "dinara.")

119 }println("Ukupno kladionica treba da isplati " + isplata + " dinara.")

121 }}

Rešenje 4.10 Zbir vektora

import java.util.Scanner2

class Sabirac(poc : Int,4 kraj : Int ,

vektor1 : Array[Float],6 vektor2 : Array[Float])

extends Thread {8 // Svaka nit racuna zbir svog dela vektora [poc, kraj)

// i rezultat smesta u prvi vektor.10 override def run() {

for( i <- poc until kraj)12 vektor1(i) += vektor2(i)

}14 }

16 object ZbirVektora {def main(args : Array[String]){

18

val sc = new Scanner(System.in)20

println("Unesite dimenziju vektora: ")22 val n = sc.nextInt()

24 val vektor1 : Array[Float] = new Array(n)val vektor2 : Array[Float] = new Array(n)

26

println("Unesite elemente prvog vektora: ")28 for(i <- 0 until n)

vektor1(i) = sc.nextFloat()30

println("Unesite elemente drugog vektora: ")32 for(i <- 0 until n)

vektor2(i) = sc.nextFloat()34

println("Unesite broj niti: ")36 val brojNiti = sc.nextInt()

38 val niti = new Array[Sabirac](brojNiti)

65

Page 71: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

40 val korak = Math.ceil(n/brojNiti.toDouble).toInt

42 // Pravimo niti i zadajemo im indekse - granicefor(i <- 0 until brojNiti)

44 niti(i) = new Sabirac(i*korak, Math.min((i+1)*korak,n),vektor1,vektor2)

46 // Pokrecemo racunanjefor(i <- 0 until brojNiti)

48 niti(i).start()

50 // Cekamo da niti zavrse sa racunanjemfor(i <- 0 until brojNiti)

52 niti(i).join()

54 // Kada sve niti zavrse sa racunanjem ispisujemo rezultatprint("Zbir vektora je: \n[")

56 for(i <- 0 until n-1)print(vektor1(i) + ", ")

58 println(vektor1(n-1) + "]")}

60 }

Rešenje 4.11 Broj petocifrenih brojeva

import java.util.concurrent._2 import java.io._

import java.util.Scanner4 import scala.collection.mutable.ArrayBuffer

6 class BrojacPetocifrenih(dat : String) extends Thread {

8 var rezultat : Int = 0// Citamo brojeve iz datoteke i povecavamo lokalni brojac

10 // ukoliko je broj petocifrenoverride def run() {

12 val sc : Scanner = new Scanner(new File(dat))

14 while(sc.hasNextInt()){var broj = sc.nextInt()

16 if(broj >= 10000 && broj <= 99999)this.rezultat+=1

18 }}

20

def getRezultat() : Int = {22 return rezultat

}24

def getDatoteka() : String = {26 return dat

}28 }

30 object BrojPetocifrenih {def main(args : Array[String]){

32

val sc = new Scanner(System.in)34

val brojaci = ArrayBuffer[BrojacPetocifrenih]()36 var kraj = false

var odg = ""38 var dat = ""

40 while(!kraj) {println("Da li zelite da zadate ime datoteke koja ce biti obradjena (y/n)?")

42 odg = sc.next()if(odg.toLowerCase() == "n")

44 kraj = trueelse{

46 println("Unesite ime datoteke: ")dat = sc.next()

48 brojaci.append(new BrojacPetocifrenih(dat))

66

Page 72: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.2 Rešenja

}50 }

52 // Zapocinjemo izvrsavanjefor(brojac <- brojaci)

54 brojac.start()

56 // Pozivom metoda join cekamo sve brojace da zavrse sa izracunavanjemfor(brojac <- brojaci)

58 brojac.join()

60 // Citamo rezultate brojanja svake nitifor(brojac <- brojaci)

62 println(s"Datoteka ${brojac.getDatoteka()} sadrzi ${brojac.getRezultat()}petocifrenih brojeva.")

}64 }

Rešenje 4.12 Berba

1 import java.util.concurrent.atomic._import java.util.concurrent._

3 import java.util.Scannerimport java.io.File

5

class Berac(drvoredi : ConcurrentLinkedQueue[Tuple2[String,Int]],7 skladiste : AtomicIntegerArray) extends Thread {

9 override def run() {

11 while(true) {// Dohvatamo dvored za berbu iz reda

13 val drvored = drvoredi.poll()// Ukoliko nema vise drvoreda za berbu zavrsavamo

15 if(drvored == null)return

17 println("Berac bere drvo " + drvored._1 )Thread.sleep(ThreadLocalRandom.current().nextInt(1,10)*1000)

19 // Dodajemo kilograme voca koje smo obrali u skladistefor(i <- 0 until drvored._2){

21 val obrano = ThreadLocalRandom.current().nextInt(30, 50)if(drvored._1 == "tresnje")

23 skladiste.getAndAdd(0, obrano)else if(drvored._1 == "kruske")

25 skladiste.getAndAdd(1, obrano)else if(drvored._1 == "kajsije")

27 skladiste.getAndAdd(2, obrano)else if(drvored._1 == "sljive")

29 skladiste.getAndAdd(3, obrano)}

31 }}

33 }

35 object Berba {def main(args : Array[String]) {

37 val sc1 : Scanner = new Scanner(new File("drvoredi.txt"))val sc2 : Scanner = new Scanner(System.in)

39

// Pravimo skladiste voca koje imamo u vocnjaku41 // i postavljamo inicijalne kolicine voca.

// Klasa AtomicIntegerArray sadzi niz integer vrednosti43 // nad kojima se operacije izvrsavaju atomicno.

// Slicno kao kod klasa AtomicInteger, AtomicLong i dr.45 val skladiste = new AtomicIntegerArray(4)

skladiste.set(0,0)47 skladiste.set(1,0)

skladiste.set(2,0)49 skladiste.set(3,0)

// Pravimo red drvoreda za berbu51 // Svaki drvored je jedan par (voce, brojStabala).

val drvoredi = new ConcurrentLinkedQueue[Tuple2[String, Int]]()

67

Page 73: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

53 while(sc1.hasNextLine())drvoredi.add((sc1.next(), sc1.nextInt()))

55

println("Unesite broj beraca: ")57 val brojBeraca = sc2.nextInt()

59 val beraci = new Array[Berac](brojBeraca)for(i <- 0 until brojBeraca)

61 beraci(i) = new Berac(drvoredi, skladiste)

63 for(b <- beraci)b.start()

65

for(b <- beraci)67 b.join()

69 println("Tresanja je obrano: " + skladiste.get(0) + " kilograma.")println("Krusaka je obrano: " + skladiste.get(1) + " kilograma.")

71 println("Kajsija je obrano: " + skladiste.get(2) + " kilograma.")println("Sljiva je obrano: " + skladiste.get(3) + " kilograma.")

73 }}

Rešenje 4.13 Turistička agencija

import java.util.concurrent._2 import java.util.Scanner

import java.io.File4

class Ucesnik(ime : String,6 cena : Int,

dobitnici : Array[String])8 extends Thread {

10 override def run() {// Cekamo dok se ne zavrsi izvlacenje.

12 //// Metod wait() suspenduje nit, oslobadja kriticnu sekciju obmotanu synchronized

blokom14 // i dozvoljava drugim nitima koje su zakljucale isti objekat da udju u kriticnu

sekciju// sve dok neka druga nit ne pozove nad istim objektom metod notifyAll()

16 // cime se obavestavaju sve niti koje cekaju sa metodom wait()// da mogu nastaviti sa radom

18 //dobitnici.synchronized {

20 dobitnici.wait()}

22 for(d <- dobitnici)if(d == ime){

24 println("Cestitamo " + ime +"!!! Osvojili ste popust od 20% na cenu karte. Vasa karta sada kosta

" + cena*0.8 + "e.")26 return

}28 println("Nazalost " + ime +

" niste osvojili popust , vise srece drugi put. Vasa karta kosta " + cena+ "e.")

30

}32

def getIme() : String = {34 return ime

}36 }

38 object TuristickaAgencija {def main(args : Array[String]) {

40 val sc : Scanner = new Scanner(new File("ucesnici.txt"))

42 val dobitnici = new Array[String](5)val n = sc.nextInt()

68

Page 74: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4.2 Rešenja

44 sc.nextLine()val ucesnici = new Array[Ucesnik](n)

46 for(i <- 0 until n){ucesnici(i) = new Ucesnik(sc.nextLine(), sc.nextInt(), dobitnici)

48 sc.nextLine()}

50

for(u <- ucesnici)52 u.start()

54 println("Izvlacenje je u toku.")Thread.sleep(5000)

56 // Ulazimo u kriticnu sekciju, i racunamo dobitnike nagradnih popustadobitnici.synchronized {

58 val izvuceniIndeksi = ThreadLocalRandom.current().ints(0, n).distinct().limit(5).toArray()

for(j <- 0 until izvuceniIndeksi.length)60 dobitnici(j) = ucesnici(izvuceniIndeksi(j)).getIme()

62 // Kada su izracunati dobitnici, obavestavamo niti koje cekaju// i izlazimo iz kriticne sekcije

64 dobitnici.notifyAll()}

66

}68 }

69

Page 75: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

4 Konkurentno programiranje

70

Page 76: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5

Distribuirano programiranje

5.1 ScalaKoristicemo jezik Scalu (verzija 2.10) http://www.scala-lang.org/ i Apache Spark alat

http://spark.apache.org/Potrebno je imati instalirano:

(a) Jezik Scalu verziju 2.10 i/ili 2.11

(b) Eclipse Neon razvojno okruzenje https://www.eclipse.org/downloads/

(c) ScalaIDE dodatak za Eclipse razvojno okruzenje http://scala-ide.org/

Korisni linkovi:http://spark.apache.org/docs/latest/index.htmlhttps://www.youtube.com/watch?v=7k_9sdTOdX4

5.1.1 UvodApache Spark je radni okvir (eng. framework) za distribuirano programiranje. Pruža inter-

fejse za programiranje (eng. API) u jezicima Java, Scala, Python i R.Svaka Spark aplikacija se sastoji od glavnog (eng. driver) programa koji pokreće funkciju main

i izvršava paralelne operacije na povezanom klaster računaru. Pristupanje klaster računaru se vršipomoću objekta kontekst tipa SparkContext. Prilikom konstrukcije kontekst objekta, potrebnoje definisati koji klaster računar će se koristiti. Spark aplikacija može koristiti lokalni računar kaosimulaciju klaster računara (svaka procesorska jedinica će simulirati jedan čvor klaster računara)ili neki udaljeni klaster računar.

Spark koristi posebne kolekcije podataka koje se mogu obrađivati paralelno (eng. RDD -Resilient Distributed Datasets). Paralelne kolekcije se mogu napraviti od već postojećih kolekcija uprogramu ili se mogu učitati iz spoljašnjeg sveta. Nad paralelnim kolekcijama možemo izvršavatidva tipa operacija transformacije i akcije (slika 5.1). Transformacije transformišu kolekciju naklaster računaru i prave novu paralelnu kolekciju. Sve transformacije su lenje, što znači da rezultatizračunavaju u trenutku kada on postane potreban.

Akcije su operacije koje se izvršavaju na klaster računaru nad paralelnim kolekcijama i njihovrezultat (izračunata vrednost) se vraća na lokalni računar.

Spark može da sačuva paralelne kolekcije u memoriji čvorova klaster računara i na taj načinubrzati izvršavanje narednih operacija.

Spark pruža mogućnost koriščenja deljenih podataka u vidu emitovanih promenljivih (eng.broadcast variables) i akumulatora (eng. accumulators).

Neke od funkcija transformacija su:

• map(f) - vraća novu kolekciju koja se dobija tako što se primeni funkcija f nad svakimelementom postojeće kolekcije

• filter(f) - primenjuje funkciju f nad svim elementima kolekcije i vraća novu kolekciju kojasadrži one elemente za koje je funkcija f vratila true

71

Page 77: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5 Distribuirano programiranje

Slika 5.1: Operacije nad paralelnim podacima

• flatMap(f) - slična je funkciji map, razlika je to što primena funkcije f nad nekim elementomkolekcije može da vrati 0 ili više novih elemenata koji se smeštaju u rezultujuću kolekciju

• groupByKey() - poziva se nad kolekcijom parova (kljuc, vrednost) i vraća kolekciju parova(kljuc, Iterable<vrednost>) tako što grupiše sve vrednosti sa istim ključem i smešta ih udrugi element rezultujućeg para

• reduceByKey(f) - poziva se nad kolekcijom parova (kljuc, vrednost) i vraća kolekciju pa-rova (kljuc, nova_vrednost) , nova_vrednost se dobija agregiranjem svih vrednosti sa istimključem koristeću zadatu funkciju agregacije f

• aggregateByKey(pocetna_vrednost)(f1, f2) - poziva se nad kolekcijom parova (kljuc,vrednost) i vraća kolekciju parova (kljuc, nova_vrednost) , nova_vrednost se dobija agregira-njem pocetne vrednosti i svih vrednosti sa istim ključem koristeću zadatu funkciju agregacijef1 u svakom čvoru klaster računara, a funkcija f2 agregira vrednosti izračunate u čvorovimaklaster računara u jednu vrednost - nova_vrednost

• sortByKey() - poziva se nad kolekcijom parova (kljuc, vrednost) i vraća novu kolekcijusortiranu po ključu

• cartesian(druga_kolekcija) - spaja kolekciju sa drugom kolekcijom i vraća kolekciju svihparova (vrednost_iz_prve_kolekcije,vrednost_iz_druge_kolekcije)

• zip(druga_kolekcija) - spaja kolekciju sa drugom kolekcijom spajajući elemente na istimpozicijama i vraća kolekciju parova (vrednost_iz_prve_kolekcije, vrednost_iz_druge_ko-lekcije)

Neke od funkcija akcija su:

• reduce(f) - agregira elemente kolekcije koristeći funkciju f i vraća rezultat agregacije

• collect() - pretvara paralelnu kolekciju u niz (koji se nalazi na lokalnom računaru)

• count() - vraća broj elemenata kolekcije

• countByKey() - poziva se nad kolekcijom parova (kljuc, vrednost), za svaki ključ broji kolikoima elemenata sa tim ključem i vraća neparalelnu kolekciju (kljuc, broj_elemenata)

• first() - vraća prvi element kolekcije

• take(n) - vraća prvih n elemenata kolekcije

• takeSample(sa_vracanjem, n, seed) - vraća prvih n nasumično izabranih elemenata ko-lekcije (sa ili bez vraćanja), seed predstavlja početnu vrednost generatora slučajnih brojeva

• takeOrdered(n[, poredak]) - vraća prvih n elemenata sortirane kolekcije (koristeći priro-dan poredak kolekcije ili zadati poredak)

• saveAsTextFile(ime_direktorijuma) - upisuje kolekciju u datoteke koje se nalaze u zada-tom direktorijumu

72

Page 78: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5.1 Scala

• foreach(f) - poziva funkciju f nad svim elementima kolekcije (uglavnom se koristi kadafunkcija f ima neke sporedne efekte kao što je upisivanja podataka u datoteku ili slično)

Konfiguraciju Spark aplikacije možemo podešavati dinamički prilikom pokretanja aplikacijena klaster računaru. Potrebno je upakovati aplikaciju zajedno sa svim njenim bibliotekama u.jar datoteku koristeći neki od alata (Maven 1, SBT 2 i sl.) i instalirati Spark upravljač na klasterračunaru (Standalone 3, Mesos 4, Yarn 5 i sl.). Aplikaciju možemo pokrenuti pomoci spark-submitskripta koji se nalazi u bin direktorijumu instaliranog Spark alata i konfigurisati dinamički. Naprimer:

1 ./bin/spark-submit --class Main --master local --num-executors 20Aplikacija.jar

Parametri koji se najčešće koriste prilikom konfiguracije su:

• --master url - URL klaster racunara

• --class ime_klase - glavna klasa naše aplikacije

• --num-executors n - broj čvorova koji izvršavaju našu aplikaciju (eng. executors)

• --executor-cores n - broj zadataka koje jedan čvor može izvršavati istovremeno

• --executor-memory n - veličina hip memorije svakog čvora

5.1.2 Zadaci sa rešenjima

Zadatak 5.1 Parni kvadrati Napisati program koji učitava ceo broj n veći od 2 i ispisujesve kvadrate parnih brojeva počev od broja 2 do n.

[Rešenje 5.1]

Zadatak 5.2 Broj petocifrenih Napisati program koji ispisuje broj petocifrenih brojevakoji se nalaze u datoteci brojevi.txt (svaka linija sadrzi jedan broj).

[Rešenje 5.2]

Zadatak 5.3 Skalarni proizvod Napisati program koji racuna skalarni proizvod dvavektora (pretpostavimo da su vektori uvek zadati ispravno tj. iste su dužine) i ispisuje ih na izlaz.Vektori se nalaze u datotekama vektor1.txt i vektor2.txt u formatu:

1 a1, a2, a3, a4, ... an

[Rešenje 5.3]

Zadatak 5.4 Broj pojavljivanja reči Napisati program koji za svaku reč iz knjige (datoteka knjiga.txt) broji koliko se puta ona pojavljuje i rezultat upisuje u datoteku.

[Rešenje 5.4]

Zadatak 5.5 Uređaji transakcije U datoteci uredjaji.txt se nalaze podaci o kupljenimuređajima u formatu:

1 marka_uredjaja ostali_podaci

Napisati program koji izdvaja podatke o svim transakcijama jedne marke i upisuje ih u posebnudatoteku sa nazivom ime_marke.txt.

1http://maven.apache.org/2http://www.scala-sbt.org/3http://spark.apache.org/docs/latest/spark-standalone.html4http://spark.apache.org/docs/latest/running-on-mesos.html5http://spark.apache.org/docs/latest/running-on-yarn.html

73

Page 79: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5 Distribuirano programiranje

[Rešenje 5.5]

Zadatak 5.6 Log poruke Datoteka log.txt sadrži podatke koji su generisani pokreta-njem Java programa. Napisati program koji izdvaja poruke koje se odnose na pakete jezika Javagrupisane po tipu poruke i ispisuje ih na izlaz.Poruke mogu biti informacione, upozorenja ili greške.Format poruka je:

1 tip ostatak_poruke

Tip moze biti [warn], [info] ili [error].

[Rešenje 5.6]

Zadatak 5.7 Uspešna preuzimanja U datoteci mavenLog.txt se nalaze podaci o zapo-četim/uspešnim preuzimanjima paketa prilikom pokretanja Maven alata (upravljač zavisnostima)u formatu:

1 Downloading: ostatak_poruke

ili

1 Downloaded: ostatak_poruke

Napisati program koji računa procenat uspešnih preuzimanja paketa u odnosu na započeta preu-zimanja.

[Rešenje 5.7]

Zadatak 5.8 Pokloni Bliži se Božić i firma želi da pokloni svojim zaposlenim progra-merima tri paketića. Sin direktora firme je budući programer i želi da napravi program koji ćesimulirati izvlačenje troje dobitnika paketića. Kako još uvek nije dobro savladao programiranje,pomozimo mu tako što ćemo napisati program koji nasumicno bira tri programera i ispisuje njihovaimena, prezimena i email.Podaci o zaposlenima se nalaze u datoteci zaposleni.txt u formatu:

1 ime prezime pol identifikator IP_adresa_racunara datum_zaposlenjasifra_pozicije plata

Šifra pozicije programera je IT_PROG.

[Rešenje 5.8]

Zadatak 5.9 Prosečna temperatura U datoteci temperaturaBoston.txt se nalaze podacio prosečnim temperaturama u Bostonu od 1995 do 2016 godine u Farenhajtima. Napisati programkoji ispisuje prosečne temperature u Bostonu za svaku godinu od 1995 do 2016 godine posebno uCelzijusima.

Format podataka je:

1 mesec dan godina temperatura

[Rešenje 5.9]

5.1.3 Zadaci za vežbu

Zadatak 5.10 Napisati program koji učitava ceo broj n i ispisuje faktorijele svih brojeva od1 do n.

Zadatak 5.11 Napisati program koji učitava ceo broj n i ispisuje sumu prvih n elemenataharmonijskog reda (podsetimo se, harmonijski red je red oblika 1 + 1/2 + 1/3 + 1/4 ... ).

74

Page 80: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5.2 Rešenja

Zadatak 5.12 Napisati program koji racuna zbir dva vektora (pretpostavimo da su vektoriuvek zadati ispravno tj. iste su dužine) i ispisuje ih na izlaz.

Vektori se nalaze u datotekama vektor1.txt i vektor2.txt u formatu:

1 a1, a2, a3, a4, ... an

Zadatak 5.13 Napisati program koji racuna broj pojavljivanja svake cifre 0-9 u datoteciknjiga.txt i ispisuje rezultat sortiran po ciframa.

Zadatak 5.14 Napisati program koji prebrojava sve poruke o greškama koje se odnose naSpark alat i rezultat ispisuje na izlaz. Poruke o greeskama se nalaze u datoteci log.txt u formatu:

1 tip ostatak_poruke

Tip poruke o grešci je [error].

Zadatak 5.15 Napisati program koji izdvaja dane sa najvišom temperaturom u Bostonu zasvaku godinu posebno, počev od 1995 do 2016 i rezultat upisuje u direktorijum MaxTemp. Podacio temperaturama se nalaze u datoteci temperaturaBoston.txt u formatu:

1 mesec dan godina temperatura

Zadatak 5.16 Napisati program koji izdvaja podatke o veličini preuzetih paketa koji se odnosena Apache server i rezultat upisuje u direktorijum ApacheDownloaded. Podaci o preuzimanjima senalaze u datoteci mavenLog.txt u formatu:

1 Downloaded: putanja podaci_o_velicini

Zadatak 5.17 Ekonomski analitičari žele da analiziraju tržište tehničke robe sa nekim raspo-nom cena. Napisati program koji učitava ime marke i bira nasumično pet poruka o transakcijamakoje se odnose na tu marku. Podaci o transakcijama se nalaze u datoteci uredjaji.txt u formatu:

1 marka_uredjaja ostali_podaci

Zadatak 5.18 Napisati program koji računa prosečnu platu programera u firmi. Podaci ozaposlenima se nalaze u datoteci zaposleni.txt u formatu:

1 ime prezime pol identifikator IP_adresa_racunara datum_zaposlenjasifra_pozicije plata

Šifra pozicije programera je IT_PROG.

5.2 Rešenja

Rešenje 5.1 Parni kvadrati

1 import org.apache.spark.SparkConfimport org.apache.spark.SparkContext

3 import org.apache.spark.rdd.RDD._

5 object ParniKvadrati {

7 def main(args: Array[String]) = {

9 println("Unesite broj n:")val n = Console.readInt()

11 /*** Podesavamo konfiguraciju Spark okruzenja

13 * tako sto dajemo ime aplikaciji* i dodeljujemo joj potencijalno 4 cvora

15 * (u nasem slucaju procesorska jezgra)

75

Page 81: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5 Distribuirano programiranje

* */17 val konf = new SparkConf()

.setAppName("ParniKvadrati")19 .setMaster("local[4]")

21 /*** Pravimo objekat Spark konteksta

23 * koji pokrece i upravlja Spark okruzenjem* */

25 val sk = new SparkContext(konf)

27

/**29 * Ukoliko zelimo da podesavamo parametre dinamicki

* (broj cvorova koji izvrsavaju nasu aplikaciju,31 * velicina hip memorije i sl.)

* potrebno je da inicijalizujemo spark kontekst na sledeci nacin33 *

* val sk = new SparkContext(new SparkConf());35 *

* cime naznacavamo da ce se parametri konfiguracije37 * podesiti dinamicki (koriscenjem spark-submit skripte).

* */39

val niz = (2 to n by 2).toArray41

/**43 * Pravimo niz tipa RDD[Integer] od niza tipa Array[Integer]

* */45 val nizRDD = sk.parallelize(niz)

47 /*** Pravimo niz kvadrata parnih brojeva (uzimamo prvih 10)

49 * i rezultat pretvaramo u niz tipa Array[Integer]* */

51 val nizKvadrata = nizRDD.map(x => x*x)/* .take(10) */

53 .collect()

55 /*** Zaustavljamo Spark okruzenje

57 * */sk.stop()

59

/**61 * Ispisujemo rezultujuci niz

* */63 println("Niz kvadrata parnih brojeva: ")

println(nizKvadrata.mkString(", "))65 }

}

Rešenje 5.2 Broj petocifrenih

import org.apache.spark.SparkConf2 import org.apache.spark.SparkContext

import org.apache.spark.rdd.RDD._4

6 object BrojPetocifrenih {

8 def main(args: Array[String]){

10 val konf = new SparkConf().setAppName("BrojPetocifrenih")

12 .setMaster("local[4]")

14 val sk = new SparkContext(konf)

16 /*** Otvaramo datoteku i njen sadrzaj cuvamo

18 * u nizu tipa RDD[String].

76

Page 82: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5.2 Rešenja

* Elementi niza su pojedinacne linije iz datoteke.20 * */

val datRDD = sk.textFile("brojevi.txt")22

/**24 * Filtriramo niz tako da nam ostanu samo petocifreni brojevi

* i prebrojavamo ih.26 * */

val brojPetocifrenihBrojeva = datRDD.filter(_.length() == 5)28 .count()

30 sk.stop()

32 println("Petocifrenih brojeva ima: ")println(brojPetocifrenihBrojeva)

34 }}

Rešenje 5.3 Skalarni proizvod

1 import org.apache.spark.SparkConfimport org.apache.spark.SparkContext

3 import org.apache.spark.rdd.RDD._

5 object SkalarniProizvod {

7 def main(args: Array[String]){

9 val konf = new SparkConf().setAppName("SkalarniProizvod")

11 .setMaster("local[4]")

13 val sk = new SparkContext(konf)

15 /*** Otvaramo datoteku i ucitavamo vektor.

17 * */val vek1RDD = sk.textFile("vektor1.txt")

19 /*** Razdvajamo elemente vektora iz niske koristeci separator ", "

21 * */.flatMap(_.split(", "))

23 /*** Kastujemo niske u tip Integer.

25 * */.map(_.toInt)

27

val vek2RDD = sk.textFile("vektor2.txt")29 .flatMap(_.split(", "))

.map(_.toInt)31

/**33 * Spajamo nizove vektora A i B funkcijom zip

* i pravimo jedan niz parova (tipa Tuple)35 * tako da svaki par sadrzi element vektora A i element vektora B

* (a1,b1), (a2,b2), ... (an, bn).37 * */

val skProizvod = vek1RDD.zip(vek2RDD)39 /**

* Mnozimo elemente para.41 * */

.map(par => par._1 * par._2)43 /**

* Pomnozene elemente parova sabiramo.45 * */

.reduce((a, b) => a+b)47 sk.stop()

49 println("Skalarni proizvod je: ")println(skProizvod)

51 }}

77

Page 83: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5 Distribuirano programiranje

Rešenje 5.4 Broj pojavljivanja reči

import org.apache.spark.SparkConf2 import org.apache.spark.SparkContext

import org.apache.spark.rdd.RDD._4

object BrojPojavljivanjaReci {6

def main(args: Array[String]){8

val konf = new SparkConf()10 .setAppName("BrojPojavljivanjaReci")

.setMaster("local[4]")12

val sk = new SparkContext(konf)14

val knjigaRDD = sk.textFile("knjiga.txt")16

/**18 * Ucitavamo linije i razlazemo ih separatorom " " tako da dobjemo niz reci

*/20 val reciBr = knjigaRDD.flatMap(_.split(" "))

/**22 * Od svake reci pravimo par (rec, 1).

*/24 .map(rec => (rec , 1))

/**26 * Sabiramo sve vrednosti drugog elementa para

* grupisane po prvom elementu para28 * koji nam predstavlja kljuc.

*/30 .reduceByKey((_+_))

/**32 * Sortiramo reci leksikografski.

*/34 .sortByKey()

/**36 * Cuvamo ih u datotekama koje se nalaze u direktorijumu

* BrojPojavljivanjaReci38 */

.saveAsTextFile("BrojPojavljivanjaReci")40

sk.stop()42 }

}

Rešenje 5.5 Uređaji transakcije

1 import org.apache.spark.SparkConfimport org.apache.spark.SparkContext

3 import org.apache.spark.rdd.RDD._import java.io._

5

object UredjajiTransakcije {7

def main(args: Array[String]){9

val konf = new SparkConf()11 .setAppName("UredjajiTransakcije")

.setMaster("local[4]")13

val sk = new SparkContext(konf)15

val transakcije = sk.textFile("uredjaji.txt")17 /**

* Razdvajamo podatke o uredjajima19 * i pravimo parove transakcija

* (marka, ostali_podaci)21 * */

.map(linija => {23 val niz = linija.split(" ")

(niz(0), niz.drop(1).mkString(" "))

78

Page 84: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5.2 Rešenja

25 })/**

27 * Grupisemo ih po marki tako da za svaku marku* cuvamo niz obavljenih transakcija

29 * (tj. niz koji sadrzi ostale podatke za svaku transakciju)* */

31 .groupByKey()/**

33 * Prolazimo kroz niz parova (marka, niz_transakcija)* i u datoteku ime_marke.txt

35 * upisujemo podatke o transakcijama.*

37 * Parametar t u foreach konstrukciji predstavlja jedan par* (marka, niz_transakcija).

39 * */.foreach(t => {

41 val dat = new PrintWriter(new File(t._1.toLowerCase() +".txt" ))

43 dat.write("---" + t._1 + "---\n")

45 t._2.foreach(por => {dat.append(por + "\n")

47 })

49 dat.close()})

51

sk.stop()53 }

}

Rešenje 5.6 Log poruke

1 import org.apache.spark.SparkConfimport org.apache.spark.SparkContext

3 import org.apache.spark.rdd.RDD._

5 object LogPoruke {

7 def main(args: Array[String]){

9 val konf = new SparkConf().setAppName("LogPoruke")

11 .setMaster("local[4]")

13 val sk = new SparkContext(konf)

15 val poruke = sk.textFile("log.txt")/**

17 * Filtriramo podatke tako da nam ostanu* samo linije koje predstavljaju

19 * upozorenja, informacije ili greske i odnose se na javu.* */

21 .filter(linija =>(linija.contains("[warn]")

23 || linija.contains("[info]")|| linija.contains("[error]"))

25 && (linija.contains("java")))/**

27 * Pravimo parove (tip_poruke, poruka).* */

29 .map(linija => {val niz = linija.split(" ")

31 (niz(0), niz.drop(1).mkString(" "))})

33 /*** Grupisemo poruke po njihovom tipu (kljuc).

35 * tako da dobijemo niz parova (tip_poruke, niz_poruka).* */

37 .groupByKey()/**

79

Page 85: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5 Distribuirano programiranje

39 * Za svaki tip racunamo broj poruka tog tipa* tako sto od parova (tip_poruke, niz_poruka)

41 * pravimo par (tip_poruke, broj_poruka)* */

43 .map( por => (por._1, por._2.size)).collect()

45

println("Informacije o log porukama koje se odnose na Javu: ")47

poruke.foreach( por => println(" " + por._1 + ": " + por._2 ))49

sk.stop()51 }

}

Rešenje 5.7 Uspešna preuzimanja

1 import org.apache.spark.SparkConfimport org.apache.spark.SparkContext

3 import org.apache.spark.rdd.RDD._

5 object UspesnaPreuzimanja {

7 def main(args: Array[String]){

9 val konf = new SparkConf().setAppName("UspesnaPreuzimanja")

11 .setMaster("local[4]")

13 val sk = new SparkContext(konf)

15 /*** Ucitavamo podatke i smestamo ih u kes memoriju radi brzeg pristupanja.

17 * */val preuzimanja = sk.textFile("mavenLog.txt")

19 .cache()/**

21 * Racunamo broj zapocetih preuzimanja.* */

23 val zapoceta = preuzimanja.filter(_.contains("Downloading:")).count()

25 /*** Racunamo broj zavrsenih preuzimanja.

27 * */val zavrsena = preuzimanja.filter(_.contains("Downloaded:"))

29 .count()

31 sk.stop()

33 println("%.2f".format(zavrsena*100.0/zapoceta) + " procenata zapocetihpreuzimanja je zavrseno.")

}35 }

Rešenje 5.8 Pokloni

1 import org.apache.spark.SparkConfimport org.apache.spark.SparkContext

3 import org.apache.spark.rdd.RDD._import scala.compat._

5

object RandomZaposleni {7

def main(args: Array[String]){9

val konf = new SparkConf()11 .setAppName("RandomZaposleni")

.setMaster("local[4]")13

val sk = new SparkContext(konf)

80

Page 86: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5.2 Rešenja

15

/**17 * Pronalazimo liniju koja sadrzi radnika programera,

* razdvajamo podatke o jednom radniku19 * i cuvamo njegovo ime, prezime i email nalog.

* Nakon toga nasumicno biramo 3 programera.21 *

* Funkcija takeSample kao argumente prihvata:23 * - indikator da li zelimo izbora sa vracanjem

* - broj uzoraka25 * - pocetnu vrednost (seed) za slucajni generator

* */27 val triProgramera = sk.textFile("zaposleni.txt")

/**29 * Pronalazimo liniju koja sadrzi radnika programera,

* */31 .filter(_.contains("IT_PROG"))

/**33 * Razdvajamo podatke o jednom radniku

* i cuvamo njegovo ime, prezime i email nalog.35 * */

.map(linija => {37 val niz = linija.split(" ")

(niz(0), niz(1), niz(3))39 })

/**41 * Nasumicno biramo 3 programera.

* Prvi parametar (false) oznacava43 * izbor bez vracanja a poslednji parametar

* predstavlja pocetnu vrednost (seed)45 * generatora slucajnih brojeva.

* */47 .takeSample(false, 3, Platform.currentTime)

49 println("Tri zaposlena radnika u IT sektoru su: ")triProgramera.foreach(prog => {

51 println("Ime i prezime: " + prog._1 + " " + prog._2 + "\n Email: " + prog._3.toLowerCase()+"@firma.com")

})53

sk.stop()55 }

}

Rešenje 5.9 Prosečna temperatura

1 import org.apache.spark.SparkConfimport org.apache.spark.SparkContext

3 import org.apache.spark.rdd.RDD._

5 object ProsecnaTemperatura {

7 def main(args: Array[String]){

9 val konf = new SparkConf().setAppName("ProsecnaTemperatura")

11 .setMaster("local[4]")

13 val sk = new SparkContext(konf)

15 val tempRDD = sk.textFile("temperatureBoston.txt")/**

17 * Pravimo torke (kljuc, vrednost) takve da je* kljuc = godina

19 * vrednost = (mesec, dan, temperatura)* */

21 .map(linija => {val niz = linija.split(" ")

23 (niz(3),(niz(1), niz(2), niz(4).toFloat))})

25 /*** Grupisemo torke po njihovom kljucu i za svaki kljuc racunamo

81

Page 87: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

5 Distribuirano programiranje

27 * sumu svih temperatura i broj temperatura koje smo sabrali.*

29 * Funkcija aggregateByKey(pocetnaVrednostAkumulatora)(f1, f2)* obradjuje niz parova (kljuc, vrednost)

31 * grupise ih po kljucu, akumulira vrednosti* (inicijalna vrednost akumulatora

33 * se prosledjuje kao parametar)* i kao rezultat vraca niz parova (k, akumuliranaVrednost).

35 ** Funkcija f1(akumulator, vrednost) se primenjuje

37 * nad svim vrednostima koje se nalaze u jednom cvoru* i rezultat se smesta u akumulator tog cvora

39 * Funkcija f2(akumulator1, akumulator2) se primenjuje* nad svim izracunatim akumulatorima pojedinacnih cvorova

41 * i rezultat se smesta u globalni akumumulator.*

43 * U nasem slucaju, akumulator ce da sadrzi dve vrednosti* (sumaTemp, brojTemp) sa nulom kao pocetnom vrednoscu.

45 * Funkcija f1(akumulator, vrednost)* sabira vrednost (temperaturu)

47 * sa sumaTemp iz akumulatora, a brojTemp povecava za 1.* Funkcija f2(akumulator1, akumulator2)

49 * sabira obe vrednosti ova dva akumulatora.*

51 * Kao rezultat primene ove funkcije dobicemo niz parova* (kljuc, (sumaTemp, brojTemp))

53 * gde nam je kljuc godina* u kojoj zelimo da izracunamo prosecnu temperaturu.

55 * */.aggregateByKey((0.0, 0))((ak, vr) => (ak._1 + vr._3 , ak._2 +

1 ),57 (a1 ,a2) => (a1._1 + a2._1, a1._2 + a2.

_2))/**

59 * Pravimo niz parova (kljuc, prosecnaTemperatura)* */

61 .map( st => (st._1, st._2._1/st._2._2)).sortByKey()

63 .collect().foreach( st => println("Godine "

65 + st._1+ " prosecna temperatura je iznosila "

67 + "%.2f".format(((st._2-32)/1.8))+ " celzijusa. "))

69

sk.stop()71 }

}

82

Page 88: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6

Logičko programiranje

Potrebno je imati instaliran B-Prolog na računaru.

Literatura:

(a) http://www.picat-lang.org/bprolog/

(b) http://www.picat-lang.org/bprolog/download/manual.pdf

6.1 Uvod6.1.1 Uvodni primeri

Zadatak 6.1 U bazu znanja uneti informacije o životinjama i njihovim odnosima po pitanjuveličine. Napisati pravilo koje omogućava da se proveri koja je od dve životinje veća, kao i dageneriše sve životinje za koje je neka životinja veća.

1 % ovo je jednolinijski komentar

3 /*ovo je viselinijski

5 komentar*/

7

/*9 Programi se cuvaju sa ekstenzijom .pro ili .pl (na sistemima gde ekstenzije imaju

globalno znacenje, kao sto je MS-Windows da ne bi bilo mesanja sa Perl programimatreba uvek koristiti .pro).

Interpreter se pokrece komandom bp. Naredbe:11 help -- pomoc

compile('ime_programa') -- prevodi program i pravi izvrsni fajl ukoliko nema gresaka13 load('ime_izvrsnog_fajla') -- uvozi izvrsni fajl

cl('ime_programa') -- compile + load15 halt ili control+D -- za izlazak iz interpretera

17 Termovi: konstante, promenljive ili kompozitni termovi.--- Konstante: atomi i brojevi.

19 ------ Atomi: stringovi od najvise 1000 karaktera koji pocinju malim slovom ('abc', 'a01', 'b_cd', 'l122k', ...).

------ Brojevi: celi i realni.21 --- Promenljive: imena pocinju velikim slovom ili podvlakom (_). Specijalna, anonimna

promenljiva: '_'.--- Kompozitni (slozeni) termovi ili strukture: oblika f(t1, ..., tn) gde je f neka

funkcija arnosti n ( 0<n<32768), a t1, ..., tn termovi.23

Program: sekvenca Hornovih klauza. Postoje tri tipa Hornovih klauza: cinjenice,pravila i upiti.

25 --- Cinjenice: atomicna formula oblika p(t1, ..., tn) gde je p predikat arnosti n, at1, ..., tn termi. One opisuju svojstva i relacije izmedju objekata. Primer:

zivotinja(slon).27 veci(zebra,vuk).

--- Pravila: imaju sledecu formu

83

Page 89: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6 Logičko programiranje

29 H :- B1, ..., Bn. (n>0)H, B1, ..., Bn su atomicne formule. H se zove GLAVA pravila, dok je sve sa desne

strane :- TELO pravila. Citamo ih kao implikaciju sa desna na levo: vazi H, akovaze B1, ..., Bn ("," u pravilu zamenjuje logicko "i").

31 --- Cinjenice i pravila cine BAZU ZNANJA.--- Upiti: konstrukcije kojima korisnik komunicira sa bazom znanja. Za ovo je

neophodan interpetator kome se postavlja upit. Primer:33 ?- veci(slon, zec).

true.35 ?- zivotinja(veverica).

false.37 */

39 /* cinjenice, svojstva */zivotinja(slon).

41 zivotinja(vuk).zivotinja(zec).

43 zivotinja(zebra).

45 /* cinjenice, odnosi */veci(slon,vuk).

47 veci(vuk,zec).veci(slon,zebra).

49 veci(zebra,vuk).veci(slon,zec).

51

/*53 upiti sa promenljivama:

-- daje jedno resenje, ako zelimo da prikaze jos resenja kucamo ; nakon prikazanog ?a za prekid control+C

55

?- veci(slon, X).57 X = vuk ? ^C

59 | ?- veci(slon, X).X = vuk ?;

61 X = zebra ?;X = zec

63 yes

65 | ?- veci(X, Y).X = slon

67 Y = vuk ?;X = vuk

69 Y = zec ?;X = slon

71 Y = zebra ?;X = zebra

73 Y = vuk ?;X = slon

75 Y = zecyes

77 */

79 /*pravilo : za neko X i Y vazi je_veci(X,Y) ako postoji Z tako da vazi veci(X,Z) i veci

(Z,Y)81 */

je_veci(X,Y):-veci(X,Z),veci(Z,Y).83 /*

| ?- je_veci(X,Y)85 X = slon

Y = zec ?;87 X = slon

Y = vuk ?;89 X = zebra

Y = zec ?;91 no

*/

Zadatak 6.2 Unifikacija. Jednakost./*

84

Page 90: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6.1 Uvod

2

Provera tipa:4

atom(X) - da li je term X atom6 atomic(X) - da li je term X atom ili broj

number(X) - da li je term X broj8 float(X) ili real(X) - da li je term X realan broj

integer(X) - da li je term X ceo broj10 var(X) - da li je term X slobodna promenljiva

nonvar(X) - da li term X nije promenljiva12

Primeri:14 | ?- atom('abc')

yes16 | ?- atomic(5)

yes18

Unifikacija:20

= unifikabilni22 \= nisu unifikabilni

== identicno jednaki termovi24 \== nisu identicno jednaki termovi

26 */

28 uni(X, Y):- X = Y.

30 /*| ?- uni(4,5)

32 no| ?- uni(4,X)

34 X = 4yes

36 */

38 jed(X, Y):- X == Y.

40 /*| ?- jed(4,X)

42 no| ?- jed(4,5)

44 no| ?- jed(4,4)

46 yes*/

Zadatak 6.3 Aritmetički operatori. Operatori is i cut./*

2 is aritmeticko izracunavanje=:= aritmeticki jednaki

4 =\= aritmeticki nisu jednaki<, =<, >, >=

6 +, -, *, /, // (celobrojno deljenje), div, mod, ** (stepenovanje)*/

8

/*10 Ako je X promenljiva, tada se njoj dodeljuje vrednost koju ima term Y (mora biti

poznata vrednost), a ukoliko X nije promenljiva, X is Y se svodi na X =:= Y*/

12 op1(X, Y):- X is Y./*

14 Termovima X i Y moraju biti poznate vrednosti, inace ce prijaviti gresku.*/

16 op2(X, Y):- X =:= Y.

18 /*| ?- op1(3,4)

20 no| ?- op1(4,4)

22 yes| ?- op1(X,4)

85

Page 91: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6 Logičko programiranje

24 X = 4yes

26 | ?- op1(4,X)*** error

28 | ?- op2(4,4)yes

30 | ?- op2(4,2)no

32 | ?- op2(4,X)*** error

34 | ?- op2(X,4)*** error

36 */

38 /*apsolutna vrednost, prvi argument je broj za koji trazimo apsolutnu vrednost, a drugi

promenljiva gde se smesta rezultat40

losa implementacija, za pozitivne brojeve oba pravila prolaze42

| ?- abs1(1,X)44 X = 1 ?;

X = -146 yes

| ?- abs1(-1,X)48 X = 1

yes50

*/52 abs1(X, X):- X >= 0.

abs1(X, Y):- Y is -X.54

/*56 dobre implementacije abs2 i abs3

58 | ?- abs2(1,X)X = 1 ?

60 yes| ?- abs2(-1,X)

62 X = 1yes

64 */abs2(X, X):- X >= 0.

66 abs2(X, Y):- X < 0, Y is -X.

68 /*koriscenje operatora "cut" koji se oznacava sa "!" uklanjamo alternativne klauze,

tako da se u slucaju pozitivnih nece primeniti drugi predikat cim uspe prvi70

| ?- abs3(1,X)72 X = 1

yes74 | ?- abs3(-1,X)

X = 176 yes

78 */abs3(X, X):- X >= 0, !.

80 abs3(X, Y):- Y is -X.

Zadatak 6.4 Rekurzivni predikat, primer porodičnog stabla.% porodicno stablo

2

% svojstva4 musko(mihajlo).

musko(stevan).6 musko(petar).

musko(mladen).8 musko(rajko).

zensko(milena).10 zensko(milica).

zensko(jelena).

86

Page 92: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6.1 Uvod

12 zensko(senka).zensko(mina).

14 zensko(maja).

16 % odnosiroditelj(mihajlo,milica).

18 roditelj(mihajlo,senka).roditelj(milena,rajko).

20 roditelj(maja,petar).roditelj(maja,mina).

22 roditelj(stevan,mladen).roditelj(stevan,jelena).

24 roditelj(milica,mladen).roditelj(milica,jelena).

26

% pravila28 majka(X,Y):- roditelj(X,Y), zensko(X).

otac(X,Y):- roditelj(X,Y), musko(X).30 brat(X,Y):- musko(X), majka(Z,X), majka(Z,Y), X\==Y.

sestra(X,Y):- zensko(X), majka(Z,X), majka(Z,Y), X\==Y.32 ujak(X,Y):- brat(X,Z), majka(Z,Y).

tetka(X,Y):- sestra(X,Z), majka(Z,Y).34

% rekurzivno pravilo36 % roditelj je predak

predak(X,Y):- roditelj(X,Y).38 % roditelj pretka je takodje predak

predak(X,Y):- roditelj(X,Z), predak(Z,Y).

Zadatak 6.5 Anonimna promenljiva, primer prestupne godine.

1 % godina je prestupna ako je deljiva sa 4 i nije deljiva sa 100 ili je deljiva sa 400prestupna(X):- X mod 4 =:= 0, X mod 100 =\= 0.

3 prestupna(X):- X mod 400 =:= 0.

5 /*anonimna promenljiva _ se koristi da oznaci da nam vrednost koja se prosledi za

godinu nije bitna, moze biti bilo sta, ali tu vrednost ne koristimo7

| ?- brdana(januar, _, X)9 X = 31

yes11 | ?- brdana(januar, 2017, X)

X = 3113 yes

*/15 brdana(januar, _, 31).

brdana(februar, X, 28):- not(prestupna(X)).17 brdana(februar, X, 29):- prestupna(X).

brdana(mart,_,31).19 brdana(april,_,30).

brdana(maj,_,31).21 brdana(jun,_,30).

brdana(jul,_,31).23 brdana(avgust,_,31).

brdana(septembar,_,30).25 brdana(oktobar,_,31).

brdana(novembar,_,30).27 brdana(decembar,_,31).

6.1.2 Zadaci za samostalni rad sa rešenjima

Zadatak 6.6 Napisati sledeće predikate:

a) maksimum(A, B, M) - određuje maksimum za dva broja A i B

b) suma(N, S) - za dati prirodan broj N računa sumu prvih N brojeva

c) sumaParnih(N, S) - za dati paran prirodan broj N računa sumu parnih brojeva od 2 do N

87

Page 93: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6 Logičko programiranje

d) proizvod(N, P) - za dati prirodan broj N računa proizvod prvih N prirodnih brojeva

e) proizvodNeparnih(N, P) - za dati neparan prirodan broj N računa proizvod neparnih bro-jeva od 1 do N

f) cifre(N) - ispisuje cifre prirodnog broja N rečima

[Rešenje 6.6]

6.1.3 Zadaci za vežbu

Zadatak 6.7 Napisati sledeće predikate:

a) sumaCifara(N, SC) - određuje sumu cifara prirodnog broja N

b) brojCifara(N, BC) - određuje broj cifara prirodnog broja N

c) maxCifra(N, MC) - određuje maksimalnu cifru prirodnog broja N

d) sumaKvadrata(N, SK) - računa sumu kvadrata prvih N prirodnih brojeva

e) fakt(N, F) - računa faktorijel prirodnog broja N

g) sumaDel(X, D) - računa sumu pravih delilaca broja X

Zadatak 6.8 Ako su date činjenice oblika:

• ucenik( SifraUcenika, ImeUcenika, Odeljenje)

• ocene( SifraUcenika, SifraPredmeta, Ocena)

• predmet( SifraPredmeta, NazivPredmeta, BrojCasova)

Napisati sledeće predikate:

a) bar2PeticeSifra(S) - određuje šifru S učenika koji ima bar dve petice iz različitih predmeta

b) bar2PeticeIme(X) - određuje ime X učenika koji ima bar dve petice iz različitih predmeta

c) odeljenjePetice(X,Y) - određuje odeljenje X u kome postoje bar dve petice iz predmeta sašifrom Y

Zadatak 6.9 Ako su date činjenice oblika:

• film(NazivFilma, ZanrFilma, ImeReditelja, SifraGlumca)

• glumac(SifraGlumca, ImeGlumca, GodRodj, MestoRodj)

Napisati sledeće predikate:

a) filmskiUmetnik(X) - X je filmski umetnik ako je reditelj nekog filma i igra u nekom filmu

b) glumacBarDva(X) - određuje ime glumca X koji igra u bar dva različita filma

c) opstiGlumac(X) - određuje ime glumca X koji igra u bar dva filma različitog žanra

d) zanrovskiGlumac(X,Y) - određuje ime glumca X koji igra u filmu žanra Y

88

Page 94: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6.2 Liste

6.2 Liste

6.2.1 Uvodni primeri

Zadatak 6.10 Osnovni pojmovi i predikati za rad sa listama.

1 /*Lista - niz uredjenih elemenata, tj. termova.

3 Lista moze biti:[] - prazna

5 .(G,R) - struktura, gde je G ma koji term i naziva se glava liste, a R lista inaziva se rep liste

7 Primeri:[] - prazna

9 .(a, []) - jednoclana lista, gde je a bilo koji term.(a, .(b, [])) - dvoclana lista, gde su a i b termi ...

11

Zapis pomocu zagrada (prvi element predstavlja glavu, a ostali cine listu koja je rep):

13 [a,b,c] <=> .(a, .(b, [c]))

15 Zapis liste u kom su jasno razdvojeni glava i rep (pogodan za unifikaciju): [G|R].

17 Primeri unifikacije listi:[X, Y, Z] [jabuka, kruska, banana] -----> X = jabuka, Y = kruska, Z = banana

19 [racunar] [X|Y] -----> X = racunar, Y = [][maja, ana, jovana] [X, Y|Z] -----> X = maja, Y = ana, Z = [jovana]

21

*/23

% predikat proverava da li element pripada listi (ako joj pripada jednak je glavi ilinekom elementu iz repa liste)

25 sadrzi(X, [X|_]):- !.sadrzi(X, [G|R]):- G \== X, sadrzi(X, R).

27

% drugi nacin, predikat kao disjunkcija:29 % sadrzi(X, [G|R]):- G == X; sadrzi(X, R).

31 % predikat koji racuna duzinu liste (prazna je duzine nula, nepraznu dekomponujemo naglavu i rep, pa je duzina liste = 1 + duzina repa)

duzina([], 0).33 duzina([G|R], L):- duzina(R,L1), L is L1+1.

35 % predikat racuna sumu elemenata liste brojevasuma([], 0).

37 suma([G|R], S):- number(G), suma(R, S1), S is S1+G.

39 % predikat racuna aritmeticku sredinu elemenata liste brojevaarsr([],0).

41 % ako ne koristimo sablon za nepraznu listu [G|R], moramo proveriti da li je K nulajer se sada L moze unifikovati sa []

arsr(L, A):- duzina(L, K), K =\= 0, suma(L, S), A is S/K.43

% predikat ucitava listu duzine N ciji elementi mogu biti proizvoljni termovi45 % za negativno N ne ucitava listu

ucitaj(N,_) :- N < 0, !.47 % za nulu vraca praznu listu

ucitaj(0, []).49 % read(X) ucitanu vrednost sa ulaza dodeljuje promenljivoj X

% ako je N > 1, lista ima glavu i rep, ucitamo glavu, pa pozovemo predikat zaucitavanje repa

51 ucitaj(N, [G|R]):- N > 1, write('unesi element '), read(G), nl, M is N-1, ucitaj(M,R).

53 /*prilikom unosa vrednosti obavezna je tacka kao oznaka kraja ulaza za read

55 | ?- ucitaj(3,L)unesi element | 5.

57

unesi element | 4.59

89

Page 95: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6 Logičko programiranje

unesi element | 3.61

L = [5,4,3]63 yes

65 | ?- ucitaj(3,L)unesi element | [1,2,3].

67

unesi element | 4.69

unesi element | [].71

L = [[1,2,3],4,[]]73 yes

75 */

6.2.2 Zadaci za samostalni rad sa rešenjima

Zadatak 6.11 Napisati sledeće predikate:

a) dodajPocetak(X, L, NL) - dodaje X na početak liste L

b) dodajKraj(X, L, NL) - dodaje X na kraj liste L

c) obrisiPrvi(L, NL) - briše prvi element, tj. glavu liste

d) obrisiPoslednji(L, NL) - briše poslednji element liste

e) obrisi(X, L, NL) - briše sva pojavljivanja elementa X u listi L

f) obrisiPrvo(X, L, NL) - briše samo prvo pojavljivanje elementa X u listi L

g) obrisiK(L, K, NL) - briše K-ti element liste L

[Rešenje 6.11]

Zadatak 6.12 Napisati predikat podeli(L, L1, L2) koji deli listu L na dve liste, listupozitivnih elemenata L1 i listu negativnih elemenata L2.

[Rešenje 6.12]

Zadatak 6.13 Napisati predikat pretvori(L, X) koji za datu listu cifara L formira brojodređen tim ciframa.

[Rešenje 6.13]

Zadatak 6.14 Napisati predikat maxEl(L, X) koji određuje maksimalni element liste L.

[Rešenje 6.14]

Zadatak 6.15 Napisati predikat spoji(L1, L2, L) koji spaja dve rastuće sortirane liste L1i L2 u treću tako da i ona bude sortirana rastuće.

[Rešenje 6.15]

6.2.3 Zadaci za vežbu

Zadatak 6.16 Napisati predikat parNepar(L, L1, L2) koji deli listu L na dve liste, listuparnih elemenata L1 i listu neparnih elemenata L2.

Zadatak 6.17 Napisati predikat podeli(L, N, L1, L2) koji deli listu L na dve liste L1 i L2,pri čemu je zadata dužina prve liste L1.

90

Page 96: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6.3 Razni zadaci

Zadatak 6.18 Napisati predikat ogledalo(L1, L2) koji proverava da li je lista L1 jednakaobrnutoj listi liste L2.

Zadatak 6.19 Napisati predikat interval(X, Y, L) koji kreira listu L koja sadži sve celebrojeve iz intervala zadatog sa prva dva argumenta.

Zadatak 6.20 Napisati predikat skalar(L1, L2, S) koji određuje skalarni proizvod dvavektora, tj. listi brojeva L1 i L2.

6.3 Razni zadaci6.3.1 Zadaci sa rešenjima

Zadatak 6.21 Ako su date činjenice oblika:

• stan(Porodica, KvadraturaStana)

• clan(Porodica, BrojClanova)

Napisati predikat poClanu(Porodica, Prosek) koji određuje prosečan broj kvadrata stana počlanu porodice koja živi u njemu.

[Rešenje 6.21]

Zadatak 6.22 Ako je data baza znanja:

• automobil(SifraAutomobila, NazivAutomobila)

• vlasnik(ImeVlasnika, SifraAutomobila)

• brziSifra(SX, SY) - automobil šifre SX je brži od automobila šifre SY

Napisati predikate:

a) brziNaziv(X, Y) - automobil naziva X je brži od automobila naziva Y

b) imaAutomobil(X) - X je vlasnik nekog automobila

c) imaBrzi(X, Y) - X je vlasnik bržeg automobila od onog čiji je vlasnik Y.

[Rešenje 6.22]

Zadatak 6.23 Napisati program koji rešava sledeću zagonetku. Postoji pet kuća, svakarazličite boje u kojoj žive ljudi različitih nacionalnosti koji piju različita pića, jedu različita jela iimaju različite kućne ljubimce. Važi sledeće:

• Englez živi u crvenoj kući

• Španac ima psa

• kafa se pije u zelenoj kući

• Ukrajinac pije čaj

• zelena kuća je odmah desno uz belu

• onaj koji jede špagete ima puža

• pica se jede u žutoj kući

• mleko se pije u srednjoj kući

• Norvežanin živi u prvoj kuci s leva

• onaj koji jede piletinu živi pored onoga koji ima lisicu

91

Page 97: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6 Logičko programiranje

• pica se jede u kući koja je pored kuće u kojoj je konj

• onaj koji jede brokoli pije sok od narandze

• Japanac jede suši

• Norvežanin živi pored plave kuće

Čija je zebra, a ko pije vodu?

[Rešenje 6.23]

Zadatak 6.24 Napisati program koji rešava sledeću zagonetku. Svakog vikenda, Milan čuvapetoro komšijske dece. Deca se zovu Kata, Lazar, Marko, Nevenka i Ognjen, a prezivaju Filipović,Grbović, Hadžić, Ivanović i Janković. Svi imaju različit broj godina od dve do šest. Važi sledeće:

• jedno dete se zove Lazar Janković

• Kata je godinu dana starija od deteta koje se preziva Ivanović koje je godinu dana starije odNevenke

• dete koje se preziva Filipović je tri godine starije od Marka

• Ognjen je duplo stariji od deteta koje se preziva Hadžić

Kako se ko zove i koliko ima godina?

[Rešenje 6.24]

6.3.2 Zadaci za vežbu

Zadatak 6.25 Napisati predikat uzastopni(X, Y, Z, L) koji proverava da li su prva triargumenta uzastopni elementi u listi L.

Zadatak 6.26 Napisati predikat kompresuj(L, KL) koji u datoj listi L eliminiše uzastopneduplikate.

Zadatak 6.27 Napisati predikat prefiksi(L, P) koji određuje sve liste koje su prefiksi dateliste L.

Zadatak 6.28 Napisati predikat sufiksi(L, S) koji određuje sve liste koje su sufiksi dateliste L.

Zadatak 6.29 Napisati predikat opadajuce(N, L) koji za dat prirodan broj N formira listubrojeva od N do 1.

Zadatak 6.30 Napisati predikat form(N, L) kojim se formira lista od prirodnih brojevadeljivih sa 5 i manjih od datog prirodnog broja N.

Zadatak 6.31 Napisati program koji rešava sledeću zagonetku. Četiri žene se zovu Petra,Milica, Lenka i Jovana, a prezivaju Perić, Mikić, Lazić i Jović. One imaju četiri kćerke koje setakodje zovu Petra, Milica, Lenka i Jovana. Važi sledeće:

• nijedna majka nema prezime koje počinje istim slovom kao ime

• nijedna kćerka nema prezime koje počinje istim slovom kao ime

• nijedna kćerka se ne zove kao majka

• majka koja se preziva Perić se zove isto kao Miličina kćerka

• Lenkina kćerka se zove Petra

Odrediti imena majki i kćerki.

Zadatak 6.32 Napisati program koji rešava sledeću zagonetku. Četiri para je došlo na ma-skenbal:

92

Page 98: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6.4 Rešenja

• Markova zena se maskirala kao macka

• dva para su stigla pre Marka i njegove žene, a jedan muskarac je bio maskiran u medveda

• prvi koji je stigao nije bio Vasa, ali je stigao pre onoga koji je bio maskiran u princa

• žena maskirana u vešticu (nije Bojana) je udata za Peru, koji se maskirao kao Paja patak

• Marija je došla posle Laze, a oboje su stigli pre Bojane

• žena maskirana u Ciganku je stigla pre Ane, pri čemu nijedna od njih nije udata za muškarcamaskiranog u Betmena

• žena maskirana u Snežanu je stigla posle Ivane

Odrediti kako je bio obučen koji par.

Zadatak 6.33 Izračunavanje vrednosti aritmetičkog izraza korišćenjem listi možete pogledatiovde:https://rosettacode.org/wiki/Arithmetic_evaluation#Prolog

Zadatak 6.34 Implementacije raznih problema u Prologu možete pogledati ovde:https://rosettacode.org/wiki/Category:Prolog

6.4 Rešenja

Rešenje 6.6

1 % maksimum dva broja% I nacin:

3 maksimum(A,B,M):- A>=B, M is A.maksimum(A,B,M):- A<B, M is B.

5 % II nacin bez trece promenjive:% maksimum(A,B,A):- A>=B.

7 % maksimum(A,B,B):- A<B.

9 % suma prvih N prirodnih brojevasuma(1,1).

11 suma(N,S):- N>1, N1 is N-1, suma(N1,S1), S is S1+N.

13 % suma parnih prirodnih brojeva od 2 do N% moze se dodati provera N mod 2 =:= 0 u pravilu, ali i bez toga sam prepoznaje za

neparne da je netacan upit jer rekurzijom dodje do sumaParnih(1,S) sto je netacnacinjenica u bazi

15 sumaParnih(2,2).sumaParnih(N,S):- N>2, N1 is N-2, sumaParnih(N1,S1), S is S1+N.

17

% proizvod prvih N prirodnih brojeva19 proizvod(1,1).

proizvod(N,P):- N>1, N1 is N-1, proizvod(N1,P1), P is P1*N.21

% proizvod neparnih prirodnih brojeva od 1 do N23 proizvodNeparnih(1,1).

proizvodNeparnih(N,P):- N>1, N1 is N-2, proizvodNeparnih(N1,P1), P is P1*N.25

% ispis cifara unetog prirodnog broja N27 cifra(0, nula).

cifra(1, jedan).29 cifra(2, dva).

cifra(3, tri).31 cifra(4, cetiri).

cifra(5, pet).33 cifra(6, sest).

cifra(7, sedam).35 cifra(8, osam).

cifra(9, devet).37

% ukoliko nije prirodan broj, cut operatorom sprecavamo poziv poslednjeg predikata

93

Page 99: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6 Logičko programiranje

39 cifre(N):- N < 1, !.

41 % ukoliko je jednocifren svodi se na poziv predikata cifra% write(t) gde je t neki term, ispisuje term

43 % nl (newline) - ispisuje se novi red% obratiti paznju na upotrebu cut operatora ! - sprecavamo poziv poslednjeg predikata

za jednocifrene45 cifre(N):- N > 1, N < 10, cifra(N, C), write(C), nl, !.

47 % ukoliko nije jednocifren, racunamo tekucu cifru koju ispisujemo i ostatak broja zakoji se ponovo poziva predikat

cifre(N):- N1 is (N // 10), cifre(N1), N2 is (N mod 10), cifra(N2, C), write(C), nl.

Rešenje 6.11

1 % dodaje element na pocetak listedodajPocetak(X, L, [X|L]).

3

% dodaje element na kraj liste5 dodajKraj(X, [], [X]).

dodajKraj(X, [G|R], [G|LR]):- dodajKraj(X, R, LR).7

% brise prvi element liste9 % za praznu listu ce uvek vratiti no jer ne moze unifikovati sa sablonom [G|R], a

mozemo napraviti i sami za taj slucaj da je predikat netacan% fail je uvek netacan pa ce nam ovako definisan predikat za slucaj prazne liste

vratiti no11 obrisiPrvi([], _):- fail.

obrisiPrvi([_|R], R).13

% brise poslednji element liste15 obrisiPoslednji([],_):- fail.

% bitan cut operator jer se jednoclana moze upariti sa sablonom [G|R]17 obrisiPoslednji([_],[]):- !.

obrisiPoslednji([G|R], [G|R1]):- obrisiPoslednji(R, R1).19

% brise element X iz liste ako postoji (svako pojavljivanje elementa X)21 obrisi(_, [], []).

obrisi(X, [X|R], R1):- obrisi(X, R, R1), !.23 obrisi(X, [G|R], [G|R1]):- G \== X, obrisi(X, R, R1).

25 % brise element X iz liste ako postoji (samo prvo pojavljivanje elementa X)obrisiPrvo(X, [], []).

27 obrisiPrvo(X, [X|R], R):- !.obrisiPrvo(X, [G|R], [G|R1]):- G \== X, obrisiPrvo(X, R, R1).

29

% brise K-ti element liste, brojimo od 1, ako je K vece od duzine liste, treciargument je jednak prvom

31 obrisiK([], K, []):- K > 0.obrisiK([G|R], 1, R):- !.

33 obrisiK([G|R], K, [G|R1]):- K>1, K1 is K-1, obrisiK(R, K1, R1).

35 % druga varijanta predikata: brise K-ti element liste, broji od 1, ali ukoliko zadatalista nema K-ti element, predikat vraca no kao odgovor i nema unifikacije za

treci argument% obrisiK([], K, []):- fail.

37 % obrisiK([G|R], 1, R):- !.% obrisiK([G|R], K, [G|R1]):- K>1, K1 is K-1, obrisiK(R, K1, R1).

Rešenje 6.12

1 % podeli1 - deli listu na dve liste - listu pozitivnih i listu negativnih elemenata% L1 - lista pozitivnih, L2 - lista negativnih

3 podeli([], [], []).podeli([G|R], [G|R1], L2):- G >= 0, podeli(R, R1, L2), !.

5 podeli([G|R], L1, [G|R2]):- G < 0, podeli(R, L1, R2).

Rešenje 6.13

94

Page 100: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6.4 Rešenja

% potreban nam je dodatni predikat za izdvajanje poslednjeg elementa liste2 izdvojPoslednji([G], G, []):- !.

izdvojPoslednji([G|R], X, [G|R1]):- izdvojPoslednji(R, X, R1).4

% formira broj od date liste cifara6 pretvori([], 0):- !.

pretvori(L, X):- izdvojPoslednji(L, Poslednji, Ostatak),8 pretvori(Ostatak, Y),

X is Poslednji + 10 * Y.10

/*12 | ?- pretvori([7,0,7], X)

X = 70714 yes

| ?- pretvori([0,2,3], X)16 X = 23

yes18 | ?- pretvori([], X)

X = 020 yes

22 */

Rešenje 6.14

% maksimalni element liste2 maxEl([X], M):- M is X, !.

% pozivamo za rep (idemo u dubinu), pa poredimo maksimalni element repa i glavu liste4 maxEl([G|R], X):- maxEl(R, Y), G < Y, X is Y, !.

maxEl([G|R], X):- maxEl(R, Y), G >= Y, X is G.

Rešenje 6.15

% poredjenjem glava listi zakljucujemo u kom redosledu dodajemo elemente u spojenulistu

2 spoji([], L, L):- !.spoji(L, [], L):- !.

4 spoji([G1|R1], [G2|R2], [G1|R]):- G1<G2, spoji(R1, [G2|R2], R), !.spoji([G1|R1], [G2|R2], [G2|R]):- G1>=G2, spoji([G1|R1], R2, R).

Rešenje 6.21

1 % cinjenicestan(petrovic, 76).

3 stan(ciric, 93).stan(aleksic, 55).

5 stan(lisic, 123).stan(peric, 67).

7

clan(ciric, 3).9 clan(peric, 5).

clan(aleksic, 2).11 clan(lisic, 3).

clan(petrovic, 4).13

% koristimo operator za realno deljenje / (// je za celobrojno, ne mesati ova dvaoperatora) da bi se dobio tacan rezultat

15 poClanu(Porodica, Prosek):- stan(Porodica, X), clan(Porodica, Y), Prosek is X/Y.

Rešenje 6.22

% baza znanja2 automobil(a1, audi).

automobil(h1, honda).4 automobil(m1, mercedes).

automobil(m2, mercedes).

95

Page 101: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6 Logičko programiranje

6 automobil(c1, citroen).automobil(c2, citroen).

8

vlasnik(milan, h1).10 vlasnik(maja, m1).

vlasnik(nemanja, m2).12 vlasnik(aleksandar , a1).

vlasnik(andjela, c1).14 vlasnik(petar, c2).

16 brziSifra(a1, c1).brziSifra(m1, c1).

18 brziSifra(m2, h1).brziSifra(a1, c2).

20

brziNaziv(X, Y):- automobil(SX, X), automobil(SY, Y), brziSifra(SX, SY).22

imaAutomobil(X):- vlasnik(X, _).24

imaBrzi(X, Y):- vlasnik(X, S1), vlasnik(Y, S2), brziSifra(S1, S2).

Rešenje 6.23

/*2 strukturama oblika k(boja, nacionalnost, jelo, pice, kucniLjubimac) opisujemo date

cinjenice, a u listi L su kuce poredjane jedna pored druge, tako da po redosleduu listi imamo informaciju da li je kuca desno od neke druge kuce i da li su kucejedna pored druge

*/4

/*6 pomocni predikat koji proverava da li je X clan liste, njemu prosledjujemo strukturu

k sa poznatim vrednostima iz teksta i opisujemo kakva kuca treba da bude u listi*/

8 clan(X, [X|_]).clan(X, [_|R]):- clan(X,R).

10

% predikat smesta u listu L kuce koje zadovoljavaju uslove iz teksta, tj. predikat Lunifikuje sa resenjem zagonetke

12 % u listu ubacujemo cinjenice koje su vezane za raspored kuca i to samo one kojejednoznacno odredjuju poziciju kuce u listi

kuce(L):- L = [ k(_,norvezanin ,_,_,_),14 k(plava,_,_,_,_),

k(_,_,_,mleko,_),16 k(_,_,_,_,_),

k(_,_,_,_,_) ],18 % dodajemo kakve sve kuce treba da budu u listi

clan(k(crvena, englez,_,_,_),L),20 clan(k(_, spanac,_,_,pas),L),

clan(k(zelena,_,_,kafa,_),L),22 clan(k(_, ukrajinac,_,caj,_),L),

% kada informacija daje relaciju za neke dve kuce iz liste koristimo predikatedesno i pored

24 desno(k(zelena,_,_,kafa,_),k(bela,_,_,_,_),L),clan(k(_,_,spagete,_,puz),L),

26 clan(k(zuta,_,pica,_,_),L),pored(k(_,_,piletina,_,_),k(_,_,_,_,lisica),L),

28 pored(k(_,_,pica,_,_),k(_,_,_,_,konj),L),clan(k(_,_,brokoli,narandza,_),L),

30 clan(k(_,japanac,susi,_,_),L),% medju datim informacijama se ne pominje zebra niti voda, ali posto je krajnjepitanje vezano za ove pojmove, moramo dodati da takvi clanovi treba da postoje uresenju zagonetke

32 clan(k(_,_,_,_,zebra),L),clan(k(_,_,_,voda,_),L).

34

% proverava da li su kuce X i Y jedna pored druge u listi L36 pored(X,Y,[X,Y|_]).

pored(X,Y,[Y,X|_]).38 pored(X,Y,[_|R]):- pored(X,Y,R).

40 % proverava da li je kuca X desno od kuce Y u listi L

96

Page 102: Programskijezici · 58 # Naredba  iskace iz bloka, isto kao i u C-u # Naredba  je ista kao naredba  u C-u 60 # Funkcije

6.4 Rešenja

desno(X,Y,[Y,X|_]).42 desno(X,Y,[_|R]):- desno(X,Y,R).

44 % predikat zagonetka daje odgovor na pitanje cija je zebra, a ko pije vodu, tako stoprvo trazi resenje zagonetke pa iz njega izdvaja samo potrebne clanove

zagonetka(X,Y):- kuce(L), clan(k(_,X,_,_,zebra),L), clan(k(_,Y,_,voda,_),L) .46

/*48 resenje:

50 | ?- kuce(L)L = [k(zuta,norvezanin,pica,voda,lisica),k(plava,ukrajinac,piletina,caj,konj),k(

crvena,englez,spagete,mleko,puz),k(bela,spanac,brokoli,narandza,pas),k(zelena,japanac,susi,kafa,zebra)]

52

odgovor na pitanje:54

| ?- zagonetka(X,Y)56 X = japanac

Y = norvezanin58

*/

Rešenje 6.24

/*2 resenje je lista L sa 5 struktura oblika: d(ime, prezime, godine)

*/4

% predikat kojim se proverava da li je X clan liste6 clan(X, [X|_]).

clan(X, [_|R]):- clan(X,R).8 % predikat smesta u listu L decu koja zadovoljavaju uslove iz teksta

% redosled dece u resenju nije bitan10 % direktno u listi mozemo naznaciti ili broj godina, ili data imena ili data

prezimena, ovde su izabrane godine, a ostale informacije dodate preko predikataclan

deca(L):- L = [d(_,_,2), d(_,_,3), d(_,_,4), d(_,_,5), d(_,_,6)],12 clan(d(lazar,jankovic,_),L),

clan(d(kata,_,G1),L),14 clan(d(_,ivanovic,G2),L),

clan(d(nevenka,_,G3),L),16 clan(d(_,filipovic,G4),L),

clan(d(marko,_,G5),L),18 clan(d(ognjen,_,G6),L),

clan(d(_,hadzic,G7),L),20 clan(d(_,grbovic,_),L),

% medju informacijama imamo odnos izmedju broja godina odredjene dece, ali neznamo tacno koliko godina imaju ta deca, zbog toga koristimo promenljive kojimaopisujemo date relacije, obratiti paznju da je potrebno koristiti aritmetickoporedjenje =:=, a ne poredjenje na identicnost (==), jer ne zelimo da se poredetermovi oblika Gi i Gj+N vec njihove brojevne vrednosti prilikom izgradjivanjaresenja

22 G1=:=G2+1, G2=:=G3+1, G4=:=G5+3, G6=:=2*G7.

24 /*resenje:

26

| ?- deca(L)28 L = [d(marko,hadzic,2),d(nevenka,grbovic,3),d(ognjen,ivanovic ,4),d(kata,filipovic ,5),

d(lazar,jankovic ,6)] ?yes

30

*/

97