Programowanie funkcyjne/Zadania egzaminacyjne: Różnice pomiędzy wersjami
Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Nie podano opisu zmian |
Nie podano opisu zmian |
||
(Nie pokazano 7 pośrednich wersji utworzonych przez tego samego użytkownika) | |||
Linia 1: | Linia 1: | ||
Propozycje zadań egzaminacyjnych: | Propozycje zadań egzaminacyjnych: | ||
* 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>.) | * 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>.) | ||
* 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. | * 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 \le j \le n</math>. Jaką złożoność ma Twoja procedura? | * 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 \le j \le n</math>. Jaką złożoność ma Twoja procedura? | ||
* Napisz procedurę <tt>przedziały:int list -> int*int</tt>, która dla danej listy <math>[a_1, \dots, a_n]</math> oblicza taką parę liczb <math>(k,l)</math>, <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. | * Napisz procedurę <tt>przedziały:int list -> int*int</tt>, która dla danej listy <math>[a_1, \dots, a_n]</math> oblicza taką parę liczb <math>(k,l)</math>, <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. | ||
* Napisz procedurę <tt>podział: int list -> int list list</tt>, która dla danej listy liczb całkowitych <math>l=[x_1; x_2; \dots; x_n]</math> podzieli ją na listę list <math>[l_1; \dots; l_k]</math>, przy czym: | |||
** <math>l = l_1 @ \dots @ l_k</math>, | |||
** każda z list <math>l_i</math> jest ściśle rosnąca, | |||
** <math>k</math> jest najmniejsze możliwe. | |||
:Przykład: | |||
podział [1;3;0;-2;-2;4;9] = [[1; 3]; [0]; [-2]; [-2;4;9]] | |||
: Rozwiązując to zadanie nie wolno Ci tworzyć żadnych własnych procedur rekurencyjnych, ani używać pętli. Powinieneś natomiast użyć standardowych procedur wyższych rzędów przetwarzających listy. | |||
* Napisz procedurę <tt>podział: int list -> int list list</tt>, która dla danej listy liczb całkowitych <math>l=[x_1; x_2; \dots; x_n]</math> podzieli ją na listę list <math>[l_1; \dots; l_k]</math>, przy czym: | |||
** <math>l = l_1 @ \dots @ l_k</math>, | |||
** dla każdej listy <math>l_i</math> wszystkie elementy na takiej liście są tego samego znaku, | |||
** <math>k</math> jest najmniejsze możliwe. | |||
: Przykład: | |||
podział [1;3;0;-2;-2;-4;9] = [[1; 3]; [0]; [-2;-2;-4]; [9]] | |||
: Rozwiązując to zadanie nie wolno Ci tworzyć żadnych własnych procedur rekurencyjnych, ani używać pętli. Powinieneś natomiast użyć standardowych procedur wyższych rzędów przetwarzających listy. | |||
* Napisz procedurę <tt>podziel: int list -> int list list</tt>, która dla danej listy <math>[a_1; a_2; \dots; a_n]</math> zawierającej permutację zbioru <math>\{1, 2, \dots, n\}</math> znajdzie jej podział na jak najliczniejszą listę list postaci: | |||
<center><math> | |||
[[a_1; a_2; \dots; a_{k_1}]; [a_{{k_1}+1}; a_{{k_1}+2}; \dots; a_{k_2}]; \dots; | |||
[a_{{k_{m-1}}+1}; a_{{k_{m-1}}+2}; \dots; a_{k_m}]] | |||
</math></center> | |||
: taką że: | |||
<center><math> | |||
\begin{matrix} | |||
\{a_1, a_2, \dots, a_{k_1}\} &=& | |||
\{1, 2, \dots, k_1\} & \mbox{(równość zbiorów)},\\ | |||
\{a_{{k_1}+1}, a_{{k_1}+2}, \dots, a_{k_2}\} &=& | |||
\{k_1+1, k_1+2, \dots, k_2\},\\ | |||
&\vdots& \\ | |||
\{a_{{k_{m-1}}+1}, a_{{k_{m-1}}+2}, \dots, a_{k_m}\} &=& | |||
\{k_{m-1}+1, k_{m-1}+2, \dots, k_m\} | |||
\end{matrix} | |||
</math></center> | |||
: Przyjmujemy, że wynikiem dla listy pustej jest lista pusta. | |||
: Przykład: | |||
podziel [2; 3; 1; 6; 5; 4; 7; 9; 10; 11; 8] = [[2; 3; 1]; [6; 5; 4]; [7]; [9; 10; 11; 8]] | |||
: Rozwiązując to zadanie powinieneś skorzystać z rekurencji, ale wolno Ci korzystać wyłącznie z rekurencji ogonowej. | |||
* Napisz procedurę <tt>buduj_permutacje: 'a list list -> 'a -> 'a</tt>, która przyjmuje permutację w postaci rozkładu na cykle i zwraca ją w postaci procedury. Lista składowa postaci <math>[a_1; \dots; a_n]</math>, gdzie <math>a_i \neq a_j</math> dla <math>1 \leq i < j \leq n</math>, reprezentuje cykl, czyli permutację przeprowadzającą <math>a_i</math> na <math>a_{(i \bmod n) + 1}</math> dla <math>1 \leq i \leq n</math>. Możesz założyć, że listy składowe są niepuste. | |||
: Lista list <math>[c_1; \dots; c_k]</math>, gdzie listy <math>c_i</math> dla <math>1 \leq i \leq k</math> reprezentują cykle, reprezentuje permutację złożoną z tych cykli. Możesz założyć, że wszystkie cykle są rozłączne. | |||
: Przyjmujemy, że dla wartości <math>x</math> nie występujących na żadnej z list <math>c_i</math> wynikiem <tt>buduj_permutacje</tt> <math>[c_0; \dots; c_k]\ x</math> jest <math>x</math>. W szczególności, przyjmujemy, że pusta lista reprezentuje permutację identycznościową. | |||
: Przykład: | |||
'''let''' p = buduj_permutacje [[2; 1]; [8; 3; 4]; [5; 7; 6; 10]; [11]];; | |||
map p [1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12];; | |||
''-: int list = [2; 1; 4; 8; 7; 10; 6; 3; 9; 5; 11; 12]'' | |||
* Dana jest lista liczb zmiennopozycyjnych <math>[x_1; x_2; \dots; x_n]</math>. Jej uśrednienie, to lista postaci: <math>[\frac{x_1 +. x_2}{2.0}; \dots; \frac{x_{n-1} +. x_n}{2.0}]</math>. Uśrednieniem listy jednoelementowej oraz pustej jest lista pusta. | |||
: Napisz procedurę <tt>usrednienie</tt>, która dla danej listy obliczy jej uśrednienie. Rozwiązując to zadanie nie możesz tworzyć procedur rekurencyjnych. Zamiast tego powinieneś skorzystać ze standardowych procedur wyższych rzędów przetwarzających listy. | |||
* Rozważmy następującą metodę kompresji ciągów liczb całkowitych: Jeżeli w oryginalnym ciągu ta sama liczba powtarza się kilka razy z rzędu, to jej kolejne wystąpienia reprezentujemy za pomocą jednej tylko liczby. Konkretnie, $i$ powtórzeń liczby $k$ reprezentujemy w ciągu skompresowanym jako <math>2^{i-1} \cdot (2 \cdot k - 1)</math>. | |||
: Napisz procedurę <tt>kompresuj: int list -> int list</tt> kompresującą zadaną listę. Lista wynikowa powinna być oczywiście jak najkrótsza. | |||
: Rozwiązując to zadanie nie wolno Ci tworzyć żadnych własnych procedur rekurencyjnych. Powinieneś natomiast użyć procedur wyższych rzędów przetwarzających listy, znanych z wykładów. | |||
: Przykład: | |||
kompresuj [1; 2; 2; 5; 11; 11; 2] = [1; 6; 9; 42; 3] | |||
* Zdefiniuj w sposób kontynuacyjny procedurę <tt>pierwsze: int -> (int -> 'a) -> 'a</tt>, która dla danej dodatniej liczby całkowitej oblicza sumę liczb pierwszych występujących w jej rozkładzie. Wszelkie procedury pomocnicze powinny również być zdefiniowane w sposób kontynuacyjny. | |||
* Napisz procedurę <tt>codrugi: 'a stream -> 'a stream</tt>, która przekształca strumień postaci <math>(s_1; s_2; s_3; s_4; \dots)</math> w strumień postaci <math>(s_1; s_3; s_5; \dots)</math>. Powinna ona działać zarówno dla strumieni skończonych, jak i nieskończonych. | |||
* Dany jest nieskończony strumień nieskończonych strumieni <math>s</math>. Zdefiniuj jego ,,przekątną'' <math>p</math>. | |||
* Zdefiniuj w sposób uwikłany strumień złożony z tych dodatnich liczb całkowitych, które w rozkładzie na czynniki pierwsze mają tylko liczby 2 i 3, oraz rozkładają się na nieparzystą liczbę czynników pierwszych. |
Aktualna wersja na dzień 18:07, 8 mar 2007
Propozycje zadań egzaminacyjnych:
- Napisz procedurę posumuj, która dla danej niemalejącej listy dodatnich liczb całkowitych oblicza listę , gdzie . (Pamiętaj o tym, że jeśli , .)
- 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ę słupki, 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ę max_diff : int list int, która dla niepustej listy znajdzie maksymalną różnicę dla . Jaką złożoność ma Twoja procedura?
- Napisz procedurę przedziały:int list -> int*int, która dla danej listy oblicza taką parę liczb , , dla której suma jest największa. Oblicz i podaj złożoność Twojego rozwiązania.
- Napisz procedurę podział: int list -> int list list, która dla danej listy liczb całkowitych podzieli ją na listę list , przy czym:
- Parser nie mógł rozpoznać (błąd składni): {\displaystyle l = l_1 @ \dots @ l_k} ,
- każda z list jest ściśle rosnąca,
- jest najmniejsze możliwe.
- Przykład:
podział [1;3;0;-2;-2;4;9] = [[1; 3]; [0]; [-2]; [-2;4;9]]
- Rozwiązując to zadanie nie wolno Ci tworzyć żadnych własnych procedur rekurencyjnych, ani używać pętli. Powinieneś natomiast użyć standardowych procedur wyższych rzędów przetwarzających listy.
- Napisz procedurę podział: int list -> int list list, która dla danej listy liczb całkowitych podzieli ją na listę list , przy czym:
- Parser nie mógł rozpoznać (błąd składni): {\displaystyle l = l_1 @ \dots @ l_k} ,
- dla każdej listy wszystkie elementy na takiej liście są tego samego znaku,
- jest najmniejsze możliwe.
- Przykład:
podział [1;3;0;-2;-2;-4;9] = [[1; 3]; [0]; [-2;-2;-4]; [9]]
- Rozwiązując to zadanie nie wolno Ci tworzyć żadnych własnych procedur rekurencyjnych, ani używać pętli. Powinieneś natomiast użyć standardowych procedur wyższych rzędów przetwarzających listy.
- Napisz procedurę podziel: int list -> int list list, która dla danej listy zawierającej permutację zbioru znajdzie jej podział na jak najliczniejszą listę list postaci:
- taką że:
- Przyjmujemy, że wynikiem dla listy pustej jest lista pusta.
- Przykład:
podziel [2; 3; 1; 6; 5; 4; 7; 9; 10; 11; 8] = [[2; 3; 1]; [6; 5; 4]; [7]; [9; 10; 11; 8]]
- Rozwiązując to zadanie powinieneś skorzystać z rekurencji, ale wolno Ci korzystać wyłącznie z rekurencji ogonowej.
- Napisz procedurę buduj_permutacje: 'a list list -> 'a -> 'a, która przyjmuje permutację w postaci rozkładu na cykle i zwraca ją w postaci procedury. Lista składowa postaci , gdzie dla , reprezentuje cykl, czyli permutację przeprowadzającą na dla . Możesz założyć, że listy składowe są niepuste.
- Lista list , gdzie listy dla reprezentują cykle, reprezentuje permutację złożoną z tych cykli. Możesz założyć, że wszystkie cykle są rozłączne.
- Przyjmujemy, że dla wartości nie występujących na żadnej z list wynikiem buduj_permutacje jest . W szczególności, przyjmujemy, że pusta lista reprezentuje permutację identycznościową.
- Przykład:
let p = buduj_permutacje [[2; 1]; [8; 3; 4]; [5; 7; 6; 10]; [11]];; map p [1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12];; -: int list = [2; 1; 4; 8; 7; 10; 6; 3; 9; 5; 11; 12]
- Dana jest lista liczb zmiennopozycyjnych . Jej uśrednienie, to lista postaci: . Uśrednieniem listy jednoelementowej oraz pustej jest lista pusta.
- Napisz procedurę usrednienie, która dla danej listy obliczy jej uśrednienie. Rozwiązując to zadanie nie możesz tworzyć procedur rekurencyjnych. Zamiast tego powinieneś skorzystać ze standardowych procedur wyższych rzędów przetwarzających listy.
- Rozważmy następującą metodę kompresji ciągów liczb całkowitych: Jeżeli w oryginalnym ciągu ta sama liczba powtarza się kilka razy z rzędu, to jej kolejne wystąpienia reprezentujemy za pomocą jednej tylko liczby. Konkretnie, $i$ powtórzeń liczby $k$ reprezentujemy w ciągu skompresowanym jako .
- Napisz procedurę kompresuj: int list -> int list kompresującą zadaną listę. Lista wynikowa powinna być oczywiście jak najkrótsza.
- Rozwiązując to zadanie nie wolno Ci tworzyć żadnych własnych procedur rekurencyjnych. Powinieneś natomiast użyć procedur wyższych rzędów przetwarzających listy, znanych z wykładów.
- Przykład:
kompresuj [1; 2; 2; 5; 11; 11; 2] = [1; 6; 9; 42; 3]
- Zdefiniuj w sposób kontynuacyjny procedurę pierwsze: int -> (int -> 'a) -> 'a, która dla danej dodatniej liczby całkowitej oblicza sumę liczb pierwszych występujących w jej rozkładzie. Wszelkie procedury pomocnicze powinny również być zdefiniowane w sposób kontynuacyjny.
- Napisz procedurę codrugi: 'a stream -> 'a stream, która przekształca strumień postaci w strumień postaci . Powinna ona działać zarówno dla strumieni skończonych, jak i nieskończonych.
- Dany jest nieskończony strumień nieskończonych strumieni . Zdefiniuj jego ,,przekątną .
- Zdefiniuj w sposób uwikłany strumień złożony z tych dodatnich liczb całkowitych, które w rozkładzie na czynniki pierwsze mają tylko liczby 2 i 3, oraz rozkładają się na nieparzystą liczbę czynników pierwszych.