Kodused ülesanded
Esitada on vaja failid mvector.h
, hadron.h
, hadron.cpp
, rgb.h
, rgb.cpp
.
Kodutöö nimede ja funktsioonide valideerimiseks kasuta järgnevat main.cpp faili.
template < typename T> concept rgbKorrektne = requires(T *rgb_ptr) { { new_RGB() } -> std::same_as<T *>; { kustuta_RGB(rgb_ptr) }; { valge_RGB(rgb_ptr) }; }; static_assert (rgbKorrektne< struct RGB>, "RGB funktsioonid katki" ); template < typename T> concept mVectorKorrektne = requires(mVector<T> v) { { mVector<T>{} }; { v.push_back(T{}) }; { v.size() } -> std::same_as< size_t >; { v.capacity() } -> std::same_as< size_t >; { v.pop() } -> std::same_as<T>; { v.pop(54) } -> std::same_as<T>; { v[42] } -> std::same_as<T &>; { v.data() } -> std::same_as<T *>; }; static_assert (mVectorKorrektne< int >, "Vektor katki" ); template < typename FilenameT> concept loeEnergiatPtrKorrektne = requires(FilenameT filename, size_t len, double *data) { { loe_osakesed(filename, &len) } -> std::same_as< double *>; { yle_l2vendi(data, len, 7E12) } -> std::same_as< size_t >; }; static_assert (loeEnergiatPtrKorrektne<std::string>, "energia lugemine viidaga katki" ); template < typename FilenameT, typename T> concept loeEnergiatVectorKorrektne = requires(FilenameT filename, mVector<T> v) { { loe_osakesed(filename) } -> std::same_as<mVector<T>>; { on_vahemikus(v, 7E12, 10E12) } -> std::same_as<mVector<T>>; }; static_assert (loeEnergiatVectorKorrektne<std::string, double >, "energia lugemine vektoriga katki" ); int main() { return 0; } |
1. Omatehtud vektor
Selle ülesande lahendus paiguta faili mvector.h
.
Loo enda std::vector
analoog. Klassimalli nimeks on mVector
. Malliparameetriks on vektoris hoitavate elementide tüüp. Eeskujuna vaata Microsoft STL selgitust.
Vektori elemente hoia massiivis, mis asub kuhjamälus. Massiivi suurust tuleb suurendada ja vähendada vastavalt vajadusele (abiks võib võtta teise massiivi). Massiivi suurendamiseks või vähendamiseks on mõistlik teha eraldi funktsioonid. Massiivi elementidele juurdepääsuks kasuta kolme viita (pointer) analoogiliselt Microsoft STL kirjeldusele.
Klassimallis peavad olema järgmised komponendid:
mVector()
- Vaikekonstruktor. Algväärtustab kõik muutujad (kõik viidad
nullptr
).
- Vaikekonstruktor. Algväärtustab kõik muutujad (kõik viidad
void push_back(T el)
- Lisab parameetrina antud elemendi vektori lõppu. Kui massiiv on tühi, luuakse kuhjamällu üheelemendiline massiiv ja element paigutatakse sinna. Kui massiivis on juba elemente, kuid massiiv on täis, siis kahekordistatakse massiivile eraldatud ruumi (elementide arvu). Mõistlik on ruumi suurendamiseks luua eraldi funktsioon.
size_t size()
- Tagastab vektoris olevate elementide arvu.
size_t capacity()
- Tagastab massiivi jaoks hõivatud mälu suuruse elementide arvuna.
T pop()
- Tagastab ja eemaldab vektori viimase elemendi.
T pop(size_t i)
- Tagastab ja eemaldab kohal
i
oleva elemendi. Järgmised elemendid nihutatakse ühe koha võrra tagasi. - Mõlema
pop
funktsiooni korral: kui massiivis on elemente vähem kui veerand mahutavusest, vabastatakse mälu poole massiivi mahutavuse ulatuses. Mõistlik on ruumi vähendamiseks luua eraldi funktsioon.
- Tagastab ja eemaldab kohal
T& operator[]
- Tagastab viite (reference) antud indeksil olevale elemendile.
T* data()
- Tagastab viida (pointer) vektori esimesele elemendile.
void reserve(size_t)
- Ruumi reserveerimine
size_t
ulatuses. See võib tähendada ka ruumi vähendamist.
- Ruumi reserveerimine
void clear()
- vektori tühjendamine (ja viidad
nullptr
-ks)
- vektori tühjendamine (ja viidad
Näiteks, testkoodi
cout << format( "Lisan 10 miljonit täisarvu.\n" ); mVector< int > a; for ( int i{0}; i < 10000000; i++) { a.push_back(i); } cout << format( "capacity: {}; size: {}\n" , a.capacity(), a.size()); cout << format( "Eemaldan (pop) 10 miljonit täisarvu.\n" ); for ( int i{0}; i < 10000000; i++) { a.pop(); } cout << format( "capacity: {}; size: {}" , a.capacity(), a.size()); |
tulemusel kuvatakse ekraanile
Lisan 10 miljonit täisarvu. capacity: 16777216; size: 10000000 Eemaldan (pop) 10 miljonit täisarvu. capacity: 0; size: 0 |
2. RGB
Selle ülesande lahendus paiguta failidesse rgb.h
ja rgb.cpp
.
Juku renoveerib kodus oma tuba ja tahab kõik tuled muuta kaugjuhitavaks. Sel eesmärgil kavatseb ta ise valmis kirjutada serveri, mis tulesid juhib. Renoveerimine on veel pooleli ja Juku pole kindel, mis värvi tuled täpsemalt tulevad.
Loo struktuur RGB
kolme täisarvu (lõigus 0-255) esitamiseks. Iga arv esitab ühte värvi. Värvide jaoks vali sobiv andmetüüp.
Lisaks struktuurile loo kolm funktsiooni:
RGB* new_RGB()
- Loob uue RGB struktuuri koos algväärtustamisega kuhjamällu ja tagastab selle viida.
void kustuta_RGB()
- Nullib RGB värvid ja ei tagasta midagi.
void valge_RGB()
- Seab kõik värvid maksimumi ja ei tagasta midagi.
Näiteks, testkoodi (siin värvide nimed on r
, g
ja b
)
RGB *ptr = new_RGB(); cout << format( "r: {} g: {} b: {}\n" , ptr->r, ptr->g, ptr->b); valge_RGB(ptr); cout << format( "r: {} g: {} b: {}\n" , ptr->r, ptr->g, ptr->b); kustuta_RGB(ptr); cout << format( "r: {} g: {} b: {}\n" , ptr->r, ptr->g, ptr->b); delete ptr; |
tulemusel kuvatakse ekraanile
r: 0 g: 0 b: 0 r: 255 g: 255 b: 255 r: 0 g: 0 b: 0 |
3. Suur Hadroni Põrguti
Selle ülesande lahendus paiguta failidesse hadron.h
ja hadron.cpp
.
Suur Hadronite Põrguti on Šveitsis asuv osakestekiirendi. Osakestele antakse suur energia ja siis need põrgatatakse omavahel kokku. Kokkupõrgete tagajärgi uurivad teadlased. Osakeste energiad on failis osakesed.txt
. Faili esimesel real on osakeste arv. Igal järgneval real on ühe osakese energia elektronvoltides ujukomaarvuna.
Fail on kättesaadav allpool. Faili suurus on umbes 20 MB. Reaalselt genereeris Suur Hadroni Põrguti testide jooksul 600 petabaiti infot.
Loo funktsioonid, et analüüsida kokkupõrgete tagajärjel saadud osakeste energiaid.
double* loe_osakesed(string failinimi, size_t* pikkus)
- Funktsiooni parameetriteks on faili nimi ja viit elementide arvule (pöördumisel 0). Funktsioon loeb sellesse osakeste arvu faili esimesest reast. Funktsioon loob kuhjamällu ujukomaarvude massiivi, loeb failist energiad loodud massiivi ja tagastab viida massiivile. Kui faili ei eksisteeri, tagastab funktsioon
nullptr
.
- Funktsiooni parameetriteks on faili nimi ja viit elementide arvule (pöördumisel 0). Funktsioon loeb sellesse osakeste arvu faili esimesest reast. Funktsioon loob kuhjamällu ujukomaarvude massiivi, loeb failist energiad loodud massiivi ja tagastab viida massiivile. Kui faili ei eksisteeri, tagastab funktsioon
size_t yle_l2vendi(double* andmed, size_t pikkus, double l2vend)
- Funktsioon tagastab nende osakeste arvu, mille energia ületab etteantud lävendit.
Näiteks, testkoodi
size_t len{}; double *data = loe_osakesed( "osakesed.txt" , &len); cout << format( "Osakeste arv: {}\n" , len); for ( int i{}; i < 5; i++) { cout << format( "Osake nr {}: {}\n" , i, data[i]); } int yle_avg = yle_l2vendi(data, len, 7); int yle_max = yle_l2vendi(data, len, 10); cout << format( "Üle 7 TeV: {}\n" , yle_avg); cout << format( "Üle 10 TeV: {}\n" , yle_max); cout << format( "Kustutan andmed" ); delete [] data; |
tulemusel kuvatakse ekraanile
Osakeste arv: 2204598 Osake nr 0: 11.727679 Osake nr 1: 0.481038 Osake nr 2: 6.05704 Osake nr 3: 8.604874 Osake nr 4: 6.862579 Üle 7 TeV: 1110607 Üle 10 TeV: 634209 Kustutan andmed |
4. Suur Hadroni Põrguti vektoriga
Selle ülesande lahendus paiguta samuti failidesse hadron.h
ja hadron.cpp
.
Loo Suure Hadroni Põrguti ülesande versioon, mis kasutab esimeses ülesandes loodud vektorit mVector
.
Loo järgmised funktsioonid:
mVector<double> loe_osakesed(string file_name)
- Failis esimesel real on osakeste arv. Funktsioon loeb failist alates teisest reast osakeste energiad vektorisse. Kuna osakeste arv on ette teada, siis on mõistlik teha klassimalli
mVector
juurde funktsioon mälu hõivamiseks etteantud arvu elementide jaoks.
- Failis esimesel real on osakeste arv. Funktsioon loeb failist alates teisest reast osakeste energiad vektorisse. Kuna osakeste arv on ette teada, siis on mõistlik teha klassimalli
mVector<double> on_vahemikus( mVector<double>& v, double min, double max)
- Funktsioon tagastab vektori nende energiatega, mis jäävad etteantud vahemikku (otspunktid ei ole kaasa arvatud).
Näiteks, testkoodi
mVector< double > v{loe_osakesed( "osakesed.txt" )}; cout << format( "capacity: {}; size: {}\n" , v.capacity(), v.size()); mVector< double > avg{on_vahemikus(v, 7, 10)}; mVector< double > min{on_vahemikus(v, 0, 7)}; cout << format( "7-10 : {}; 0-7 : {}\n" , avg.size(), min.size()); |
tulemusel kuvatakse ekraanile
capacity: 2204598; size: 2204598 7-10 : 476398; 0-7 : 1093991 |