Języki programowania Haskell zadanie projektowe nr. 4 2014/15 K. Turowski, T. Goluch 1. Kompilacja, uruchamianie i Hello world Kompilacja i uruchamianie: ghc --make hello.hs./hello Interaktywny interpreter: ghci hello.hs main = putstrln "Hello world!" Haskel w przeglądarce: http://tryhaskell.org/ http://ideone.com/ 2. Cechy języka wszystko jest funkcją funkcja składa się z deklaracji: nazwa_funkcji::kwalifikatory_typu => Typ_Argumentu_1 -> Typ_Argumentu_2 -> Typ_Wyniku nazwa_funkcji argument_1 argument_2 = let definicje_podfunkcji in polecenie zwracające wynik podstawowe typy danych (operator :: - czytamy jako: jest typu ): True::Bool, 'a'::char, 1::Int, 1::Integer, 1.0::Double, "abc"::string (tożsame z listą znaków [Char]) listy: 1:2:3:4:[], 1:2:[3, 4], [1, 2, 3, 4] lub [1, 2.. 4] lub [1.. 4]::[Int] - homogeniczne o zmiennej długości krotki: (1, a, litera ) heterogeniczne o stałej długości programowania{c91e19c4-8b08-4d63-9b7c-0913aab2a7ce} 1
funkcje nie są redefiniowalne (w obrębie własnego zakresu) więc np. x = 2 x = 3 main = print x nie zadziała kolejność funkcji w pliku nie ma znaczenia main = print x x = 123 leniwe wartościowanie - obliczenia są wykonywane TYLKO wtedy, gdy jest to niezbędne np. podziel :: (RealFrac a) => a -> a -> a podziel x y = let q = (/) x y in if (abs y) < 0.001 then 0 else q ukonkretnianie funkcji odwroc :: (RealFrac a) => a -> a odwroc = podziel 1 składanie funkcji identycznosc :: (RealFrac a) => a -> a identycznosc = odwroc. odwroc 3. Silnia i wyrażenia: if then else, let in, where oraz silnia :: (Num a, Ord a) => a -> a silnia n = if n == 1 then 1 else n * silnia (n - 1) silnia n = let loop n' a = if n' == 1 then a else loop (n' - 1) (a * n') in loop n 1 silnia n = let loop n' a n' == 1 = a otherwise = loop (n' - 1) (a * n') in loop n 1 silnia n = loop n 1 where loop n' a n' == 1 = a otherwise = loop (n' - 1) (a * n') 4. Listy, mapy i filtry moduł zawierający: import Data.List typowe funkcje: head, tail, last, init, reverse, take n reverse::[a] -> [a] reverse [] = [] reverse (x:y) = reverse y ++ [x] nieskończony ciąg Fibonacciego fibonacci = 1:1:[(a + b) (a, b) <- zip fibonacci (tail fibonacci)] print fibonacci powoduje nieskończoną pętlę, print (take 1000 fibonacci) działa bo leniwe wartościowanie wykonanie funkcji f na wszystkich elementach listy x map f x [f xs xs <- x] np. map cos [1..10] programowania{c91e19c4-8b08-4d63-9b7c-0913aab2a7ce} 2
map (+1) [1..10] map (\x -> 3 * x + 2) [1..10] wybranie tylko elementów funkcji f na wszystkich elementach listy x filter f x np. filter (>3) [-10..10] filter (\x -> x * x == 1) [-10..10] scalenie dwóch list w listę par (elementy dłuższej listy są odrzucane zip a b np. zip "Mississippi" [-10..10] 5. Tablice 1 moduł zawierający: import Data.Array tworzenie tablicy sqr zawierającej kwadraty liczb od 1 do 100 array :: (Ix a) => (a,a) -> [(a,b)] -> Array a b sqr = array (1,100) [(i, i*i) i <- [1..100]] pobranie kwadratu liczby 7 sqr!7 => 49 sprawdzenie zakresów wymiarów tablicy bounds sqr => (1,100) rekurencyjne tworzenie tablicy zawierającej liczby Fibonacciego fibs :: Int -> Array Int Int fibs n = a where a = array (0,n) ([(0, 1), (1, 1)] ++ [(i, a!(i-2) + a!(i-1)) i <- [2..n]]) pobranie 10 elementu ciągu fibs 10! 10 => 89 6. Tablice haszujące tworzenie tablicy H z przykładowej listy par H :: Map Char Int H = fromlist [('a', 3), ('b', 5), ('c', 7)] wyszukiwanie elementu x w tablicy H wynik :: Maybe a wynik = lookup x H 7. Typy danych proste: data Color = Red Green Blue isred :: Color -> Bool isred Red = True isred _ = False main = print (isred Blue) 1 https://www.haskell.org/tutorial/arrays.html programowania{c91e19c4-8b08-4d63-9b7c-0913aab2a7ce} 3
złożone: data Chars = Value Char Join Chars Chars ischar :: Chars -> Bool ischar (Value x) = True ischar _ = False tostring :: Chars -> String tostring (Join x y) = (tostring x) ++ (tostring y) tostring (Value x) = [x] main = print (tostring (Join (Join (Value 'a') (Value 'b')) (Value 'c'))) 8. Funkcje: group, sort Funkcja group przyjmuje listę i zwraca listę składającą się z list zgrupowanych identycznych kolejnych elementów. Przykładowo: group :: Eq a => [a] -> [[a]] group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"] Funkcja sort implementuje stabilną wersję algorytmu sortującego. Przykładowo: sort :: Ord a => [a] -> [a] sort "Mississippi" = "Miiiippssss" Funkcje wymagają zaimportowania modułu Data.List 9. Zadanie domowe Zadanie pierwsze (3 pkt.) 1) Dla danej liczby n wyświetlić w postaci listy n-ty wiersz trójkąta Pascala, 2) Dla danej liczby naturalnej n znaleźć sumę wszystkich parzystych elementów ciągu Fibonacciego o wartości mniejszej niż n. 3) Dla danej liczby naturalnej n podaj różnicę pomiędzy kwadratem sum a sumą kwadratów liczb od 1 do n. Dla n = 2 wynik jest następujący: (1 + 2) 2 (1 2 + 2 2 ) = 9 5 = 4. 4) Dla danej listy L wypisz listę par [(element, liczba wystąpień), ], 5) Dla danej liczby naturalnej n wyświetl n-tą liczbę pierwszą. Zakładając, że pierwszą liczba pierwszą jest dwa. 6) Dla danej listy i elementu należy wypisać listę indeksów wszystkich wystąpień elementu na liście, 7) Dla danej listy par należy zwrócić listę tych par posortowaną wg amplitudy punktu we współrzędnych biegunowych, 8) Dla danej liczby n należy obliczyć listy rozkładu liczby na czynniki pierwsze i unikalne czynniki pierwsze, 9) Dla danych zbiorów w postaci list L i M obliczyć ich różnicę i różnicę symetryczną, 10) Dla danej listy L liczb całkowitych znaleźć najmniejszą liczbę dodatnią podzielną przez wszystkie liczby z L. 11) Dla danego dla danych list L i M należy sprawdzić, czy jedna jest permutacją drugiej, 12) Dla podanej liczby n podaj, jeśli to możliwe, trójkę pitagorejską a, b, c taką, że a+b+c=n. Dla n = 12 jest nią odpowiednio: 3, 4, 5 ponieważ 3 2 + 4 2 =5 2. 13) Dla danej liczby naturalnej n podaj taką liczbę n, która da się rozłożyć na największą liczbę różnych trójek a, b, c. Takich, że a + b + c = n i z boków o długości a, b, c można zbudować trójkąt prostokątny. 14) Dla danej liczby naturalnej n podaj sumę cyfr liczby równej n!. Dla n = 10, 10! = 10... 2 1 = 3628800, co daje w wyniku: 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27. 15) Dla danej liczby naturalnej n podaj od dla jakiej liczby naturalnej m n zaczyna się najdłuższy ciąg Collatza. programowania{c91e19c4-8b08-4d63-9b7c-0913aab2a7ce} 4
16) Dla danej liczby naturalnej n podaj sumę cyfr liczby równej 2 n. Dla n = 15, 2 15 = 32768, co daje w wyniku: 3 + 2 + 7 + 6 + 8 = 26. 17) Dla danej liczby naturalnej n istnieje ciąg ułamków od 1/2, 1/3,, 1/n. Wskaż którego okres w reprezentacji dziesiętnej jest najdłuższy. Dla n = 10, wynikiem jest 1/7= 0.(142857). 18) Dla danej liczby naturalnej n 30000 podaj największą liczbę naturalną która nie może zostać zapisana przy pomocy sumy dwóch liczb obfitych 2. 19) Dla danych liczb naturalnych n i m podać n-tą liczbę z porządku leksykograficznego liczb od 0 do n. Przykładowo dla n = 2 i m = 3 wynikiem jest 0132. 20) Dla danych zbiorów w postaci list L i M obliczyć ich iloczyn i sumę, 21) Dla danej liczby naturalnej n 999 podaj liczbę znaków w jej reprezentacji słownej. Dla n = 345 wynikiem jest 23, z tylu znaków składa się napis trzysta czterdzieści pięć. 22) dla danego zbioru w postaci listy L obliczyć jego zbiór potęgowy. 23) Dla danej liczby naturalnej n wyświetl pierwszą liczbę trójkątna (suma kolejnych liczb naturalnych) która posiada więcej niż n dzielników. Np. siódma liczba trójkątna 28 = 1 + 2 + 3 + 4 + 5 + 6 + 7 posiada 6 dzielników: 1, 2, 4, 7, 14, 28. 24) Dla danej liczby naturalnej n podaj liczbę pierwszą n, która równa jest sumie składającej się z największej liczby różnych liczb pierwszych. Dla n = 81, wynikiem jest 41. Można ją zapisać przy pomocy sumy 6 liczb pierwszych: 2 + 3 + 5 + 7 + 11 + 13. 25) Dla danej liczby n należy znaleźć liczbę jej dzielników, mniejszych od n, Uwaga: złożoność programu powinna wynosić O(p + k), gdzie p największy dzielnik n mniejszy od sqrt(n), k liczba dzielników n 26) Dla danej liczby naturalnej n podaj wszystkie liczby pierwsze n dla których każda rotacja ich cyfr nadal jest liczbą pierwszą 3. Taką liczbą jest 197 i jej dwie możliwe rotacje: 971 i 719. 27) Dla danej liczby naturalnej n 5 podaj sumę liczb które mogą zostać zapisane jako suma n-tych potęg swoich cyfr. Dla n = 4 wynikiem jest 19316 = 1634 + 8208 + 9474 = 1 4 + 6 4 + 3 4 + 4 4 + 8 4 + 2 4 + 0 4 + 8 4 + 9 4 + 4 4 + 7 4 + 4 4. 28) Dla danej liczby naturalnej n oraz listy L liczb naturalnych, znaleźć sumę wszystkich liczb naturalnych od 1 do n podzielnych przez przynajmniej jedną liczbę z L. 29) Dla danej liczby naturalnej n znaleźć największy palindrom który można uzyskać z mnożenia liczb n-cyfrowych. Dla n=2 największym palindromem jest 9009 = 91 99. 30) Dla danej liczby naturalnej n podaj sumę wszystkich liczb n, które jednocześnie są palindromami w reprezentacji dziesiętnej i binarnej. Taką liczbą jest 585 10 = 1001001001 2. 31) Dla danej listy par należy zwrócić listę tych par posortowaną wg odległości od punktu (0, 0), 32) Dla danej liczby naturalnej n podaj największą, jeśli istnieje, parę liczb zaprzyjaźnionych a i b takich, że a n, b n. Uwagi: a. wszystkie funkcje powinny posiadać odpowiedni nagłówek z typem funkcji, b. w programach nie można korzystać z funkcji spoza instrukcji, c. funkcja sort dozwolona jest tylko w zadaniu poniżej. Zadanie drugie (12 pkt.) Napisać program do rozwiązywania rachunku zdań z funktorami negacji (N), koniunkcji (K), alternatywy (A) i implikacji (C) Typ zdania: data Zdanie = Z Char - tj. zmienną może być dowolna zmienna z Przykładowe zdanie: (C (N (Z 'p')) (A (K (Z 'p') (Z 'q')) (Z 'r'))) Program powinien: 1) zawierać funkcję: drukuj zdanie (2 pkt.) 2 https://en.wikipedia.org/wiki/abundant_number 3 https://en.wikipedia.org/wiki/circular_prime programowania{c91e19c4-8b08-4d63-9b7c-0913aab2a7ce} 5
dla zadanego przykładu (C (N (Z 'p')) (A (K (Z 'p') (Z 'q')) (Z 'r'))) wyjściem powinno być "(~p => ((p & q) r))" 2) posiadać funkcję: wypisz_zmienne zdanie (2 pkt.) dla zadanego przykładu (C (N (Z 'p')) (A (K (Z 'p') (Z 'q')) (Z 'r'))) wyjściem powinno być [p, q, r] (niekoniecznie posortowane, ale unikalne) 3) posiadać funkcję: sprawdz zdanie mapa wartosci (4 pkt.) dla zadanego przykładu (C (N (Z 'p')) (A (K (Z 'p') (Z 'q')) (Z 'r'))) oraz mapy wartości fromlist [('p', False), ('q', True), ('r', False)] wyjściem powinno być False 4) posiadać jedną z funkcjonalności a/b (4 pkt.) 4a) wykonywać zadania 1-3 dla trójwartościowej logiki Łukasiewicza True/False/Nothing 4b) posiadać funkcję: jest_tautologia zdanie sprawdzającą, czy zdanie jest spełnione dla dowolnego wartościowania zmiennych w formule Projekty proszę przesyłać na adres prowadzącego: goluch@eti.pg.gda.pl Proszę koniecznie zatytułować pocztę w następujący sposób: JPGZNRINDEKS gdzie: G numer grupy dziekańskiej, przykładowo: 1 - grupa nr. 1, Z numer części zadania, przykładowo: 4 to zadanie Haskell. NR - numer zadania indywidualnego, przykładowo: 04 zad. Indywidualne z Haskell a INDEKS - sześcioliterowy numer indeksu, przykładowo: 103057. programowania{c91e19c4-8b08-4d63-9b7c-0913aab2a7ce} 6