Programowanie funkcyjne/Struktury danych/Ćwiczenia: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Kubica (dyskusja | edycje)
Nie podano opisu zmian
 
(Nie pokazano 29 wersji utworzonych przez 3 użytkowników)
Linia 1: Linia 1:
==Praca domowa==
== Praca domowa ==
* Napisz procedurę <tt>dubluj</tt>, która dubluje elementy listy. Na przykład, <tt>dubluj [1;2;3] = [1;1;2;2;3;3]</tt>.
* Napisz procedurę <tt>dubluj</tt>, która dubluje elementy listy, na przykład <tt>dubluj [1;2;3] = [1;1;2;2;3;3]</tt>.


==Ćwiczenia==
* 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 ==
{{cwiczenie|[<tt>rev</tt>]||
Zaimplementuj procedurę <tt>rev</tt> odwracającą listę. (Zwróć uwagę, że rozwiązując to zadanie można korzystać z <tt>::</tt> lub <tt>@</tt>, co daje liniową lub kwadratową złożoność czasową.)
}}
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie nieefektywne, ale proste</span>
<div class="mw-collapsible-content" style="display:none">
'''let rec''' rev l =
  '''match''' l '''with'''
    [] -> [] |
    h::t -> (rev t) @ [h];;
Ze względu na koszt operacji <tt>@</tt> to rozwiązanie ma złożoność czasową kwadratową.
</div></div>
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie efektywne</span>
<div class="mw-collapsible-content" style="display:none">
'''let''' rev l =
  '''let rec''' pom l w =
    '''match''' l '''with'''
      [] -> w |
      h::t -> pom t (h::w)
  '''in'''
    pom l [];;
</div></div>
 
{{cwiczenie|[Przeplot list]||
Napisz procedurę <tt>shuffle: α list → α list → α list</tt>, która dla danych dwóch list postaci <math>[x_1; x_2; \dots; x_n]</math> oraz <math>[y_1; y_2; \dots; y_m]</math> wyznaczy listę postaci <math>[x_1; y_1; x_2; y_2; \dots]</math>. 
Jeżeli jedna z list jest dłuższa, to jej końcowe elementy trafiają na koniec listy wyikowej.
Na przykład: <tt><nowiki>shuffle [3; 2; 8; 1; 9; 3; 6] [5; 7; 0] = [3; 5; 2; 7; 8; 0; 1; 9; 3; 6].</nowiki></tt>   
}}
 
 
{{cwiczenie|[<tt>flatten</tt>]||
Napisz procedurę <tt>flatten</tt> rozwijającą listę list do listy elementów.
Na przykład, <tt><nowiki>flatten [[1; 2]; []; [3; 4; 5]] = [1; 2; 3; 4; 5]</nowiki></tt>.
}}
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
'''let rec''' flatten l =
  '''match''' l '''with'''
    [] -> [] |
    h::t -> h @ flatten t;;
</div></div>
 
{{cwiczenie|[Średnica drzew]||}}
Dana jest definicja typu: <tt>type tree = Node of tree * tree | Leaf</tt>.
Odległością między dwoma wierzchołkami (<tt>Node</tt>) 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 (<tt>Node</tt>) w drzewie.
Przyjmujemy, że średnica pustego drzewa (<tt>Leaf</tt>) jest równa 0.
Napisz procedurę <tt>srednica: tree -> int</tt>, która oblicza średnicę danego drzewa.
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
Opieramy się na następującej obserwacji:
* Puste drzewo ma średnicę 0.
* Jeśli drzewo jest niepuste, to przez <math>t_1</math> i <math>t_2</math> oznaczmy dwa poddrzewa zakorzenione w lewym i prawym synie korzenia. Odpowiednio przez <math>d_1</math> i <math>d_2</math> oznaczmy średnice tych poddrzew, a przez <math>h_1</math> i <math>h_2</math> ich wysokości. Wówczas średnica całego drzewa wynosi <math>\max(d_1, d_2, h_1+h_2+2)</math>.
Dla każdego wierzchołka w drzewie obliczamy wysokość i średnicę drzewa zakorzenionego w tym wierzchołku.
Przyjmujemy przy tym, że drzewo puste ma średnicę 0 i wysokość -1.
 
let rec wys_sr t =
  match t with
    Leaf -> (-1,0) |
    Node (t1, t2) ->
      let (h1, d1) = wys_sr t1
      and (h2, d2) = wys_sr t2
      in (max h1 h2 + 1, max (max d1 d2) (h1+h2+2));;
let srednica t = snd (wys_sr t);;
</div></div>
 
