Sveučilište u Zagrebu Fakultet elektrotehnike i računarstva PROGRAMIRANJE U HASKELLU Ak.god. 2011/12. LEKCIJA 3: sažet zapis listi, n-torke v1.0 (c) 2011 Jan Šnajder ============================================================================== > import Data.Char > import Data.List === SAŽET ZAPIS LISTI (AKA LIST COMPREHENSIONS) ============================== > doubles = [x*2 | x <- [1..10]] > doublesFromTo a b = [x*2 | x <- [a..b]] > sums1 = [x + y | x <- [1..10], y <- [1..10]] > sums2 = [x + y | x <- [1..10], y <- [1..10], x < y] > sums3 = [x + y | x <- [1..10], y <- [1..10], x < y, odd x || even y] Lista duljina podlista: > lengths xss = [length xs | xs <- xss] > microLength xss = sum $ lengths xss Kombiniranje stringova: > food = [s1 ++ " " ++ s2 | > s1 <- ["hladna","topla","svježa"], > s2 <- ["torta","gibanica","salata"]] Kako su liste zapravo stringovi, možemo raditi list comprehensions nad znakovima u stringu: > codes = [ [c1,c2] | c1 <- "abc", c2 <- "123"] > caesarCode s = [succ c | c <- s, c /= ' '] > onlyDigits s = [c | c <- s, isDigit c] > upperCase s = [toUpper c | c <- s] === VJEŽBA 1 ================================================================= 1.1 - Nadogradite 'doublesFromTo' tako da radi i kada b ws = words "Vožnja bez karte, najskuplja vožnja." Razlamanje stringa na linije: > ls = lines "Prva linija\nDruga Linija" Spajanje linija u jedan string: > stream = unlines ls Filtriranje riječi koje počinju velikim slovom: > capitalized s = [w | w <- words s, isUpper $ head w] > camelCase s = concat [toUpper (head w) : tail w | w <- words s] Ili, preglednije, pomoću podudaranja uzoraka (pattern matching): > camelCase' s = concat [toUpper g : r | (g:r) <- words s] === VJEŽBA 2 ================================================================= 2.1. - Napravite funkciju koja izračunava ukupan broj slova u rečenici, ignorirajući praznine i sve riječi koje su manje od tri slova. Možete iskoristiti funkciju 'microLength'. 2.2 - Nadogradite 'isPalindrome' tako da ispravno radi i kada postoje praznine te neovisno o veličini slova. ============================================================================== Matrice možemo prikazati kao listu listi: > matrix = [[1,2,3],[4,5,6],[7,8,9]] Zbrajanje svih elemenata matrice: > sumMatrix m = sum [ e | row <- m, e <- row] Inkrementiranje svih elemenata matrice: > incMatrix m = [ [ e+1 | e <- row] | row <- m] Logičke operacije nad listom: jesu li svi elementi liste jednaki 100 ili veći? > atLeast100 xs = and [ x >= 100 | x <- xs] Postoji li u stringu znamenka? > containsDigit xs = or [ isDigit x | x <- xs] Postoji li u matrici redak čiji su svi elementi jednaki 'n' ? > rowWithNs n m = or [ and [ e==n | e <- row] | row <- m] Postoje li u matrici retci čiji su svi elementi identični? > rowWithEqualElems m = > or [ and [ e==head row | e <- row] | row <- m] === VJEŽBA 3 ================================================================= 3.1. - Napravite funkciju 'flipp xs' koja uzima listu listi 'xs', obrće svaku pojedinačnu listu i zatim ih sve konkatenira, ali reverzno. Npr. flip ["voda","je","topla"] -> "alptejadov" 3.2. - Napravite funkciju 'takeMins xs ys' koja iz liste ys izdvaja sve elemente koji su jednaki minimalnom elementu u listi 'xs'. 3.3. - Napišite funkciju 'isMatrix' koja provjera je li lista listi matrica. 3.4. - Pomoću sažetog zapisa liste napišite funkciju 'elem' x xs' koja vraća True akko je 'x' element liste 'xs'. === N-TORKE (TUPLES) ========================================================= > pair1 = (1,2) > pair2 = ("Vatroslav","Lisinski") > triplet1 = (10,1,8) > triplet2 = ("Vatroslav","Lisinski", 1819) > e1 = pair1 == (1,2) Što se događa ako pokušamo 'pair1 == pair2' ? > (a,b) = (1,2) Projekcija prvog i drugog elementa liste: > p = fst (5,6) > q = snd (5,6) Lista parova: > pairs = [(1,2),(3,4),(5,6)] Parovi brojeva od 1 do 100: > pairsUpTo100 = [(x,y) | x <- [0..100], y <- [0..100]] Parovi brojeva čiji elementi u zbroju daju 100: > pairsSumTo100 = [(x,y) | x <- [0..100], y <- [0..100], x+y==100 ] Stranice trokuta (cjelobrojne duljine) koje zadovoljavaju Pitagorov poučak (Pitagorejske trojke): > pythagoreanTriplets = > [(a,b,c) | a <- [1..10], b <- [1..10], c <- [1..10], a^2 + b^2 == c^2] Može se optimizirati: > pythagoreanTriplets' = > [(a,b,c) | c <- [1..10], a <- [1..c], b <- [1..a], a^2 + b^2 == c^2] Funkcija 'zip': > pairs2 = zip [1,2,3] "abc" > pairs3 = zip [1,2,3,4] "abc" > pairs4 = zip [1..] "abc" > pairs5 = zip [1..100] [2..100] === VJEŽBA 4 ================================================================= 4.1. - Napisati funkciju 'applyToPair f p' koja primjenuje funkciju 'f' između elemenata para 'p'. - Iskoristiti tu funkciju za funkciju 'addPair'. 4.2. - Napisati funkciju 'inCircle r x y' vraća koordinate svih točaka iz intervala ([-10..10],[-10..10]) koje se nalaze unutar kružnice radijusa 'r' sa središtem '(x,y)'. - Modificirati funkciju tako da kao argument uzima razlučivost rešetke. 4.3. - Napisati funkciju 'steps xs' koja za listu xs=[x1,x2,..] generira parove [(x1,x2),(x2,x3),...]. Hint: pogledati 'pairs5'. ============================================================================== Indeksiranje elemenata liste: > index xs = zip [1..] xs Filtriranje svakog drugog elementa liste: > evenElems xs = [ snd x | x <- index xs, even (fst x)] Korištenje mehanizma podudaranja uzoraka (pattern matching): > evenElems' xs = [ e | (i,e) <- index xs, even i] Zip3: > triplets2 = zip3 [0..10] ['A'..] [100..] === VJEŽBA 5 ================================================================= 5.1. - Napisati funkciju 'indices x xs' koja vraća indekse elementa 'x' u listi 'xs. 5.2. - Napravite funkciju 'showLineNumbers s' koja sve linije iz stringa 's' prefiksira brojem linije. 5.3. - Napisati funkciju 'haveAlignment xs ys' koja vraća 'True' ako liste xs i ys imaju identičnih elemenata koji su poravnati (na istim su pozicijama). - Proširiti funkciju na 'common xs ys' koja vraća takve poravnate podnizove. - Proširiti funkciju tako da vraća i indekse na kojima je nađeno poravnanje. Koristiti funkciju 'zip3'.