Za zgodą Dziekana WMP.SNŚ w najbliższy czwartek, 14 grudnia, wykład ZTP od godz. 16:45 do 18:15 odbędzie się w trybie zdalnym na platformie MS Teams. Aby uczestniczyć w wykładzie należy dołączyć do zespołu WM-I-S1-E3-ZTP_2023/24_Z_WYK_GR1 korzystając z kodu: yv04q5s
Archiwa kategorii: Zaawansowane Techniki Programowania 2023
ZTP2023: Zadania przed lab.6
Zadania, które dotyczą zakresu materiału, jaki będzie poruszany na lab. 6. Rozwiązanie nie jest wymagane. Zadania stanowią wyłącznie pomoc w przygotowaniu się do zajęć.
Zadanie #1:
Przyjmij, że A, B, C i D reprezentują punkty w przestrzeni n-wymiarowej. Punkty te są reprezentowane w programie przez wektory współrzędnych. Wektor A zawiera dla każdej współrzędnej uzyskaną niezależnie wartość losową z generatora liczb o rozkładzie jednostajnym z przedziału [-10,10]. Wektor B zawiera wartości stałe [1,..,1].
Pobierz od użytkownika liczbę wymiarów przestrzeni n, utwórz odpowiednich rozmiarów wektory, przy czym zainicjuj też odpowiednio A i B, a następnie napisz kod wykonujący kolejno następujące obliczenia:
- D = A*B
- C = 3*B + D
- D = 3*(A+C)-(A*B)
gdzie operator '*’ oznacza mnożenie, przy czym kiedy argumentami są skalar i wektor, następuje przemnożenie wszystkich współrzędnych wektora przez skalar, natomiast w przypadku, kiedy argumentami są dwa wektory, jest to iloczyn Hadamarda (zobacz: https://pl.wikipedia.org/wiki/Mnożenie_macierzy). Sprawdź na danych testowych, czy obliczenia wykonują się poprawnie.
Uwaga – ograniczenie: do zaimplementowania w/w operacji nie wykorzystuj żadnych pętli (for, while, repeat
), a wyłącznie algorytmy STL i obiekty funkcyjne (własne lub biblioteczne). Jeżeli to potrzebne, rozłóż operacje na pojedyncze kroki, których wynik zapamiętuj w wektorach pomocniczych.
Zadanie #2:
W celu wygenerowania punktu na powierzchni hipersfery (zobacz: https://pl.wikipedia.org/wiki/Hipersfera) z centrum w środku układu współrzędnych należy wykonać następujące kroki:
- wygenerować wektor Z, którego każda współrzędna jest uzyskaną niezależnie wartością losową z generatora liczb o rozkładzie normalnym. Liczba współrzędnych wektora odpowiada liczbie wymiarów przestrzeni, w której definiowana jest hipersfera,
- policzyć ||Z||, tj. długość wektora Z, a następnie podzielić każdą ze współrzędnych wektora Z przez tę długość.
Nowy wektor Z reprezentuje punkt na powierzchni hipersfery o promieniu 1 z centrum w środku układu współrzędnych.
Wygeneruj wiele takich punktów dla przestrzeni 2-wymiarowej i przedstaw je w postaci graficznej. Sprawdź, czy układają się w kształt okręgu.
Uwaga – ograniczenie: do zaimplementowania w/w operacji nie wykorzystuj żadnych pętli (for, while, repeat
), a wyłącznie algorytmy STL i obiekty funkcyjne (własne lub biblioteczne). Jeżeli to potrzebne, rozłóż operacje na pojedyncze kroki, których wynik zapamiętuj w wektorach pomocniczych.
ZTP2023: Zadania przed lab.5
Zadania, które dotyczą zakresu materiału, jaki będzie poruszany na lab. 5. Rozwiązanie tych zadań nie jest wymagane. Stanowią wyłącznie pomoc w przygotowaniu się do zajęć.
Zadanie 1:
Napisz funkcję, która wczytuje macierz z pliku tekstowego zapisaną tak, że w kolejnych wierszach pliku są wartości komórek kolejnych wierszy macierzy rozdzielone spacjami, a następnie dokonuje jej transpozycji. Przyjmij, że wymiary wczytywanej macierzy są nieznane, ale że dane w pliku są na pewno poprawne (tj. wiersze przechowują tylko liczby, liczby liczb w wierszach są takie same, itp.). Do wczytania macierzy użyj kontenera typu <deque<deque<double>>
. Funkcja zwraca transponowaną macierz w postaci wskaźnika do dynamicznie alokowanego kontenera typu vector<vector<double>>
. Wypisz w oknie konsoli zawartość wynikowego kontenera i sprawdź, czy transpozycja została przeprowadzona poprawnie.
Zadanie 2:
Wczytaj słowa z kolejnych wierszy z pliku tekstowego do listy list, tj. kontenera typu list<list<string>>
, tak aby kontener zawierał listę wierszy, gdzie każdy wiersz jest reprezentowany przez listę słów z tego wiersza. Posortuj rosnąco słowa z każdego wiersza wg zasady sortowania takiej jak w słowniku języka polskiego, a następnie scal posortowane listy słów do jednej listy wynikowej reprezentowanej przez inny kontener typu list<string>
. Wypisz w oknie konsoli zawartość wynikowego kontenera w postaci kolumny i upewnij się, że sortowanie i scalanie się powiodło. Testy przeprowadź na pliku mistrz.txt
ZTP2023: Zadanie przed lab.4
Zadanie, które dotyczy zakresu materiału, jaki będzie poruszany na lab. 4. Rozwiązanie tego zadania nie jest wymagane. Stanowi wyłącznie pomoc w przygotowaniu się do zajęć.
Zamieszczony poniżej kod programu reprezentuje przykład programowania z wykorzystaniem cech charakterystycznych. W programie wykorzystywane są dwie klasy reprezentujące dwa pojęcia:
temperatura_wody
– liczba rzeczywista reprezentująca temperaturę wodykostka_do_gry
– liczba całkowita reprezentująca wartość, jaka może wypaść w wyniku rzutu kostką do gry.
Dla tych klas zdefiniowano ich cechy charakterystyczne. Są nimi:
- _jest_liczba – cecha mówiąca, czy danych obiekt reprezentuje liczbę,
- _jest_liczba_calkowita – cecha mówiąca, czy liczba którą reprezentuje danych obiekt, jest liczbą całkowitą,
- _nalezy_do_przedzialu – cecha mówiąca, czy liczba którą reprezentuje danych obiekt, należy do przedziału,
- _dolna_granica_przedzialu – wartość dolnej granicy przedziału, do którego mogą należeć liczby reprezentowane przez danych obiekt,
- _gorna_granica_przedzialu – wartość górnej granicy przedziału, do którego mogą należeć liczby reprezentowane przez danych obiekt,
Cechy charakterystyczne zostały zaimplementowane w programie. W tym celu najpierw zostały zaimplementowane dwie klasy: Bazowe_Cechy
oraz Cechy: public Bazowe_Cechy
tworzące pojęcie zbioru cech.
Następnie dla każdej z dwóch klas: temperatura_wody
i kostka_do_gry
zostały skonkretyzowane w odpowiedni sposób przypisane im klasy cech:
Cechy<temperatura_wody>: public Bazowe_Cechy
Cechy<kostka_do_gry>: public Bazowe_Cechy
Działanie programu polega na gromadzeniu danych liczbowych różnych typów w kontenerach, przy czym kontenery do walidacji wprowadzanych danych używają cech charakterystycznych. W tym celu zdefiniowana została klasa reprezentująca kontener SzablonStosu
przystosowany do przechowywania dowolnych wartości, w tym obiektów typu temperatura_wody
i kostka_do_gry
. Metoda push
tego kontenera przed umieszczeniem danej dokonuje jej walidacji posługując się informacjami z klasy Bazowe_Cechy
.
Wykorzystanie kontenera zostało zademonstrowane w funkcji main
. W kodzie main
tworzone są trzy kontenery K1, K2 i K3, a następnie są wypełniane wartościami. Uwaga: kontener K1 jest zapełniany wartościami tak długo, póki wystarczy zasobów komputera (w trakcie wykonania programu warto uruchomić menedżer zadań i w sekcji wydajności obserwować, jak ubywa wolnej pamięci w miarę pracy programu).
Zadania do zrobienia przed ćwiczeniami
- Przenieś kod do środowiska VS C++, skompiluj i uruchom.
- Przeanalizuj kod, upewnij się, że rozumiesz rolę wszystkich pól i metod w klasach i potrafisz to wyjaśnić na zajęciach.
- Upewnij się, że potrafisz wyjaśnić, dlaczego tyle właśnie elementów zostaje umieszczonych w każdym z trzech kontenerów (a nie więcej).
- dodaj do kodu jeszcze jedną klasę reprezentującą pojęcie liczbowe „numer kołnierzyka koszuli” i skonkretyzuj w odpowiedni sposób odpowiadającą jej klasę cech. Następnie, jeżeli to konieczne, rozszerz kod metody
push
tak aby poprawnie walidował obiekty nowego typu. W funkcjimain
dodaj kontener K4 w którym zgromadzisz kilka obiektów nowego typu. - Przygotuj się do rozwijania tego kodu dla potrzeb nowych rodzajów wartości, jakie można przechowywać w tym kontenerze.
Pliki do pobrania
Plik programu: ZPO-traits.cpp
Plik z danymi wejściowymi: qv-lab4 (po założeniu nowego projektu VC++ należy go umieścić w tym samym folderze, co plik z kodem programu).
/* ==========================
(c) WMP.SNS UKSW, 2015
========================== */
#include<iostream>
#include<fstream>
#include<string>
#include<limits>
#include<exception>
using namespace std;
class _Bazowe_Cechy {
public:
// pola statyczne stałe - dla stałych wartości całkowitych
static const bool _jest_liczba = false;
static const bool _nalezy_do_przedzialu = false;
static const bool _jest_liczba_calkowita = false;
};
template<typename T>
class _Cechy : public _Bazowe_Cechy {
public:
// metody statyczne - dla wartości innych typów niż liczby całkowite
static const T _dolna_granica() { return T(); };
static const T _gorna_granica() { return T(); };
};
template<typename T>
class Cechy : public _Cechy<T> {
};
class przyspieszenie {
double a;
public:
przyspieszenie(double acc = 0) : a(acc) {};
double operator()() const { return a; };
przyspieszenie& operator=(double acc) { a = acc; return *this; };
bool operator<(const przyspieszenie& p) const { return (a < p.a); };
friend ostream& operator<<(ostream& os, const przyspieszenie&);
};
ostream& operator<<(ostream& os, const przyspieszenie& p) { return os << p.a; };
template<>
class Cechy<przyspieszenie> : public _Cechy<przyspieszenie> {
public:
static const bool _jest_liczba = true;
};
class temperatura_wody {
double t;
public:
temperatura_wody(double temp = 50) : t(temp) {};
double operator()() const { return t; };
temperatura_wody& operator=(double temp) { t = temp; return *this; };
bool operator<(const temperatura_wody& tw) const { return (t < tw.t); };
friend ostream& operator<<(ostream& os, const temperatura_wody&);
};
ostream& operator<<(ostream& os, const temperatura_wody& tw) { return os << tw.t; };
template<>
class Cechy<temperatura_wody> : public _Cechy<temperatura_wody> {
public:
static const bool _jest_liczba = true;
static const bool _nalezy_do_przedzialu = true;
static const temperatura_wody _dolna_granica() { return temperatura_wody(0); };
static const temperatura_wody _gorna_granica() { return temperatura_wody(100); };
};
class kostka_do_gry {
int n;
public:
kostka_do_gry(int num = 1) : n(num) {};
int operator()() const { return n; };
kostka_do_gry& operator=(int num) { n = num; return *this; };
bool operator<(const kostka_do_gry& k) const { return (n < k.n); };
friend ostream& operator<<(ostream& os, const kostka_do_gry&);
};
ostream& operator<<(ostream& os, const kostka_do_gry& k) { return os << k.n; };
template<>
class Cechy<kostka_do_gry> : public _Cechy<kostka_do_gry> {
public:
static const bool _jest_liczba = true;
static const bool _nalezy_do_przedzialu = true;
static const bool _jest_liczba_calkowita = true;
static const kostka_do_gry _dolna_granica() { return kostka_do_gry(1); };
static const kostka_do_gry _gorna_granica() { return kostka_do_gry(6); };
};
class Przepelnienie : public exception {
char opis[100];
public:
Przepelnienie(const char* o) { strcpy_s(opis, o); }
const char* what() const throw() { return opis; };
};
class BrakDanych : public exception {
char opis[100];
public:
BrakDanych(const char* o) { strcpy_s(opis, o); }
const char* what() const throw() { return opis; };
};
template<typename T, int rozmiar, typename CechyT = Cechy<T>>
class SzablonStosu{
T stos[rozmiar];
int top;
public:
int zajetosc() { return top; };
SzablonStosu() : top(0) {}
void push(const T& i) {
if (top == rozmiar)
throw Przepelnienie(typeid(i).name());
stos[top++] = i;
}
void push(int i) {
if (top == rozmiar)
throw Przepelnienie(typeid(i).name());
// walidacja wartości przekazanej do zapisu
if (CechyT::_jest_liczba && CechyT::_jest_liczba_calkowita) {
if (CechyT::_nalezy_do_przedzialu) {
if (!(T(i) < CechyT::_dolna_granica()) && !(CechyT::_gorna_granica() < T(i)))
stos[top++] = i;
}
else
stos[top++] = i;
}
}
void push(double i) {
if (top == rozmiar)
throw Przepelnienie(typeid(i).name());
// walidacja wartości przekazanej do zapisu
if (CechyT::_jest_liczba && !CechyT::_jest_liczba_calkowita) {
if (CechyT::_nalezy_do_przedzialu) {
if (!(T(i) < CechyT::_dolna_granica()) && !(CechyT::_gorna_granica() < T(i)))
stos[top++] = i;
}
else
stos[top++] = i;
}
}
T pop() {
if (top == 0)
throw BrakDanych(typeid(stos[0]).name());
return stos[--top];
}
template<typename U1, int r, typename U2>
friend ostream& operator<<(ostream& os, const SzablonStosu<U1, r, U2>&);
};
template<typename U1, int r, typename U2>
ostream& operator<<(ostream& os, const SzablonStosu<U1, r, U2>& S)
{
for (int i = 0; i < S.top; i++) cout << S.stos[i] << endl;
return os;
};
int main() {
SzablonStosu<string, 5> K1;
SzablonStosu<przyspieszenie, 10> K2;
SzablonStosu<temperatura_wody, 10> K3;
SzablonStosu<kostka_do_gry, 10> K4;
// zapełnianie stosów K1, K2, K3 i K4:
ifstream fi("qv-lab4.txt");
string s;
try{
K1.push("Henryk");
K1.push("Sienkiewicz");
while (fi) {
fi >> s;
K1.push(s);
fi.seekg(ios::beg);
fi.clear();
cout << '*';
};
}
catch (Przepelnienie& e){
cout << "K1 gotowy: " << e.what() << endl;
};
cout << "Danych na stosie K1: " << K1.zajetosc() << endl << endl;
K2.push(przyspieszenie());
K2.push(przyspieszenie(5.0));
K2.push(10); // uwaga: nie akceptujemy przyspieszenia jako liczby całkowitej
K2.push(10.0);
cout << K2;
cout << "Danych na stosie K2: " << K2.zajetosc() << endl << endl;
K3.push(temperatura_wody());
K3.push(temperatura_wody(36.6));
K3.push(71.2);
K3.push(112.1); // uwaga: nie akceptujemy wartości spoza przedziału
cout << K3;
cout << "Danych na stosie K3: " << K3.zajetosc() << endl << endl;
K4.push(kostka_do_gry(3));
K4.push(kostka_do_gry());
K4.push(6);
K4.push(10); // uwaga: nie akceptujemy wartości spoza przedziału
cout << K4;
cout << "Danych na stosie K4: " << K4.zajetosc() << endl << endl;
// opróżnianie stosów
try{
while (true)
K1.pop();
}
catch (BrakDanych& e) {
cout << "K1 pusty: " << e.what() << endl;
}
try{
while (true)
K2.pop();
}
catch (BrakDanych& e) {
cout << "K2 pusty: " << e.what() << endl;
}
try{
while (true)
K3.pop();
}
catch (BrakDanych& e) {
cout << "K3 pusty: " << e.what() << endl;
}
try {
while (true)
K4.pop();
}
catch (BrakDanych& e) {
cout << "K4 pusty: " << e.what() << endl;
}
system("pause");
return 0;
}
ZTP2023: Wskazówki przed lab. 1
Zasady ogólne
Zasady wykonywania i oceniania programów na stacjonarnych zajęciach lab.:
- Każdy uczestnik wykonuje na komputerze w pracowni dwa zadania w środowisku MS Visual Studio: podstawowe (pierwszego poziomu) za 6 pkt. i dodatkowe (drugiego poziomu) za 4 pkt.
- Zadań nie wolno realizować na własnym laptopie.
- Dopiero kiedy prowadzący odbierze i pozytywnie oceni zadanie podstawowe, można zacząć rozwiązywać zadanie dodatkowe (dodatkowe bywa łatwiejsze).
- Studenci mogą realizować swoje zadania tylko na zajęciach – nie ma możliwości kończenia programu poza pracownią i przesyłania go do oceny w godzinach wieczornych czy następnego dnia.
- Studenci obowiązkowo uploadują do moodle rozwiązane zadania I i II poziomu w trakcie zajęć. Rozwiązania uploadowane po zajęciach nie będą oceniane.
Pełny opis zasad jest zamieszczony w moodle.
Rozwiązania będą weryfikowane za pomocą oprogramowania antyplagiatowego MOSS (tak samo jak w ubiegłym semestrze), dlatego oceny wystawione na zajęciach mogą jeszcze być później korygowane na podstawie wyników raportu MOSS (zbytnie podobieństwo kodu powoduje obniżenie oceny u wszystkich wskazanych w raporcie, tj. bez ustalania, kto był rzeczywistym autorem, a kto popełnił plagiat).
Porady przed lab. 1
Zadania realizowane na pierwszych zajęciach lab. będą dotyczyły materiału z pierwszego wykładu ZTP i wykładów PO z poprzedniego semestru. Dlatego proszę Państwa o przejrzenie materiału z poprzedniego semestru, a zwłaszcza dwóch ostatnich wykładów (strumienie).