Upload
markostevanovic
View
77
Download
3
Embed Size (px)
DESCRIPTION
Pascal (Glava09 ) Nizovi
Citation preview
Glava 9
Nizovi
Nizovi u programskom jeziku Pascal predstavljaju nacin da se efektivno radisa velikim brojem promenljivih istog tipa. Na primer, problemi koji zahtevaju dase istovremeno obra-duje 10000 brojeva bi se veoma teško mogli realizovati takošto bi se deklarisalo 10000 razlicitih promenljivih i onda radilo sa njima. U ovojglavi upoznajemo se sa nizovima kao strukturom podataka programskog jezikaPascal. Od važnih algoritama pominjemo Eratostenovo sito, a efektivan rad sanizovima demonstriramo na dva važna primera: pokazujemo kako se polinomi iveliki brojevi mogu implementirati pomocu nizova.
9.1 Deklaracija niza
Evo primera promenljive nizovnog tipa:
var
niz : array [1 .. 10000] of integer;
(array = niz, engl.). Tada imeniz oznacava složenu promenljivu koja se sastoji od10000 kucica (“malih” promenljivih), a svaka od tih kucica može da primi jedanceo broj:
[10000][4] [9999]
· · ·
[3][2][1]
niz:
Promenljiva nizovnog tipa lici na ulicu: niz je ime ulice, a [1], [2], itd. su kucnibrojevi. Pojedinacni elementi niza (tj. pojedinacne kucice) se ponašaju kao obicne
199
200 GLAVA 9. NIZOVI
promeniljive tipainteger, a zovu se ovako:niz[1], niz[2], . . . ,niz[10000].Dakle, ime pojedinacne promenljive se formira tako što se na ime ulice doda kucnibroj kucice. Na primer, ako želimo da u trecu kucicu smestimo broj 5, to radimokomandom
niz[3] := 5;
i efekt je sledeci:
[10000][4] [9999]
· · ·
[3][2][1]
5niz:
a nakon naredbe
niz[9999] := 2 * niz[3] 12;
imamo da jeniz[9999] = 2, tj.
[10000][4] [9999]
· · · -2
[3][2][1]
5niz:
Tip koji se navodi iza kljucne reci of može bitibilo koji tip programskog jezikaPascal!Primeri:
type
Dani = (pon, uto, sre, cet, pet, sub, ned);
var
b : array [1 .. 341] of Boolean;
c : array [1 .. 500] of char;
d : array [1 .. 437] of Dani;
r : array [1 .. 17] of real;
l : array [1 .. 1826] of longint;
9.1. DEKLARACIJA NIZA 201
Primer. Napisati program koji od korisnika ucitavan brojeva (16 n 6 10000) ištampa njihovu aritmeticku sredinu, kao i najmanji i najveci broj.
Rešenje.
program PrimerSaNizovima;
const
MaxEl = 10000;
var
n : integer;
a : array [1 .. MaxEl] of real;
sum, mi, ma : real;
i : integer;
begin
repeat
write(’Unesite broj izmedju 1 i ’, MaxEl, ’ > ’);
readln(n)
until (1 <= n) and (n <= MaxEl);
writeln(’Sada unesite brojeve:’);
for i := 1 to n do readln(a[i]);
sum := a[1]; mi := a[1]; ma := a[1];
for i := 2 to n do
begin
sum := sum + a[i];
if a[i] > ma then ma := a[i];
if a[i] < mi then mi := a[i]
end;
writeln(’Prosek = ’, sum/n : 10 : 2);
writeln(’Minimum = ’, mi : 10 : 2);
writeln(’Maksimum = ’, ma : 10 : 2)
end.
Primer. Nizovi secesto koriste kada je potrebno racunati sa brojevima koji imajumnogo cifara ili mnogo decimala. Navodimo primer programa koji racuna decimalebroja π koristeci Spigot algoritam1. Nije lako objasniti zašto ovaj algoritam radibez dubljeg poznavanja tajni matematike, tako da ga necemo detaljno komentarisati.Primetite samo da decimale brojaπ smeštamo u niza.
1S. Rabinowitz and S. Wagon, A spigot algorithm for the digits ofπ, Amer. Math. Monthly 102(1995) 195–203.
202 GLAVA 9. NIZOVI
program PiSpigot;
const
maxn = 1000;
maxlen = 3333; {10 * maxn div 3}
var
i, j, k, q, x, n, len, nines, predigit : longint;
a : array[1..maxlen] of longint;
begin
repeat
write(’Broj decimala (bar 2, najvise ’, maxn 1, ’) >’);
readln(n)
until (n >= 2) and (n <= maxn 1);
n := n + 1; len := 10 * n div 3;
for j := 1 to len do a[j] := 2;
nines := 0; predigit := 0;
for j := 1 to n do begin
q := 0;
for i := len downto 1 do begin
x := 10*a[i] + q*i;
a[i] := x mod (2*i1);
q := x div (2*i1);
end;
a[1] := q mod 10; q := q div 10;
if q = 9 then nines := nines + 1
else if q = 10 then begin
write(predigit+1);
for k := 1 to nines do write(0);
predigit := 0; nines := 0
end
else begin
if j = 2 then write(predigit, ’.’)
else if j >= 3 then write(predigit);
predigit := q;
if nines <> 0 then begin
for k := 1 to nines do write(9);
nines := 0
end
end
end;
writeln(predigit)
end.
9.1. DEKLARACIJA NIZA 203
Zadaci.9.1. Napisati program koji od korisnika ucitavan celih brojeva (16 n 6 1000)
i utvr -duje koliko ima parnih brojeva sa neparnim indeksom.
9.2. Napisati program koji od korisnika ucitava n realnih brojeva (16 n 6
1000) i utvr-duje koliko njih je strogo iznad proseka svih ucitanih brojeva.
9.3. Napisati program koji odre-duje indeks i vrednost prvogclana u nizu kojije najbliži proseku elemenata niza. Niz iman elemenata, gde je 16 n 6
1000.
9.4. 2-sredina niza realnih brojeva(a1,a2, . . . ,an) je data saα p+βq
p+q, gde jeα
najmanji element niza,p broj pojavljivanja najmanjeg elementa u nizu,βnajveci element niza, aq broj pojavljivanja najveceg elementa u nizu. Naprimer, za niz brojeva
2,1,5,3,1,3,1,5
je α = 1, p= 3,β = 5 i q= 2, pa je 2-sredina tog niza data sa 2,6. NapisatiPascal program koji od korisnika ucitavan realnih brojeva, 16 n 6 1000,i racuna 2-sredinu tog niza brojeva.
9.5. Kvadratna sredina niza brojeva(a1,a2, . . . ,an) se definiše ovako:
Kn =
√
a21 +a2
2 + . . .+a2n
n.
Napisati Pascal program koji od korisnika ucitava nekoliko brojeva i odre--duje i štampa njihovu kvadratnu sredinu. Brojevi se unose u jednom redurazdvojeni razmacima, a njihov broj nije unapred poznat.
9.6. Harmonijska sredina niza brojeva(a1,a2, . . . ,an) se definiše ovako:
Hn =n
1a1
+ 1a2
+ . . .+ 1an
.
Napisati Pascal program koji od korisnika ucitava nekoliko brojeva i utvr--duje koliko njih je strogo manje od harmonijske sredine svih brojeva.Brojevi se unose u jednom redu razdvojeni razmacima, a njihov broj nijeunapred poznat.
9.7. Napisati program koji od korisnika ucitavan celih brojeva (16 n 6 1000)i utvr -duje koliko ima brojeva iza poslednjeg negativnog broja u nizu. Akosu svi brojevi u nizu nenegativni, program ispisujen.
204 GLAVA 9. NIZOVI
9.8. Napisati Pascal program koji proverava da li dati niz slova predstavljapalindromnakon izbacivanja razmaka, znakova interpunkcije i zanemarivanjavelikih i malih slova. Palindrom je rec koja se istocita i sleva i zdesna. Naprimer, za sledece recenice program treba da prijavi da su palindromi:
Sir ima miris.
Sava zidar radi za vas!
Ana voli Milovana!
Maja sa Nedom ode na sajam.
9.9. Napisati Pascal program koji od korisnika ucitava pozitivne cele brojeveni b i utvr -duje da li je zapis brojan u osnovib palindrom.
9.10. Napisati Pascal program koji od korisnika ucitava prirodan brojn i potomispisuje prvihn prostih brojeva od najveceg ka najmanjem. Na primer, zan = 10 program ispisuje
29 23 19 17 13 11 7 5 3 2
9.11. Napisati Pascal program koji od korisnika ucitava ceo brojn> 2 i utvr -dujeda li je on proizvod uzastopnih prostih brojeva. Na primer, sledeci brojevijesu proizvod uzastopnih prostih brojeva: 6= 2 · 3, 2341= 11· 13· 17,23= 23, a sledeci nisu: 12= 22 ·3, 21= 3·7, 286= 2·11·13.
9.12. Napisati program koji formira i štampa nizb[1], b[2], . . . ,b[m] koji sedobija od nizaa[1], a[2], . . . ,a[n] izbacivanjem najveceg elementa togniza i svih njemu jednakih elemenata.
9.13. Napisati program koji formira i štampa nizb[1], b[2], . . . ,b[m] koji sedobija od nizaa[1], a[2], . . . ,a[n] izbacivanjemnajveceg i najmanjegelementa tog nizai svih njima jednakih elemenata.
9.14. Neka je dat niz brojevaa1, a2, . . . ,an. Niz brojeva definisan sa
sk = a1 + . . .+ak
zove seniz parcijalnih sumapolaznog niza. Napisati program koji odkorisnika ucitava ceo brojn (1 6 n 6 2000), potomn brojevaa1, a2, . . . ,an, i racuna i ispisuje niz parcijalnih suma ovog niza.
9.15. U redu u samoposluzi se nalazin kupaca. Kasirka potrošitk vremenskihjedinica da bi opslužila kupcak, k ∈ {1, . . . ,n}. Kupack na raspolaganjuima fk vremenskih jedinica za kupovinu. Ako završi kupovinu za više odfk jedinica, smatracemo da je zakasnio. Napisati Pascal program koji odkorisnika ucitava ceo brojn (16 n6 100), potomn parova brojeva(t1, f1),. . . , (tn, fn) i za svakog kupca racuna da lice zakasniti ili ne.
9.1. DEKLARACIJA NIZA 205
9.16. Konvolucija nizova A= (a1, . . . ,an) i B= (b1, . . . ,bn) je broj koji se racunaovako:
A?B = a1bn +a2bn−1 +a3bn−2 + . . .+anb1.
Napisati Pascal program koji od korisnika ucitava ceo brojn, potom nizoveA = (a1, . . . ,an) i B = (b1, . . . ,bn), i racuna njihovu konvoluciju.
9.17. Linearna regresijaje jedan metod obra-divanja eksperimentalnih rezultataza koje pretpostavljamo da se ponašaju po linearnom modeluy = ax+ b.Pretpostavimo da smo nizom merenja neke velicine u tackamax1, x2, . . . ,xn dobili izmerene vrednostiy1, y2, . . . ,yn. Nas interesuje da li se izmerenevrednosti grupišu oko neke prave (u kom slucaju fenomen možemo opisatilinearnim modelom) ili ne. Na primer, na slici ispod, podaci levo segrupišu oko neke prave, dok za podatke desno to nije slucaj:
Broj koji pokazuje da li se dati podaci ponašaju po linearnom modelu iline zove sekoeficijent korelacijei racuna se po formuli:
r =
n∑
i=1xiyi
√n∑
i=1x2
i ·√
n∑
i=1y2
i
To je realan broj iz intervala[−1,1]. Ukoliko je r blizu 1 ili −1, radi se ofenomenu koji se može dobro opisati linearnim modelom (i tada zar ≈ 1imamo dace odgovarajuca prava biti rastuca, dok zar ≈−1 prava opada),a u ostalim slucajevima se linearni model ne preporucuje.
Nezavisno od vrednosti brojar, za svaki niz eksperimentalnih podataka(x1,y1), . . . ,(xn,yn) možemo odrediti jednacinu prave koja najbolje aprok-simira dati niz brojeva. Ona ima obliky = ax+b gde je
a =
n·n∑
i=1xiyi −
n∑
i=1xi ·
n∑
i=1yi
n·n∑
i=1x2
i −(
n∑
i=1xi
)2 i b =
n∑
i=1x2
i ·n∑
i=1yi −
n∑
i=1xi ·
n∑
i=1xiyi
n·n∑
i=1x2
i −(
n∑
i=1xi
)2
206 GLAVA 9. NIZOVI
Napisati Pascal program koji od korisnika ucitava ceo brojn (1 6 n 6
1000), potomn parova realnih brojeva(x1,y1), . . . ,(xn,yn) i potom racunai štampa veliciner, a i b.
9.18. Na raspolaganju imamon1 novcanica u vrednosti oda1 dinara,n2 novca-nica u vrednosti oda2 dinara, . . . ,nk novcanica u vrednosti odak dinara.Napisati Pascal program koji od korisnika ucitavak, 1 6 k 6 100, potomcele brojevea1, . . . , ak, n1, . . . , nk i na kraju pozitivan ceo brojm kojipredstavlja kolicinu novca, a onda “isplacuje” korisniku iznos odmdinarakoristeci najmanji moguci broj novcanica. Ukoliko to nije moguce, isplatikorisniku najbolje što može, i obavesti ga o iznosu koji preostaje.
9.19. Dato jen tacaka u ravni svojim koordinatama, 16 n 6 1000. NapisatiPascal program koji odre-duje površinu najveceg trougla sa temenima uovim tackama i štampa površinu, kao i redne brojeve temena kojicine tajtrougao. Ako suA(x1,y1), B(x2,y2), C(x3,y3) temena trougla onda je
P(4ABC) =12|(x2y3−x3y2)− (x1y3−x3y1)+(x1y2−x2y1)|.
9.20. Za niz(a1, . . . ,an) kažemo da je periodican ako postoji brojp (period niza)takav da jeai+p = ai za svei ∈{1, . . . ,n−p}. Napisati Pascal program kojiod korisnika ucitava niz realnih brojeva i proverava da li je on periodican.Ako je niz periodican program ispisuje dužinu perioda, a ako nije ispisujeporukuNIJE.
9.21. Napisati Pascal program koji ucitava niz realnih brojeva i potom nalazinajduži strogo rastuci segment u tom nizu, i ispisuje dužinu segmenta iredni broj elementa od koga segment pocinje. Na primer, za niz brojeva
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 0 1 2
3 4 5 6 7 0 1
program ispisuje8 22 zato što je0 1 2 3 4 5 6 7 najduži strogo rastucisegment u tom nizu, njegova dužina je 8 i pocinje na 22. mestu. (Napomena:segmentcine uzastopni elementi nekog niza.)
9.2. INDEKSI NIZA 207
9.2 Indeksi niza
Jedna od lepih osobina nizova u Pascalu je to što prvi indeks niza ne mora biti1, vec može biti bilo koji broj. Na primer, sledece deklaracije su ispravne:
var
a : array [0 .. 49] of real;
b : array [2 .. 2] of integer;
c : array [13 .. 10] of char;
d : array [2 .. 1000] of Boolean;
Niz b izgleda ovako:
[2][1][0][-2] [-1]
b:
a nizc ovako:
[-10][-13] [-12]
c:
[-11]
Druga lepa stvar je to da indeks uopšte ne mora biti celobrojnog tipa!Indeks nizamože biti bilo koji nabrojivi ili podintervalni tip!Dakle, kao indeks niza može dase pojaviinteger, Boolean, char, ili neki nabrojivi tip koga je definisao korisnikkao što jeDani, ali ne sme biti realan broj! Primeri:
type
Dani = (pon, uto, sre, cet, pet, sub, ned);
var
c1 : array [char] of integer;
c2 : array [’a’ .. ’z’] of integer;
c3 : array [’A’ .. ’Z’] of char;
d : array [Dani] of real;
208 GLAVA 9. NIZOVI
Promenljivec1, c2 i d izgledaju ovako:
[chr(254)] [chr(255)]
· · ·[chr(1)][chr(0)]
c1:
[chr(2)]
[’z’][’y’]
· · ·[’a’] [’b’]
c2:
[’c’]
[ned][pet][cet] [sub][pon] [uto]
d:
[sre]
Me -dutim,sledece nije dozvoljeno:
const
Pi = 3.1415;
DvaPi = 6.283;
var
ISNOGOOD : array [Pi .. DvaPi] of integer;
(* NE SME OVAKO! *)
Primer 1. Ucenici Gimnazije “Jovan Jovanovic-Zmaj” anketirani su kako bi seutvrdilo koliko su zadovoljni ukupnim stanjem u školi. Svaki ucenik je dobioanketni listic sa skalom
532 41−1 0−2−3−5 −4
na kojoj je trebalo da zaokruži jedan od navedenih brojeva. Napisati Pascal programkoji od korisnika ucitava ceo brojn (broj anketiranih ucenika), potomn brojeva izskupa{−5, . . . ,−1,0,1, . . . ,5} i ispisuje koliko se puta koji broj pojavio kao ocena.
program Anketa;
var
BrUcenika, i, k : integer;
frekv : array [5 .. 5] of integer;
begin
for i := 5 to 5 do frekv[i] := 0;
write(’Unesite broj anketiranih ucenika > ’);
readln(BrUcenika);
9.2. INDEKSI NIZA 209
writeln(’Unesite rezultate ankete:’);
for i := 1 to BrUcenika do
begin
repeat
write(’Ucenik ’, i, ’ > ’);
readln(k)
until (5 <= k) and (k <= 5);
frekv[k] := frekv[k] + 1
end;
writeln(’Frekvencije:’);
for i := 5 to 5 do
writeln(i:3, frekv[i]:5)
end.
Primer 2. Napisati program koji od korisnika ucitava jedan rad teksta, a ondautvr -duje koliko se puta koji karakter pojavio u tom redu.
program KarakteriURedu;
var
a : array [char] of integer;
c : char;
begin
for c := chr(0) to chr(255) do a[c] := 0;
writeln(’Unesite jedan red teksta:’);
while not eoln do
begin
read(c);
a[c] := a[c] + 1
end;
readln;
writeln(’Frekvencije:’);
for c := chr(0) to chr(255) do
if a[c] > 0 then
writeln(ord(c):3, a[c]:5)
end.
Primer 3. Za svaki od dana u nedelji ucitati od korisnika broj radnih sati u tomdanu, a potom odrediti kojim danomkorisnik najviše radi.
210 GLAVA 9. NIZOVI
program NajvrednijiDan;
type
Dani = (pon, uto, sre, cet, pet, sub, ned);
var
d, dmax : Dani;
BrSati : array [Dani] of integer;
nmax : integer;
begin
writeln(’Unesite broj radnih sati po danima:’);
write(’Pon > ’); readln(BrSati[pon]);
write(’Uto > ’); readln(BrSati[uto]);
write(’Sre > ’); readln(BrSati[sre]);
write(’Cet > ’); readln(BrSati[cet]);
write(’Pet > ’); readln(BrSati[pet]);
write(’Sub > ’); readln(BrSati[sub]);
write(’Ned > ’); readln(BrSati[ned]);
nmax := BrSati[pon];
dmax := pon;
for d := uto to ned do
if BrSati[d] > nmax then
begin
nmax := BrSati[d];
dmax := d
end;
write(’Najzaposleniji dan je ’);
case d of
pon : writeln(’ponedeljak’);
uto : writeln(’utorak’);
sre : writeln(’sreda’);
cet : writeln(’cetvrtak’);
pet : writeln(’petak’);
sub : writeln(’subota’);
ned : writeln(’nedelja’)
end
end.
Zadaci.9.22. U Tabeli 9.1 oznaciti deklaracije koje su korektne.
9.23. Napisati Pascal program koji od korisnika ucitava brojeve iz skupa{−10,. . . , −1, 0, 1, . . . , 10} i broji koliko se puta svaki od njih pojavio. Krajunosa oznacen je brojem 99 koji se, naravno, ne racuna.
9.2. INDEKSI NIZA 211
� var a : array [1 .. 100] of real;
� var a : array [3 .. 3] of real;
� var b : array [1 .. 3] of real;
� var c : array [2.1 .. 3.3] of real;
� type Dani = (po,ut,sr,ce,pe,su);
var d : array [Dani] of Dani;
� type Dani = (po,ut,sr,ce,pe,su);
var d : array [po .. pe] of char;
� var e : array [char] of Boolean;
� var f : array [integer] of char;
� var g : array [real] of integer;
� const N = 13;
var d : array [N .. 20] of char;
� var g : array [Boolean] of integer;
� var g : array [false .. true] of char;
� var g : array [’a’ .. ’z’] of char;
� type MalaSl = ’a’ .. ’z’;
var d : array [1 .. 10] of MalaSl;
� type Dani = (po,ut,sr,ce,pe,su);
Niz = array [Dani] of char;
var n : Niz;
Tabela 9.1: Tabela iz Zadatka 9.22
212 GLAVA 9. NIZOVI
9.24. Napisati Pascal program koji od korisnika ucitava prirodan brojn i utvr -dujekoliko se puta koja cifra javlja u njegovom zapisu, tj. koliko ima nula,koliko jedinica, koliko dvojki, itd, koliko devetki.
9.25. Napisati Pascal program koji od korisnika ucitava pozitivan ceo brojn,potom ucitavan pozitivnih celih brojeva i racuna koliko se puta pojavljujesvaka od cifara 0, . . . , 9 u decimalnim zapisima tih brojeva. Na primer, zabrojeve 12, 354, 121, 10000, 1, 990 dobijamo:
Cifra 0 > 5 puta
Cifra 1 > 5 puta
Cifra 2 > 2 puta
Cifra 3 > 1 puta
Cifra 4 > 1 puta
Cifra 5 > 1 puta
Cifra 9 > 2 puta
9.26. Napisati Pascal program koji od korisnika ucitava pozitivan ceo brojn,potom ucitavan pozitivnih celih brojeva i racuna koliko se puta pojavljujesvaka od cifara 0, . . . , 9,a, . . . , f u heksadecimalnim zapisima tih brojeva.
9.27. Catalanovi brojevisu brojevi definisani na sledeci nacin:
C0=1
Cn=n−1
∑i=0
CiCn−1−i .
Napisati Pascal program koji od korisnika ucitava ceo brojn (16 n6 100)i racunan-ti Catalanov broj.
‡9.28. Amebe se razmnožavaju prostom deobom, što znaci da se jedna amebaprosto podeli na dve:
U jednoj populaciji ameba se nalazin ameba i znamo da su sve nastale odjedne jedine amebe. Napisati Pascal program koji od korisnika ucitavan i odre-duje na koliko razlicitih nacina se može realizovati niz deoba
9.2. INDEKSI NIZA 213
kojim od jedne amebe nastanen ameba. Na primer zan = 4 postoji petrazlicitih nacina da deobama od jedne amebe nastanecetiri amebe, kakoje to pokazano na Sl. 9.1.
9.29. Napisati program koji od korisnika ucitava pozitivan ceo brojn, potomn redova teksta, i utvr-duje koliko se puta u tim redovima javlja svako odslovaa, . . . , z, nezavisno od toga da li se u redu pojavljuje kao veliko ilikao malo slovo. Na primer, u reduAna voli Milovanase slovoa javlja 4puta, a slovom samo jednom.
9.30. Jedan od najstarijih metoda šifrovanja poruka sastoji se u tome da se svakoslovo poruke na sistematican nacin zameni nekim drugim slovom. Naprimer, ako nam je data tabela zamene:
Slovo a b c d e f g h i j k l m n o p q r s t u v w x y zZamena q w e r t y u i o p a s d f g h j k l z x c v b n m
onda porukaSir ima mirispostajeLok odq dokok. Niz od 26 slova
qwertyuiopasdfghjklzxcvbnm
u tabeli zamene zove sekljuc šifre.
(a) Tekstualna datotekakljuc.txt sadrži jedan red teksta koji predstavljakljuc šifre. Napisati Pascal program koji tekst u datoteciporuka.txt
šifruje tim kljucem i šifrovanu poruku upisuje u datotekusifra.txt.
(b) Tekstualna datotekakljuc.txt sadrži jedan red teksta koji predstavljakljuc šifre. Napisati Pascal program koji dešifruje tekst u datotecisifra.txt
i dobijenu poruku upisuje u datotekuoriginal.txt.
214
GLA
VA9.
NIZ
OV
I
Slika 9.1: Amebe iz Zadatka 9.28
9.3. ERATOSTENOVO SITO – PAKOVANI NIZOVI 215
9.3 Eratostenovo sito – Pakovani nizovi
Posebno interesantan nacin za pronalaženje svih prostih brojeva iz skupa{2,3, . . . ,n} pronašao je starogrcki naucnik Eratosten. Svi brojevi od 2 don seispišu u niz. Potom neke od njih zaokružujemo, a neke precrtavamo prema jednomveoma jednostavnom pravilu. Na kraju brojevi koji ostanu neprecrtani su prosti.Precrtavanje se radi ovako. Uocimo prvi broj koji nije zaokružen. Neka je tok.Zaokružimok, a svakik-ti broj pocev od njega precrtamo. Evo primera zan = 25.Na pocetku ispišemo brojeve od 2 do 25:
2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20 21
22 23 24 25
Prvi neprecrtani broj, a to je 2, zaokružimo i precrtamo svaki drugi broj pocev odnjega:
2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20 21
22 23 24 25
Prvi sledeci neprecrtani broj, a to je 3, zaokružimo i precrtamo svaki treci brojpocev od njega:
2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20 21
22 23 24 25
Sledeci broj je 5, itd. Kao i ranije, dovoljno je raditi samo sa brojevima koji sumanji ili jednaki sab√nc. Na kraju dobijamo:
216 GLAVA 9. NIZOVI
2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20 21
22 23 24 25
Brojevi koji nisu precrtani su prosti, nezavisno od toga da li su zaokruženi ili ne.Kako ceo postupak lici na prosejavanje, ovaj algoritam se zoveEratostenovo sito.
program EratostenovoSito;
const
MaxEl = 1000;
var
N, i, k : integer;
Precrtan : array [2 .. MaxEl] of Boolean;
begin
write(’Unesite broj izmedju 5 i ’, MaxEl, ’ > ’);
readln(N)
for k := 2 to N do Precrtan[k] := false;
for k := 2 to trunc(sqrt(N)) do
if not Precrtan[k] then
begin
(* precrtavanje umnozaka *)
i := 2 * k;
while i <= N do
begin
Precrtan[i] := true;
i := i + k
end;
end;
writeln(’Prosti brojevi su:’);
for k := 2 to N do
if not Precrtan[k] then write(k:4);
writeln
end.
Program ovako kako je napisan radi korektno, ali ima jedan mali kozmeticki nedostatak:nizPrecrtan zauzimaznatnoviše mesta nego što bismo ocekivali! Da bi se dobilona brzini pristupa elementima niza, ukoliko je niz tipa “mali” (kao što je slucaj satipom Boolean), racunar za jedan element niza rezerviše onoliko mesta koliko jenjemu zgodno. Recimo, moderni racunari bi zbog arhitekture svojih procesora u
9.4. NIZ KAO IMENOVANI TIP PODATAKA 217
ovom slucaju za jedan element niza rezervisali dva bajta (ili moždacak i cetiriukoliko je procesor 64-bitni!). To znaci da se od 16 bitova (ili moždacak i 32)koliko je rezervisano za smeštanje jednog elementa niza koristi samo jedan.
Postoji mogucnost da se prevodiocu naredi da se za elemente takvih nizovarezerviše najmanji potreban broj bitova, a to se postiže direktivompacked kao udeklaraciji
var
N, i, k : integer;
Precrtan : packed array [2 .. MaxEl] of Boolean;
U ovom slucaju ce za jedan element niza biti rezervisan tacno jedan bit. Time seštedi memorija, ali se gubi na brzini zato što je sada procedura pristupa elementimaniza komplikovanija.
Programer mora sam da odluci da li mu je za izvršenje programa važnija uštedamemorije ili brzina. Praksa, me-dutim, pokazuje da se danas, kada racunari imajumemorije u obilju, programeri najcešce odlucuju da dobiju na brzini, pa ova mogu-cnost programskog jezika Pascal polako odumire. Neki prevodiocicak idu tolikodaleko da ignorišu direktivupacked i pakovane nizove tretiraju isto kao da nisupakovani.
9.4 Niz kao imenovani tip podataka
Neka su promenljivea i b deklarisane ovako:
var
a : array [1 .. MaxN] of integer;
b : array [1 .. MaxN] of integer;
Ako je potrebno iskopirati niza u niz b, nema nam druge nego da to uradimou jednojfor petlji:
for i := 1 to MaxN do b[i] := a[i];
Prirodno se postavlja pitanje: da li ovo može da se uradi brže? Zašto racunar ne bito mogao da uradi automatski? Da li može da se kaže nešto kaob := a?
I odgovor na sva ova pitanja je, naravno, DA,cim uspemo da ubedimo prevodilacda promenljivea i b zauzimaju istu kolicinu memorije, kao i to da je je u obaslucaja memorija organizovana na isti nacin. U tom slucaju se kopiranje sadržajamože uraditi jednom super-brzom mašinskom instrukcijom.
Prevodilac bi mogao da bude veštacki inteligentan i da sam do-de do zakljuckada promenljivea i b zauzimaju istu kolicinu memorije koja je organizovana na
218 GLAVA 9. NIZOVI
isti nacin u oba slucaja, ali bi se time kompliacija znacajno usporila. 1970-ihkada je Pascal nastao mašine nisu bile ni blizu brze kao što su to mašine danas,tako da se ovakva analiza uopšte nije isplatila. Zato se autor Pascala opredelioza jedno veoma jednostavno i efikasno rešenje: ako bismo postigli daime tipaobepromenljive bude isto, prevodilac ne bi imao nikakvih problema da zakljuci da smeda kopira jednu promenljivu u drugu bajt po bajt. Trik se zato sastoji u tome daprvo deklarišemo novi tip i da onda kažemo da sua i b tog tipa:
type
Niz = array [1 .. MaxN] of integer;
var
a, b : Niz;
Sada je naredbab := a legalna, a efekt je tacno onaj koji smo želeli: najbržemoguce kopiranje sadržaja promenljivea u promenljivub. Uopšte, u Pascalu važisledece pravilo:
Ukoliko promenljivea i b nisu nekog prostog tipa, onda je naredbab := a dozvoljena ako i samo ako obe promenljive imaju tip saistim imenom.
Sledi kompletan primer koji baš i ne radi nešto jako pametno, ali pokazuje kakose definiše i koristi novistrukturirani tip podataka:
program NeBasJakoBistarPrimer;
const
MaxEl = 20;
type
Niz = array [1 .. MaxEl] of integer;
var
i : integer;
a, b : Niz;
begin
for i := 1 to MaxEl do readln(a[i]);
b := a;
for i := 1 to MaxEl do writeln(b[i])
end.
Nagradno pitanje: Šta radi ovaj program?
9.4. NIZ KAO IMENOVANI TIP PODATAKA 219
Nizovi mogu da se pojave kaoargumenti procedura i funkcija kaošto pokazuje sledeci primer.
Primer. Napisati funkciju kojautvr -duje koliko pozitivnih brojevaima u datom nizu brojeva.
const
MaxEl = 100;
type
Niz = array [1 .. MaxEl] of real;
...
function BrPoz(a : Niz) : integer;
var
i, n : integer;
begin
n := 0;
for i := 1 to MaxEl do
if a[i] > 0 then
n := n + 1;
BrPoz := n
end;
☞ Kada se nizovi javljaju kao argumenti procedura i funkcija moramo da vodimoracuna o nekoliko stvari:
• niz se može pojaviti kao argument procedure ili funkcijesamo kaoimenovanitip podataka; dakle, ovako nešnone smeda se pojavi u programu:
function BrPoz(a : array [1 .. MaxEl] of real) : integer;
^^^^^^^^^^^ NE SME ^^^^^^^^^^^
• funkcijane možeda vrati niz kao svoju vrednost; zato ovako neštone smedase pojavi u programu:
function F(n : integer) : Niz;
^^^ NE SME
Ako niz treba preneti u proceduru ili funkciju, onda je kao u primeru na pocetkupotrebno definisati odgovarajuci tip podataka. Ako želimo da vratim niz kao rezultatnekog racunanja, onda moramo koristiti proceduru u koju se niz prosle-duje kaoulazno-izlazni argument, na primer ovako:
procedure P(n : integer; var REZ : Niz); { ovo je OK }
220 GLAVA 9. NIZOVI
Zadaci.9.31. Norma 1niza brojeva(a1,a2, . . . ,an) je sledeci broj |a1|+ |a2|+ . . .+ |an|,
norma 2istog niza je sledeci broj:√
a21 +a2
2 + . . .+a2n, anorma∞ je broj:
max{|a1|, |a2|, . . . , |an|}. Napisati funkcijeNorma1, Norma2 i NormaInfkoje racunaju odgovarajucu normu niza brojeva, pricemu je tip podatakaniza dat sa
const
MaxEl = 1000;
type
Niz = array [1 .. MaxEl] of real;
9.32. Napisati proceduruVelikaSlova(var s : NizSlova; n : integer)
koja u delu nizas od prvog don-tog mesta mala slova konvertuje u velika,dok ostale simbole ostavlja neizmenjene. Pri tome je:
const
MaxEl = 1000;
type
NizSlova = array [1 .. MaxEl] of char;
9.33. Napisati proceduru
Bin(n : integer; var b : Niz; var len : integer)
koja nizb puni ciframa brojan u binarnom zapisu. Argumentlen sadržidužinu dobijenog niza.
9.5 Polinomi
Polinom stepenan je algebarski izraz oblika
anxn +an−1xn−1 + . . .+a1x+a0
gde suai neki realni brojevi ian 6= 0. Polinom se može opisati sledecim tipompodataka pricemu za promenljivua tipaPolinom vrednosta[i] predstavlja koeficijentuzxi :
const
9.5. POLINOMI 221
MaxSt = 200;
type
Polinom = array [0 .. MaxSt] of real;
Na primer, polinom−x6−8x3 +25x+11 cemo predstaviti u memoriji kao sledeciniz:
01234567MaxSt
· · ·0 0 −1 −8 25 110 0 0
Polinome ucitavamo tako što ucitavamo parove brojevaai , i, sve dok ne do-demodo slobodnogclana, kada prekidamo sa ucitavanjem. Na primer, polinom−x6−8x3 +25x+11 cemo ucitati tako štoce korisnik uneti sledece:
1 6
8 3
25 1
11 0
Procedura koja realizuje ucitavanje polinoma sada izgleda ovako (pretpostavljamoda ce korisnik unositi stepene monoma koji su uvek izme-du 0 i MaxSt; bez ovepretpostavke procedura bi bilo nešto komplikovanija zato što bismo morali davršimo dodatne provere):
procedure UcitajPol(var p : Polinom);
var
koef : real;
i : integer;
begin
for i := 0 to MaxSt do p[i] := 0;
repeat
readln(koef, i);
p[i] := koef
until i = 0
end;
Kasnijece nam zatrebati i funkcija koja odre-duje stepen polinoma. Stepen polinomaanxn + an−1xn−1 + . . . + a1x+ a0 je najmanjei za koje jeaine0; ako takvoi nepostoji, stepen polinoma je 0:
222 GLAVA 9. NIZOVI
function StepenPol(p : Polinom) : integer;
var
n : integer;
begin
n := MaxSt;
while (a[n] = 0) and (n > 0) do n := n 1;
StepenPol := n
end;
Procedura koja ispisuje polinom treba da ispiše sve monomeciji koeficijent jerazlicit od 0. Na primer, polinom−x6−8x3 +25x+11 ce biti ispisan ovako:
1.00 * x^6
8.00 * x^3
25.00 * x
11.00
Primetimo da linearni i slobodniclan imaju poseban tretman pri ispisu! Treba jošsamo voditi racuna o tome da za polinom koji ima samo slobodniclan treba ispisatisamo slobodniclan polinoma, nezavisno od toga da li je on 0 ili ne:
procedure IspisiPol(p : Polinom);
var
n, i : integer;
begin
n := StepenPol(p);
if n = 0 then
writeln(p[0] : 10 : 2)
else begin
for i := n downto 2 do
if p[i] <> 0 then
writeln(p[i] : 10 : 2, ’ * x^’, i);
if p[1] <> 0 then writeln(p[1] : 10 : 2, ’ * x’);
if p[0] <> 0 then writeln(p[0] : 10 : 2)
end
end;
Zadaci.9.34. Napisati procedure
SaberiPol(a, b : Polinom; var c : Polinom);
OduzmiPol(a, b : Polinom; var c : Polinom);
od kojih prva sabira, a druga oduzima dva polinoma.
9.5. POLINOMI 223
9.35. Napisati funkcijuIzracunajPol(p : Polinom; x : real) : real;
koja racuna vrednost polinomap za radi realan brojx (tj. racunap(x)).
9.36. Napisati Pascal program koji od korisnika ucitava polinomp, potom ceobroj n i n realnih brojevax1, . . . ,xn, i racuna i štampa broj
p(x1)+ . . .+ p(xn).
9.37. Napisati Pascal program koji od korisnika ucitava polinomp, realan brojα i prirodan brojn i racuna i štampa vrednost sledeceg izraza:
p(α)+ p(p(α))+ . . .+ p(p(. . .(p︸ ︷︷ ︸
n
(α)) . . .)).
9.38. Napisati Pascal program koji od korisnika ucitava polinomp i štampapolinom p(x2).
9.39. Napisati proceduruDodeliPolBr(var p : Polinom; a : real);
koja datom polinomup dodeljuje broja. (To znaci da jep[0] = a, dokse ostali koeficijenti polinomap postavljaju na nulu.)
9.40. Napisati Pascal program koji od korisnika ucitava prirodan brojn, potomn polinoma i racuna i ispisuje njihovu sumu.
9.41. Napisati proceduruPomnoziPolBr(a: Polinom; b: real; var c:
Polinom); koja racuna proizvod polinomaa i realnog brojab.
9.42. Napisati Pascal program koji od korisnika ucitava prirodan brojn potomnpolinomap1, . . . , pn, i potom racuna i štampa polinom
p1 +22p2 +32p3 + . . .+n2pn.
9.43. Napisati proceduruPomnoziPol(a, b : Polinom; var c : Polinom);
koja racuna proizvod dva polinoma.
9.44. Napisati Pascal program koji ucitava polinomp, prirodan brojn i racuna ištampa polinom
p+ p2 + . . .+ pn.
9.45. Napisati Pascal program koji ucitava dva polinoma,p i q, i racuna i štampapolinom p(q(x)).
224 GLAVA 9. NIZOVI
9.46. Napisati Pascal program koji od korisnika ucitava prirodan brojn > 3,potomn polinomaP1(x), P2(x), . . . ,Pn(x) i odre-duje i štampa polinom
P1(P2(x))+P2(P3(x))+P3(P4(x))+ . . .++Pn−1(Pn(x))+Pn(P1(x))n
.
9.47. Napisati Pascal program koji od korisnika ucitava prirodan brojn > 3,potomn polinomaP1(x), P2(x), . . . ,Pn(x) i odre-duje i štampa polinom
11
P1(x)+12
P2(x)2 +
13
P3(x)3 + . . .+
1n
Pn(x)n.
9.48. Kada se polinomanxn +an−1xn−1 + . . .+a1x+a0 podeli binomomx− pdobija se kolicnik bn−1xn−1 + . . .+b1x+b0 i ostatakr. Koli cnik i ostatakpri deljenju polinoma binomomx− p se mogu lako izracunati koristecitzv. Hornerovu šemu:
bn−1= an
bn−2= bn−1p+an−1
bn−3= bn−2p+an−2...
b1 = b2p+a2
b0 = b1p+a1
r = b0p+a0.
Napisati proceduru
PodeliPolBin(a : Polinom; p : real; var b : Polinom;
var r : real);
koja racuna kolicnik i ostatak pri deljenju polinomaa binomomx− p.
9.49. Raspisati polinomanxn +an−1xn−1 + . . .+a1x+a0 po stepenima odx− pznaci naci brojevebn, bn−1, . . . ,b0 takve da je
anxn + . . .+a1x+a0 = bn(x− p)n + . . .+b1(x− p)+b0.
Napisati Pascal program koji od korisnika ucitava polinoma i realan brojp i odre-duje koeficijentebn, . . . ,b0 koji se dobijaju raspisivanje polinomaa po stepenima odx− p.
9.50. Potom napisati program koji od korisnika ucitava polinom sa celobrojnimkoeficijentima i odre-duje sve celobrojne nule tog polinoma. (Uputstvo:Celobrojne nule polinoma su delioci slobodnogclana tog polinoma, ukolikoje od razlicit od 0. Napraviti tip podatakaCPolinom koji opisuje polinomesa celobrojnim koeficijentima.)
9.6. VELIKI BROJEVI 225
9.6 Veliki brojevi
Svaki programski jezik ima ogranicenje na maksimalan broj cifara celih brojevasa kojima zna da racuna. Ako želimo da radimo sa celim brojevima koji su veciod onih koje jezik inicijalno podržava, moramo sami da napišemo odgovarajuceprocedure. Veliki brojcemo pamtiti kao niz cifara:
const
MaxC = 300;
type
VBroj = array [0 .. MaxC] of integer;
pri cemu usvajamo konvenciju da u kucici redni brojk stoji cifra koja odgovarastepenu 10k. Na primer, broj 7145239cemo predstaviti sledecim nizom:
01234567MaxC
· · ·0 0 7 5 3 91 4 2
ProceduraUcitajVBroj ucitava veliki broj i uz put brine o tome da na pocetakdopiše dovoljnu kolicinu nula.
procedure UcitajVBroj(var a : VBroj);
var
n, i, t : integer;
c : char;
begin
n := 1;
while not eoln do begin
read(c);
n := n + 1;
a[n] := ord(c) ord(’0’)
end;
readln;
for i := n + 1 to MaxC do a[i] := 0;
{ zamenimo mesta }
for i := 0 to n div 2 do begin
t := a[i];
a[i] := a[n i];
a[n i] := t
end
end;
226 GLAVA 9. NIZOVI
ProceduraIspisiVBroj ispisuje veliki broj uz preskakanje vodecih nula:
procedure IspisiVBroj(a : VBroj);
var
i, j : integer;
begin
i := MaxC;
while (a[i] = 0) and (i > 0) do i := i 1;
for j := i downto 0 do write(a[j]);
writeln
end;
Sledi procedura koja sabira dva velika broja tako što simulira sabiranje “peške”.Pretpostavlja se da rezultat sabiranja može da stane uVBroj.
procedure SaberiVBroj(a, b : VBroj; var c : VBroj);
var
i, prenos, rez : integer;
begin
prenos := 0;
for i := 0 to MaxC do
begin
rez := a[i] + b[i] + prenos;
c[i] := rez mod 10;
prenos := rez div 10
end
end;
Pogledajmo sada proceduru koja oduzima dva velika broja simulirajuci oduzimanje“peške”. Pretpostavljamo da prvi broj nije manji od drugog jer ne radimo sanegativnim brojevima.
procedure OduzmiVBroj(a, b : VBroj; var c : VBroj);
var
i : integer;
begin
for i := 0 to MaxC 1 do
begin
if a[i] < b[i] then { pozajmljujemo }
begin
a[i] := a[i] + 10;
a[i + 1] := a[i + 1] 1
end;
c[i] := a[i] b[i]
end;
9.6. VELIKI BROJEVI 227
c[MaxC] := a[MaxC] b[MaxC]
end;
Na kraju pokazujemo proceduru koja poredi dva velika broja. Ona vraca−1 akoje prvi broj manji, 0 ako su jednaki, odnosno 1 ako je prvi broj veci.
function UporediVBroj(a, b : VBroj) : integer;
var
i : integer;
begin
i := MaxC;
while (i > 0) and (a[i] = b[i]) do i := i 1;
if a[i] < b[i] then UporediVBroj := 1
else if a[i] = b[i] then UporediVBroj := 0
else UporediVBroj := 1
end;
Zadaci.9.51. Napisati proceduruDodeliVBrojBr(var a : VBroj; b : integer);
koja “mali” prirodan brojb upisuje u veliki broja i tako simulira naredbua := b.
9.52. Napisati Pascal program koji od korisnika ucitava prirodan brojn, potomn velikih brojeva i potom racuna i ispisuje njihov zbir.
9.53. Napisati proceduruPomnoziVBrojBr(a : VBroj; b : integer; var
c : VBroj); koja množi veliki broj “malim” brojem.
9.54. Napisati program koji racuna i ispisuje 1000-ti Fibonaccijev broj (on imamanje od 300 cifara).
9.55. Napisati Pascal program koji od korisnika ucitavan i racuna i ispisujen-ti clan niza koji je dat sledecom rekurentnom vezom:a0 = 0, a1 = 13,an = 4an−1 +9an−2.
9.56. Napisati Pascal program koji od korisnika ucitavan i racuna i ispisujen-ticlan niza koji je dat sledecom rekurentnom vezom:a1 = 1, a2 = 2, a3 = 3,an = n2an−1−2an−2−3an−3.
9.57. Napisati Pascal program koji od korisnika ucitavan i potom racuna i štampan! koristeci velike brojeve.
9.58. Napisati Pascal program koji od korisnika ucitavan i potom racuna i štampa∑n
k=1k! koristeci velike brojeve.
9.59. Napisati proceduruPomnoziVBroj(a, b : VBroj; var c : VBroj);
koja množi dva velika broja.
228 GLAVA 9. NIZOVI
9.60. Napisati Pascal program koji od korisnika ucitavanpotomnvelikih brojevaa1, . . . ,an i racuna i štampa vrednost izrazaa2
1 + . . .+a2n.
9.61. Niz brojeva zadat je na sledeci nacin: L0 = 2, L1 = 5, Ln = 3Ln−1−2Ln−2.Napisati Pascal program koji racunaL1000ako se zna da taj broj ima manjeod 400 cifara.
9.62. Napisati Pascal program koji od korisnika ucitavan i racuna i ispisujen-ticlan niza koji je dat sledecom rekurentnom vezom:a0 = 1, a1 = 5,
an =
{an−1an−2, n neparno
(n−1)an−1 +an−2, inace.
9.63. Napisati proceduru
PodeliVBrojBr(a : VBroj; b : integer; var q : VBroj; var
r : integer);
koja deli veliki broj “malim” brojem. Argumentq sadrži kolicnik, a argumentr ostatak celobrojnog deljenja.
9.64. Za prirodan brojn kažemo da je pseudoprost ako nije prost, alin|2n−2.Napisati Pascal program koji od korisnika ucitava pozitivan ceo brojn iutvr -duje da li je to pseudoprost broj. Obratiti pažnju na to da 2n može bitiveci odmaxlongint.
9.7. SISTEMATIZACIJA 229
9.7 Sistematizacija
Deklaracija promenljive nizovnog tipa ima sledeci oblik:
var
〈ime〉 : array [〈nabrojivi_tip〉] of 〈proizvoljan_tip〉;
ili u zapakovanoj verziji
var
〈ime〉 : packed array [〈nabrojivi_tip〉] of 〈proizvoljan_tip〉;
Pri tome〈nabrojivi_tip〉 može biti neki podintervalni tip naveden eksplicitno:
var
〈ime〉 : array [〈konstanta〉 .. 〈konstanta〉] of 〈proizvoljan_tip〉;
Niz se može definisati i kao poseban tip:
type
〈novo_ime_tipa〉 = array [〈nabrojivi_tip〉] of 〈proizvoljan_tip〉;
Za promenljiveciji tipovi nisu prosti, ali imaju isto ime dozvoljeno je kopiranjesadržaja jedne od njih u drugu:
type
〈novo_ime_tipa〉 = 〈neka_definicija_tipa〉;var
〈var1〉, 〈var2〉 : 〈novo_ime_tipa〉;begin
...
〈var2〉 := 〈var1〉;...
end.