Programowanie funkcyjne/Struktury danych/Ćwiczenia
Praca domowa
- Napisz procedurę dubluj, która dubluje elementy listy, na przykład dubluj [1;2;3] = [1;1;2;2;3;3].
- Punkty (kratowe) na płaszczyźnie reprezentujemy jako pary liczb całkowitych. Prostokąty o bokach równoległych do osi układu współrzędnych reprezentujemy jako pary punktów: dolny lewy i górny prawy róg. Napisz procedurę, która dla dwóch danych prostokątów wyznacza ich przecięcie. Podaj w jaki sposób reprezentowany jest zbiór pusty.
- Zadeklaruj wariantowy typ danych reprezentujący abstrakcyjną składnię wyrażeń arytmetycznych. Napisz procedurę obliczającą wartość wyrażenia.
Ćwiczenia
Ćwiczenie [rev]
Zaimplementuj procedurę rev odwracającą listę. (Zwróć uwagę, że rozwiązując to zadanie można korzystać z :: lub @, co daje liniową lub kwadratową złożoność czasową.)
Rozwiązanie nieefektywne, ale proste
Rozwiązanie efektywne
Ćwiczenie [Przeplot list]
Napisz procedurę shuffle: α list → α list → α list, która dla danych dwóch list postaci oraz wyznaczy listę postaci . Jeżeli jedna z list jest dłuższa, to jej końcowe elementy trafiają na koniec listy wyikowej. Na przykład: shuffle [3; 2; 8; 1; 9; 3; 6] [5; 7; 0] = [3; 5; 2; 7; 8; 0; 1; 9; 3; 6].
Ćwiczenie [flatten]
Napisz procedurę flatten rozwijającą listę list do listy elementów. Na przykład, flatten [[1; 2]; []; [3; 4; 5]] = [1; 2; 3; 4; 5].
Rozwiązanie
Ćwiczenie [Średnica drzew]
Dana jest definicja typu: type tree = Node of tree * tree | Leaf. Odległością między dwoma wierzchołkami (Node) w drzewie nazywamy minimalną liczbę krawędzi jakie trzeba przejść z jednego wierzchołka do drugiego. Średnicą drzewa nazwiemy maksymalną odległość między dwoma węzłami (Node) w drzewie. Przyjmujemy, że średnica pustego drzewa (Leaf) jest równa 0. Napisz procedurę srednica: tree -> int, która oblicza średnicę danego drzewa.
Rozwiązanie
Ćwiczenie [Drzewa dowolnego stopnia]
Zdefiniuj typ reprezentujący drzewa o wierzchołkach dowolnego (skończonego) stopnia. Zdefiniuj trochę procedur operujących na takich drzewach, np. procedury wyznaczające listy elementów w porządku prefiksowym i postfiksowym.
Laboratorium
Ćwiczenia programistyczne na listy:
Ćwiczenie [-ty element listy]
Zaimplementuj procedurę zwracającą -ty element listy.
Rozwiązanie
Ćwiczenie [Lista ]
Napisz procedurę tworzącą listę pierwszych liczb naturalnych.
Rozwiązanie
Ćwiczenie [append]
Zaimplementuj procedurę append sklejającą listy.
Rozwiązanie
Ćwiczenie [ciąg różnicowy]
Ciąg różnicowy ciągu to ciąg postaci . Napisz procedurę obliczającą ciąg różnicowy żądanej listy liczb całkowitych.
Rozwiązanie
Rozwiązanie 2
Ćwiczenie [ciąg ciągów różnicowych]
Napisz procedurę obliczającą listę kolejnych ciągów różnicowych zadanej listy liczb całkowitych, tzn.: daną listę, jej ciąg różnicowy, ciąg różnicowy ciągu różnicowego itd.
Rozwiązanie
Ćwiczenie [minimum-maksimum]
Napisz procedurę, której wynikiem jest para: minimum i maksimum elementów z listy. Procedura ta powinna wykonywać co najwyżej porównań.
Ćwiczenie [last]
Napisz procedurę last, której wynikiem jest ostatni element (niepustej) listy.
Rozwiązanie
{{cwiczenie|[head i tail]|| Napisz procedury head i tail, które dla zadanej listy i liczby całkowitej zwracają pierwsze/ostatnie elementów listy . Jeśli lista ma mniej elementów niż , to wynikiem powinna być cała lista . (Nazwy pochodzą od programów head i tail w Uniksie.) Co jest wynikiem tail (head l n) 1?
Rozwiązanie
Ćwiczenie [sortowanie]
Zaimplementuj sortowanie: przez scalanie lub quick-sort.
Ćwiczenie [arytmetyka nieograniczonych liczb całkowitych]
Zaimplementuj pakiet arytmetyczny nieograniczonych liczb całkowitych.
Ćwiczenie [lista większościowa]
Ćwiczenie [trójki]
Napisz procedurę trójki:int list -> (int * int * int) list, która dla zadanej listy dodatnich liczb całkowitych, uporządkowanej rosnąco, stworzy listę takich trójek liczb z danej listy, że:
- ,
- liczby , i spełniają nierówność trójkąta, czyli .
Ćwiczenia na inne struktury danych:
Ćwiczenie [arytmetyka liczb wymiernych]
Zaimplementuj arytmetykę liczb wymiernych, reprezentując liczby wymierne jako rekordy złożone z licznika i mianownika. Implementacja może być uproszczona, np. bez skracania ułamków i bez normalizacji znaków.
Ćwiczenie [reprezentacja daty]
Zdefiniuj typ reprezentujący dni tygodnia, miesiące i datę.
Ćwiczenie [dzień tygodnia]
Zdefiniuj procedurę obliczającą na podstawie daty dzień tygodnia. Możesz założyć, że dana jest procedura sylwester, która na podstawie roku określa jakiego dnia tygodnia był Sylwester.
Ćwiczenie [słaby warunek BST]
Napisz procedurę, która dla dowolnego drzewa binarnego poprawia je tak, że spełnia ono słabszą wersję warunku BST: dla dowolnego węzła, lewy syn nie jest większy, a prawy nie jest mniejszy niż węzeł.
Ćwiczenie [wyważanie drzewa BST]
Napisz procedurę, która przekształca dane drzewo binarne w wyważone drzewo binarne, zachowując kolejność elementów w porządku infiksowym.
Ćwiczenie [zbiory jako drzewa BST]
Zaimplementuj takie operacje na zbiorach (reprezentowanych jako drzewa BST) jak suma, przecięcie i różnica.
Ćwiczenie [kolejki dwustronne]
Rozszerz implementację kolejek o wkładanie i wyjmowanie elementów z obydwu stron. Jaką własność powinna zachowywać procedura balance, aby koszt zamortyzowany operacji był stały?
Ćwiczenie [liczby naturalne]
type nat = ZERO | SUCC of nat;;
Zaimplementuj operacje arytmetyczne na takich liczbach.