{{cwiczenie|[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:
{{cwiczenie|[<math>n</math>-ty element listy]||
Zaimplementuj procedurę zwracającą <math>n</math>-ty element listy.
}}
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
  '''let rec''' nth l n =
    '''match''' l '''with'''
      h::t ->
        '''if''' n = 0 '''then''' h '''else''' nth t (n-1);;
</div></div>
 
{{cwiczenie|[Lista <math>[0;1;\dots;n]</math>]||
Napisz procedurę tworzącą listę <math>n</math> pierwszych liczb naturalnych.
}}
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
  '''let''' naturalne n =
    '''let rec''' pom k =
      '''if''' k >= n '''then''' [] '''else''' k :: pom (k+1)
    '''in''' pom 0;;
</div></div>
 
{{cwiczenie|[append]||
Zaimplementuj procedurę <tt>append</tt> sklejającą listy.
}}
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
  '''let rec''' append l1 l2 =
    '''match''' l1 '''with'''
      []  -> l2 |
      h::t -> h :: append t l2;;
</div></div>
 
{{cwiczenie|[ciąg różnicowy]||
Ciąg różnicowy ciągu <math>(x_1, \dots, x_n)</math> to ciąg postaci <math>(x_2-x_1,\dots,x_n-x_{n-1})</math>. Napisz procedurę obliczającą ciąg różnicowy żądanej listy liczb całkowitych.
}}
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
  '''let rec''' roznicowy l =
    '''match''' l '''with'''
      h1::(h2::_ '''as''' t) -> (h2-h1) :: roznicowy t |
      _                -> [];;
</div></div>
 
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie 2</span>
<div class="mw-collapsible-content" style="display:none">
  '''let''' roznicowy l =
    '''let rec''' pom a l =
      '''match''' l '''with'''
        h1::(h2::_ as t) -> pom ((h2-h1)::a) t |
        _                  -> rev a
    '''in''' pom [] l;;
</div></div>
 
{{cwiczenie|[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.
}}
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
  '''let rec''' roznicowe l =
    '''if''' l = [] '''then''' [[]] '''else''' l :: roznicowe (roznicowy l);;
</div></div>
 
{{cwiczenie|[minimum-maksimum]||
Napisz procedurę, której wynikiem jest para: minimum i maksimum elementów z listy. Procedura ta powinna wykonywać co najwyżej <math>\frac{3}{2} n</math> porównań.
}}
 
{{cwiczenie|[<tt>last</tt>]||
Napisz procedurę <tt>last</tt>, której wynikiem jest ostatni element (niepustej) listy.
}}
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
  '''let rec''' last (h::t) =
    '''if''' t = [] '''then''' h '''else''' last t;;
</div></div>
 
{{cwiczenie|[<tt>head</tt> i <tt>tail</tt>]||
Napisz procedury <tt>head</tt> i <tt>tail</tt>, które dla zadanej listy <math>l</math> i liczby całkowitej <math>n</math> zwracają pierwsze/ostatnie <math>n</math> elementów listy <math>l</math>. Jeśli lista <math>l</math> ma mniej elementów niż <math>n</math>, to wynikiem powinna być cała lista <math>l</math>. (Nazwy pochodzą od programów <tt>head</tt> i <tt>tail</tt> w Uniksie.) Co jest wynikiem <tt>tail (head l n) 1</tt>?}}
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
  '''let''' head l n =
    '''let rec''' head_pom l n a =
      '''if''' (n = 0) || (l = []) '''then'''
        rev a
      '''else'''
        head_pom (tl l) (n-1) ((hd l)::a)
    '''in''' head_pom l n [];;
 
  '''let''' tail l n =
    '''let rec''' skip l k =
      '''if''' k = 0 '''then''' l '''else''' skip (tl l) (k-1)
    '''in'''
      skip l (max (length l - n) 0);; 
</div></div>
 
{{cwiczenie|[sortowanie]||
Zaimplementuj sortowanie: przez scalanie lub quick-sort.
}}
 
{{cwiczenie|[arytmetyka nieograniczonych liczb całkowitych]||
Zaimplementuj pakiet arytmetyczny nieograniczonych liczb całkowitych.
}}
 
{{cwiczenie|[lista większościowa]||
Lista większościowa to taka lista, na której ponad połowa elementów jest sobie równa, a ich wartość nazywa się właśnie większością. Napisz procedurę wybierającą większość z listy większościowej; uzasadnij jej poprawność.}}
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">
  '''let''' majority l =
    '''let rec''' scan c k l =
      '''match''' l '''with'''
        [] -> c |
        h::t ->
          '''if''' k = 0 '''then''' scan h 1 t
          '''else if''' c = h '''then''' scan c (k+1) t
          '''else''' scan c (k-1) t
  '''in''' scan (hd l) 0 l;;
</div></div>
 
{{cwiczenie|[trójki]||
Napisz procedurę <tt>trójki:int list -> (int * int * int) list</tt>, która dla zadanej listy dodatnich liczb całkowitych, uporządkowanej rosnąco, stworzy listę takich trójek <math>(a, b, c)</math> liczb z danej listy, że:
* <math>a < b < c</math>,
* liczby <math>a</math>, <math>b</math> i <math>c</math> spełniają nierówność trójkąta, czyli <math>c < a + b</math>.
}}


Ćwiczenie programistyczne na listy:
* <math>N</math>-ty element listy.
* Lista <math>n</math> pierwszych liczb naturalnych.
* Odwrócenie listy <tt>rev</tt>. Wersje o liniowej (z <tt>::</tt>) i kwadratowej (z <tt>@</tt>) złożoności czasowej. Porównać je.
* Sklejanie list <tt>append</tt>. Obliczenie ciągu różnicowego zadanej listy liczb całkowitych.
* Obliczenie listy kolejnych ciągów różnicowych zadanej listy liczb całkowitych.
* Napisz procedurę, której wynikiem jest para: minimum i maksimum elementów z listy. Procedura ta powinna wykonywać jak najmniej porównań (ale bez przeginania).


Ćwiczenia na inne struktury danych:
Ćwiczenia na inne struktury danych:
* Zdefiniuj typ reprezentujący drzewa o wierzchołkach dowolnego (skończonego stopnia).
{{cwiczenie|[arytmetyka liczb wymiernych]||
* Zdefiniuj trochę procedur operujących na takich drzewach.  
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.
* Zdefiniuj typ reprezentujący dni tygodnia, miesiące i datę.  
}}
* Zdefiniuj procedurę obliczającą na podstawie daty dzień tygodnia. Możesz założyć, że dana jest procedura <tt>sylwester</tt>, która na podstawie roku określa jakiego dnia tygodnia był Sylwester.


Proste ćwiczenia na listy. Można je wykonywać w dwóch wariantach: korzystając ze wzorców, lub z procedur <tt>hd</tt>, <tt>tl</tt> i (zdefiniowanej samemu) <tt>null</tt>.
{{cwiczenie|[reprezentacja daty]||
* Rozwinięcie listy list do listy (<tt>flatten</tt>).
Zdefiniuj typ reprezentujący dni tygodnia, miesiące i datę.  
* Napisz procedurę <tt>last</tt>, której wynikiem jest ostatni element listy.
}}
* Napisz procedury <tt>head</tt> i <tt>tail</tt>, które dla zadanej listy <math>l</math> i liczby całkowitej <math>n</math> zwracają pierwsze/ostatnie <math>n</math> elementów listy <math>l</math>. Jeśli lista <math>l</math> ma mniej elementów niż <math>n</math>, to wynikiem powinna być cała lista <math>l</math>. (Nazwy pochodzą od programów <tt>head</tt> i <tt>tail</tt> w Uniksie.) Co jest wynikiem <tt>tail (head l n) 1</tt>?
* Napisz procedurę <tt>posumuj</tt>, która dla danej niemalejącej listy dodatnich liczb całkowitych <math>(a_1 \dots a_n)</math> oblicza listę <math>(b_1 \dots b_n)</math>, gdzie <math>b_i = \sum_{k=a_i}^n a_k</math>. (Pamiętaj o tym, że jeśli <math>m>n</math>, <math>\sum_{k=m}^n a_k = 0</math>.)
* Zaimplementuj sortowanie: przez scalanie lub quick-sort.
* Zaimplementuj pakiet arytmetyczny nieograniczonych liczb całkowitych.
* Napisz program wybierający większość z listy większościowej; uzasadnij jego poprawność. Uwaga: to zadanie można rozwiązać probabilistycznie: metodą Las Vegas: wylosuj element i sprawdź czy to większość; policz oczekiwaną złożoność,
* Tomek ma zabawkę, z której wystają drewniane słupki różnej wysokości. Jednym uderzeniem młotka może wbić lub wysunąć wybrany słupek o 1. Napisz procedurę <tt>słupki</tt>, która dla danej listy początkowych wysokości słupków obliczy minimalną liczbę uderzeń młotka potrzebnych do wyrównania wysokości słupków. Napisz funkcję <tt>max_diff : int list <math>\to</math> int</tt>, która dla niepustej listy <math>[x_1; \dots; x_n]</math> znajdzie maksymalną różnicę <math>x_j - x_i</math> dla <math>1 \le i < j \le n</math>. Jaką złożoność ma Twój program.
* Napisz funkcję <tt>trójki:int list <math>\to</math> (int * int * int) list</tt>, która dla zadanej listy dodatnich liczb całkowitych, uporządkowanej rosnąco, stworzy listę takich trójek <math>(a, b, c)</math> liczb z danej listy, że:
** <math>a < b < c</math>,
** liczby <math>a</math>, <math>b</math> i <math>c</math> spełniają nierówność trójkąta, czyli <math>c < a + b</math>.
* Zdefiniuj taką funkcję <tt>przedziały:int list <math>\to</math> int*int</tt>, że <tt>przedzialy</tt><math>\ [a_1, \dots, a_n] = (k,l)</math>, gdzie jest to taka para liczb <math>1 \le k \le l \le n</math>, dla której suma <math>a_k + \cdots + a_l</math> jest największa. Oblicz i podaj złożoność Twojego rozwiązania (jako funkcję <math>n</math>).


Ćwiczenia na inne struktury danych:
{{cwiczenie|[dzień tygodnia]||
* Napisz całe mnóstwo procedur operujących na drzewach. Mogą to być znane Ci operacje dotyczące drzew, lub odpowiedniki operacji na listach.  
Zdefiniuj procedurę obliczającą na podstawie daty dzień tygodnia. Możesz założyć, że dana jest procedura <tt>sylwester</tt>, która na podstawie roku określa jakiego dnia tygodnia był Sylwester.
* 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ł.  
}}
* Napisz procedurę, która przekształca dane drzewo binarne w wyważone drzewo binarne, zachowując kolejność elementów w porządku infiksowym.  
 
* Zaimplementować 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 (jeśli czasu mało).
{{cwiczenie|[słaby warunek BST]||
* Rozszerzyć implementację kolejek o wkładanie i wyjmowanie elementów z obydwu stron.
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ł.  
* Dany jest typ danych reprezentujący (mało efektywnie) liczby naturalne:  <tt>type nat = ZERO | SUCC of nat;;</tt>. Zaimplementuj operacje arytmetyczne na takich liczbach.
}}
* Zaimplementuj takie operacje na zbiorach, jak suma, przecięcie, różnica.
 
* Zadeklaruj typ danych reprezentujący abstrakcyjną składnię wyrażeń arytmetycznych. Napisz procedurę obliczającą wartość wyrażenia.
{{cwiczenie|[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.  
}}
 
{{cwiczenie|[zbiory jako drzewa BST]||
Zaimplementuj takie operacje na zbiorach (reprezentowanych jako drzewa BST) jak suma, przecięcie i różnica.
}}
 
{{cwiczenie|[kolejki dwustronne]||
Rozszerz implementację kolejek o wkładanie i wyjmowanie elementów z obydwu stron. Jaką własność powinna zachowywać procedura <tt>balance</tt>, aby koszt zamortyzowany operacji był stały?
}}
 
{{cwiczenie|[liczby naturalne]||
Dany jest typ danych reprezentujący (mało efektywnie) liczby naturalne:}}  
  '''type''' nat = ZERO | SUCC of nat;;
Zaimplementuj operacje arytmetyczne na takich liczbach.

Aktualna wersja na dzień 13:57, 1 cze 2020

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 [x1;x2;;xn] oraz [y1;y2;;ym] wyznaczy listę postaci [x1;y1;x2;y2;]. 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 [n-ty element listy]

Zaimplementuj procedurę zwracającą n-ty element listy.

Rozwiązanie

Ćwiczenie [Lista [0;1;;n]]

Napisz procedurę tworzącą listę n 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 (x1,,xn) to ciąg postaci (x2x1,,xnxn1). 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 32n porównań.

Ćwiczenie [last]

Napisz procedurę last, której wynikiem jest ostatni element (niepustej) listy.

Rozwiązanie

Ćwiczenie [head i tail]

Napisz procedury head i tail, które dla zadanej listy l i liczby całkowitej n zwracają pierwsze/ostatnie n elementów listy l. Jeśli lista l ma mniej elementów niż n, to wynikiem powinna być cała lista l. (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]

Lista większościowa to taka lista, na której ponad połowa elementów jest sobie równa, a ich wartość nazywa się właśnie większością. Napisz procedurę wybierającą większość z listy większościowej; uzasadnij jej poprawność.

Rozwiązanie

Ć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 (a,b,c) liczb z danej listy, że:

  • a<b<c,
  • liczby a, b i c spełniają nierówność trójkąta, czyli c<a+b.


Ć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]

Dany jest typ danych reprezentujący (mało efektywnie) liczby naturalne:
 type nat = ZERO | SUCC of nat;;

Zaimplementuj operacje arytmetyczne na takich liczbach.