Część zajęć będzie się odbywać w laboratorium komputerowym, pozostałe będą prowadzone w trybie "tablicowym".
W laboratorium będziemy pracowali w systemie Linux. Programy będziemy pisać w języku C. Ze względu na prawie stuprocentową przenośność kodu w języku C, można będzie testować tworzone w LABie programy w innych środowiskach programistycznych, takich, jak popularne w systemie Windows środowiska Microsoft Visual Studio lub Clang.
W tym tygodniu będzie dodatkowe kolokwium dla osoby, która ma usprawiedliwioną nieobecność na grudniowym "kolokwium dla wszystkich". Będzie to także kolokwium ostatniej szansy na zaliczenie ćwiczeń dla osób, którym (choć przykładali się do nauki w trakcie semestru) grozi sytuacja przeciwna. Termin tego kolokwium ustalimy na najbliższych zajęciach.
Najbliższe zajęcia odbędą się nie w laboratorium komputerowym, tylko w sali.
Pisząc programy, zachowujcie Państwo ich czytelną strukturę i dodawajcie wyraziste komentarze - co prawda kompilatorowi jest obojętne, jak zapisujecie program (byleby tylko syntax był poprawny) - ale za to Wam będzie znacznie wygodniej je czytać, sprawdzać, analizować...
Polecana lektura na jesienne weekendy: B.Kernighan, D.Ritchie Język ANSI C, WNT. (dzieło popularnie zwane krótko "K&R").
Arytmetyka zmiennoprzecinkowa.
To jeszcze nie jest ostateczna wersja pracy domowej.
QuickSort i jego koszt w niektórych przypadkach skrajnych. Procedura Partition
. Stabilizacja sortowania.
To jeszcze nie jest ostateczna wersja pracy domowej.
MergeSort. Implementacja i koszt. Zastosowania sortowania w innych zadaniach. Wyszukiwanie lidera kosztem O(n log(n)).
HeapSort i jego implementacja
DownHeap
w wersji rekurencyjnej (implementacja).
Zastanawiałem się, czy pod choinkę nie podarować Państwu większej liczby zadań ;-) ale ostatecznie zostałem przy typowym zestawie.
Rozwiązania zadań 2 i 3 (kody źródłowe i pliki textowe z wynikami) należy przesłać mailem w/g standardowych reguł (przypominam o dobrych komentarzach!) do środy, 07.01.09. do godz. 9:00. Zadanie 1 nie będzie osobno oceniane (jest elementem rozwiązania zadania 2.)
DownHeap
tak, by procedura wskazywania elementu do zamiany była mniej skomplikowana.
HeapSort
sortowania tablicy n liczb rzeczywistych. Wynikiem funkcji ma być liczba wszystkich wykonanych porównań elementów tablicy, jakie wystąpiły w trakcie procesu sortowania. Następnie opracuj program, który dla n=2k, gdzie k=2..12, wyznacza stosunek liczby wszystkich wykonanych porównań (zwracanej przez funkcję HeapSort
) do n log(n), w 3 przypadkach, gdy dane w tablicy:
Wynikiem działania programu powinna być tabelka o 3 kolumnach i 11 wierszach. Uwaga: wszystko wymaga testowania, także Twoja implementacja HeapSort
a. Aby więc Twój program (przy okazji głównego zadania) dodatkowo testował poprawność implementacji, zmuś go, by po każdym wywołaniu HeapSort
sprawdzał, czy tablica faktycznie została posortowana. To znaczy, że musisz opracować jeszcze jedną dodatkową funkcję IsSorted
, która sprawdza, czy dana tablica jest faktycznie posortowana rosnąco, czy nie.
HeapSort
zamienionym na QuickSort
. W implementacji postępuj według idei z wykładu. Pamiętaj, aby nie przepisywać wprost kodu ze skryptu, Twój QuickSort
ma po prostu posortować rosnąco elementy tablicy.
Kopce i ich własności.
Zadanie o fladze polskiej (wersja z dodatkową tablicą i wersja bez dodatkowej tablicy (in situ), ta druga nieoptymalna).
Porównanie wersji z buforem tablicowym (w istocie korzystaliście Państwo z niego jak ze stosu) i wersji rekurencyjnej (a więc w istocie: ze stosem) programu wypisującego liczbę w systemie o zadanej podstawie.
strcmp
oraz strcpy
. strncmp
oraz strncpy
i dodaj taką funkcjonalność do poprzednio opracowanych funkcji.O stringach i funkcjach na nich działających.
strcpy
(kopiowanie), strcmp
(porównywanie), strlen
(długość), sprintf
(formatowana konwersja do stringa), itd...
Analiza algorytmu potęgowania z wykładnikiem naturalnym (poprawność, koszt, operacja dominująca).
Nie ma pracy domowej.
Przekierowanie stdin i stdout: ./program < wejscie.txt > wyjscie.txt
Pierwsza dygresja o wskaźnikach: co, jak i po co. Pliki tekstowe w C:
fopen
, fclose
fprintf
, fscanf
getc
, putc
, EOF
, do samodzielnego przyswojenia: getchar
, putchar
. Uwaga: funkcja getc
zwraca wynik typu int
, tzn. jej prototyp to: int getc(FILE *fp)
(na zajęciach błędnie podałem Państwu, że wyniki getc
są typu char
)
Pierwsze zadanie oddajemy na kartkach, dwa ostatnie - wysyłamy kod źródłowy e-mailem. Zasady te same, co zwykle.
Podaj bazę do konwersji: 2 Podaj liczbę do konwersji: 12 (12)_10 = (1100)_2 Podaj bazę do konwersji: 3 Podaj liczbę do konwersji: 12 (12)_10 = (110)_3
Twierdzenie o rekurencji uniwersalnej dla T(n) = a T(n/b) + f(n).
Rozwiązania zadań należy zapisać na kartkach i oddać na następnych ćwiczeniach.
Rekurencja, cd. Koszty różnych algorytmów cd.
Pierwsze zadanie - do oddania na kartkach. Rozwiązania dwóch ostatnich zadań należy przesłać na mój adres email, piotr.krzyzanowski@mimuw.edu.pl, do najbliższej środy, do godz. 9:00 (decyduje chwila dotarcia wiadomości do mojej skrzynki pocztowej). Uwagi wstępne:
A oto właściwa praca domowa.
1 10 15 20 25 16 19 24 9 14 11 2 17 6 21 18 23 4 13 8 3 12 7 22 5Warianty dla chętnych (poza konkursem):
o współczynnikach rzeczywistych, oparty na idei, że
Argumentami tej funkcji mają być: tablica współczynników wielomianu, stopień wielomianu n oraz wartość x. Wynikiem działania funkcji ma być oczywiście wartość wf(x) wielomianu w punkcie x.
Porównaj koszt tego algorytmu z kosztem algorytmu opracowanego na ćwiczeniach (uwzględniając tylko operacje arytmetyczne na zmiennych typu "rzeczywistego") - wynik porównania zamieść w komentarzu w pliku źródłowym.
Dobrze napisanej funkcji powinien towarzyszyć mały program testujący, zatem zamieść taki program testujący w swoim rozwiązaniu zadania o algorytmie Hornera. Robimy to tak: powiedzmy, że chcemy w pliku c7-silnia.c zapisać funkcję unsigned int silnia(unsigned int n)
. Jej implementacja mogłaby wyglądać następująco:
unsigned int silnia(unsigned int n)
{
int s = 1; /* zwracana wartość silni */
int i;
/* implementacja nierekurencyjna */
for(i = 2; i < n; i++)
s *= i;
return(s);
}
Ponieważ nie wiemy z góry, czy nie popełniliśmy jakiegoś drobnego błędu w implementacji (akurat powyżej popełniliśmy błąd! - wykonanie testu od razu go wychwyci!), warto mieć możliwość uruchomienia prostego programu, któryby testował działanie naszej funkcji- na przykład, wypisując pierwszych kilka wartości. W tym celu do pliku źródłowego dołąćczymy warunkowo małą funkcję main()
, która zostanie skompilowana tylko wtedy, gdy będzie zdefiniowana stała DEBUG
:
unsigned int silnia(unsigned int n)
{
int s = 1; /* zwracana wartość silni */
int i;
/* implementacja nierekurencyjna */
for(i = 2; i < n; i++)
s *= i;
return(s);
}
#ifdef DEBUG
/*
skompiluj
gcc -DDEBUG -o c7-silnia c7-silnia.c,
aby wygenerować program testujący funkcję silnia()
*/
#include <stdio.h>
int main(void)
{
int k;
printf("Test funkcji silnia():\n");
for(k=0; k <= 10; k++)
printf("\t%2d! = %d\n",k,silnia(k));
return(0);
}
#endif
Teraz, mogę skompilować tylko samą funkcję:
gcc -c c7-silnia.c
(wynik kompilacji znjadzie się w pliku c7-silnia.o), ale mogę też skompilować i funkcję, i towarzyszący jej program testujący, a następnie uruchomić go:
gcc -DDEBUG -o c7-silnia c7-silnia.c ./c7-silnia
Rekurencja.
Zadana na ćwiczeniach.
Programy proszę przysłać wg standardowych zasad, zadanie tekstowe oddajemy na kartkach na początku zajęć.
Dalsze programy w języku C.
int fibonacci(int n)
i wykorzystaj ją w programie do wypisania pierwszych K wyrazów ciągu Fibonacciego.
int
. Listę dostępnych typów całkowitych można przejrzeć na Wikipedii. Najszerszym dostępnym dla nas typem będzie unsigned long long int
.
time ./test
. Aby dowiedzieć się więcej o poleceniu time
, wystarczy wpisać w terminalu: man time.
int silnia(int n)
. Porównaj ich działanie w sposób podobny jak dla liczb Fibonacciego.
double wyrazexp(double x, int n)
, obliczającą tym razem n-ty wyraz ciągu (xn/n!).
Rozwiązania, dwóch pierwszych zadań - zestaw liczb, o których w nich mowa - należy przesłać na mój adres email, piotr.krzyzanowski@mimuw.edu.pl, do najbliższej środy, do godz. 9:00 (decyduje chwila dotarcia wiadomości do mojej skrzynki pocztowej). Uwagi wstępne:
A oto właściwa praca domowa. Z pewnych powodów, które zbyt długo by tutaj omawiać, pracę domową należy wykonywać wyłącznie na komputerach w studenckim labie!
double wyrazexp(double x, int n)
opisanej w zestawie zadań ćwiczeniowych, oblicz jej wartość dla x=200, n=1000 (tzn. policz, ile to jest xn/n! dla zadanych wartości parametrów). Ponadto sprawdź, dla jakiego n, wartość tej funkcji jest mniejsza od 1/2 (przy ustalonym x=200). Rozwiązaniem są dwie liczby szukane w zadaniu.
Aby drukować liczbę x
typu double
, użyj polecenia w stylu
printf("Liczba x = %e \n", x);
(formatka, której używaliśmy dla typu float
, tzn: printf("Liczba x = %f \n", x);
będzie dawała błędne wyniki dla zmiennych typu double
.
Dalsze programy w języku C.
float
?
float
. Następnie dodatkowo zrób jego wersję dla tablicy liczb typu całkowitego. Przydatne funkcje: sqrt
, znajduje się ona w bibliotece matematycznej. Prototyp sqrt
znajduje się w pliku nagłówkowym: #include <math.h>
. Kompilacja: gcc -o srednie srednie.c -lm
(dyrektywa -lm
dołącza z biblioteki matematycznej funkcje niezbędne w tym programie)
rand
, znajduje się ona w bibliotece standardowej. Dodatkowo stała RAND_MAX
. Prototyp rand
oraz definicja RAND_MAX
znajdują się w pliku nagłówkowym #include <math.h>
. Zastosuj tę procedurę w programie liczącym średnie! Pamiętaj o utworzeniu i wykorzystaniu stosownego pliku nagłówkowego. Kompilacja: gcc -o srednie srednie.c tablicelosowe.c -lm
.
Programy, o których mowa w dwóch pierwszych zadaniach - ich kody źródłowe w języku C, a nie pliki wykonywalne - należy przesłać na mój adres email, piotr.krzyzanowski@mimuw.edu.pl, do najbliższej środy, do godz. 9:00 (decyduje chwila dotarcia wiadomości do mojej skrzynki pocztowej). Uwagi wstępne:
A oto właściwa praca domowa:
Przykład dla N=4:
******************************************************************* * Program wskazuje pola szachowane przez Wieżę na szachownicy 4x4 * ******************************************************************* Podaj wiersz i kolumnę, w której ma być Wieża: 3 2 Oto pola szachowane: 1 2 3 4 1 + 1 2 + 2 3 + + + + 3 4 + 4 1 2 3 4
W przypadku podania pozycji poza szachownicą (np. "0 20") program ma drukować pustą szachownicę i komunikat o błędzie.
W programie trzeba będzie sprawdzać spełnienie kilku warunków. Do tego mamy operatory &&
(logiczne "AND") oraz ||
(logiczne "OR"). Jak ich używać, widzieliśmy w programie o latach przestępnych, dobrze też sprawdzić w K&R.
Część nieobowiązkowa. Choć nie będzie to dodatkowo punktowane, osoby chętne mogą następująco upiększyć swój program:
float
rozmiaru N, liczby dodatnie, ujemne i równe zero. Testuj tak, jak robiliśmy to dla średnich, zadając gotową tablicę wprost w kodzie źródłowym.
Dalsze programy w języku C.
Parę dodatkowych komend Unixa.
cp readme.txt kopia.txt
(kopiuje plik readme.txt do kopia.txt, ang. copy),
mv readme.txt czytajto.txt
(zmienia nazwę pliku readme.txt na czytajto.txt, czyli przenosi plik, ang. move),
mv WDI WstepDoInformatyki
(zmienia nazwę katalogu WDI na WstepDoInformatyki),
Programy, o których mowa w dwóch pierwszych zadaniach - ich kody źródłowe w języku C, a nie pliki wykonywalne - należy przesłać na mój adres email, piotr.krzyzanowski@mimuw.edu.pl, do najbliższej środy, do godz. 9:00 (decyduje chwila dotarcia wiadomości do mojej skrzynki pocztowej).
%
.
43 120 1komputer ma wypisać:
Podane liczby uporzadkowane malejaco: 120, 43, 1.Zobacz przykładowe rozwiązanie!
Pierwsze programy w języku C: wypisywanie tekstów i liczb na ekran, wczytywanie liczb, pętle, sumowanie. Zobacz: teksty programów.
Kompilacja programu.
gcc -o pierwszy pierwszy.c
(kompiluje kod źródłowy znajdujący się w pliku pierwszy.c do programu o nazwie pierwszy),
./pierwszy
(uruchamia program o nazwie pierwszy, znajdujący się w bieżącym katalogu)
Reakcja na błędy kompilatora.
Parę dodatkowych komend Unixa.
kate &
(dodanie znaku & po nazwie polecenia, uruchamia to polecenie (tutaj: kate) w tle, nie blokując w ten sposób terminala),
ps
(lista uruchomionych procesów),
kill -9 8790
(niszczy proces o numerze 8790 - numer znamy dzięki poleceniu ps
),
Wprowadzenie do systemu Linux. Logowanie i wylogowywanie się (System -> Wyloguj...). System okienkowy, podstawowe aplikacje, niektóre możliwości zmiany ustawień.
Edytory plików tekstowych: Gedit, Kate, Nedit (okienkowe, wygodne, dla każdego); joe, vi, emacs (pracujące w trybie tekstowym, zwykle trudniejsze w użyciu dla nieoswojonych - ale szalenie elastyczne i "szybkie" dla tych, którzy się przyzwyczają). Edycja i zapis pliku tekstowego.
Terminal. Podstawowe komendy Unixa (wydawane w terminalu), w tym:
mkdir WDI
(utworzenie katalogu WDI w katalogu bieżącym, ang. make directory),
ls WDI
(wyświetla zawartość katalogu WDI: pliki i podkatalogi, ang. list),
ls -l WDI
(wyświetla okraszoną szczegółowymi informacjami zawartość katalogu WDI: pliki i podkatalogi),
ls -halt WDI
(wyświetla posortowaną względem czasu utworzenia (opcja -t
, ang. time), a także okraszoną innymi szczegółami (opcja -l
, ang. long) pełną (opcja -a
, ang. all) zawartość katalogu WDI: pliki (także "ukryte") i podkatalogi; opcja -h
, ang. human, wyświetla "przyjazne człowiekowi" rozmiary plików: w zależności od potrzeby w kilo-, mega- i gigabajtach; jak widać opcje można łączyć ze sobą),
cd WDI
(przejście do katalogu WDI, ang. change directory),
man ls
(wyświetla strony manuala dotyczące polecenia (tutaj: ls); wyświetlanie przerywamy klawiszem q, ang. manual),
pwd
(sprawdzenie, w jakim katalogu jesteśmy - podaje pełną ścieżkę do katalogu bieżącego, ang. print working directory),
cd ..
(przejście do katalogu "piętro wyżej"),
more readme.txt
(wyświetla zawartość pliku tekstowego readme.txt; wyświetlanie przerywamy klawiszem q),
ls *.txt
(wypisuje wszystkie pliki kończące się na .txt),
rm readme.txt
(usuwa nieodwracalnie plik readme.txt, ang. remove),
rmdir WDI
(usunięcie katalogu WDI, o ile jest pusty),
rm *
(usuwa nieodwracalnie wszystkie pliki z bieżącego katalogu),
rm -rf *
(usuwa nieodwracalnie wszystkie pliki i podkatalogi z bieżącego katalogu),
Polecana literatura dotycząca środowiska, którego będziemy używać: wykład Środowisko programisty (pierwsze dwa moduły: Wprowadzenie do Basha
oraz (zwłaszcza!) Bash - podstawowe komendy). Dodatkowa literatura dotycząca systemu Unix: Silvester, Unix, WNT (nieco trąci myszką). Ponadto, całkiem sensowne omówienia na Wikipedii: Unix, polecenia Unixa. Warto także pamiętać o poleceniu man
, które wyświetla kompletny (chociaż trochę techniczny) opis działania każdego polecenia Unixa, np. man rm
poda szczegółowy opis działania polecenia rm
. Osoby żądne mocniejszych wrażeń mogą spróbować pinfo coreutils
.
Dalsze techniczne informacje o tym, jak korzystać z dobrodziejstw tutejszego LABu, można uzyskać w serwsie internetowym lk.mimuw.edu.pl, lub od (starszych?) koleżanek/kolegów, lub od osoby z "akwarium" przy wejściu.
Podstawy zostały sformułowane na pierwszym wykładzie. Na ocenę z ćwiczeń składają się:
Kartkówki będą mini-zadaniami na tematy różne. Może to być jakieś zadanie do rozwiązania na kartce, sprawdzenie znajomości zagadnień z wykładu, czy też zaprogramowanie czegoś małego przy komputerze.
Prace domowe będą zadawane z tygodnia na tydzień. Po terminie prace nie będą sprawdzane.
Za każde zadanie z pracy domowej można otrzymać maksymalnie 3 punkty. Za każde zadanie z kartkówki można dostać maksymalnie 1 punkt. Program zaliczeniowy będzie oceniany w skali 10-punktowej. Suma uzyskanych punktów z prac domowych i kartkówek zostanie na koniec semestru znormalizowana tak, by 100% punktów było równe maksimum punktów do uzyskania z kolokwium; tak samo zostanie znormalizowana ocena z programu zaliczeniowego.
Ostateczna liczba punktów uzyskanych z ćwiczeń będzie wyliczona według wzoru P = 0.3*D + 0.3*Z + 0.4*K, gdzie D - znormalizowana suma punktów z prac domowych i kartkówek, Z - znormalizowana suma punktów z programu zaliczeniowego, K - znormalizowana suma punktów z kolokwium.
Zapoznaj się z programem zaliczeniowym.
Wykładowca, P. Kiciak, udostępnia na swojej stronie WWW notatki do wykładu. Warto na bieżąco je śledzić!