Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
cpp-25
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
kerdo
cpp-25
Commits
56fc8bbd
Commit
56fc8bbd
authored
2 weeks ago
by
Kerdo Kurs
Browse files
Options
Downloads
Patches
Plain Diff
add kodu4
parent
c90ac85b
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
kodu/kodu4/main.cpp
+356
-0
356 additions, 0 deletions
kodu/kodu4/main.cpp
with
356 additions
and
0 deletions
kodu/kodu4/main.cpp
0 → 100644
+
356
−
0
View file @
56fc8bbd
#include
<algorithm>
#include
<cassert>
#include
<concepts>
#include
<iostream>
#include
<numeric>
#include
<print>
#include
<sstream>
#include
<type_traits>
// 1. Ülesanne
// Siin on antud põhi klassile `IntVector`, mis on sisuliselt "wrapper"
// standardteegi vektorile, mis hoiustab täisarve. Implementeeri kõik nõutud
// konstruktorid ja liikmefunktsioonid.
class
IntVector
{
public:
// Vaikekonstruktor, mis initsialiseerib tühja vektori
IntVector
()
=
default
;
// Konstruktor, mis initsialiseerib n-pikkuse vektori vaikeväärtusega 0
// Näide:
// IntVector v(n) peaks väärtustama liikme `m_Vec` nagu teeb seda
// `std::vector<int> v(n)`
// IntVector objekti ei tohiks saada konstrueerida järgmiselt: `IntVector v =
// n` - see ei ole korrektne.
explicit
IntVector
(
const
long
n
)
:
m_Vec
(
n
)
{}
// Konstruktor, mis initsialiseerib n-pikkuse vektori väärtusega v
// Näide:
// IntVector v(n, v) peaks väärtustama liikme `m_Vec` nagu teeb seda
// `std::vector<int> v(n, v)`
IntVector
(
const
long
n
,
const
int
val
)
:
m_Vec
(
n
,
val
)
{}
// "Range" konstruktor, mis käitub kui Pythoni `range` funktsioon.
// Konstruktor on 3 argumendiga: start, end, step ning lisab vektorisse
// elemendid vahemikus [start, end) sammuga `step`. Näide:
// IntVector v(0, 10, 2) lisab vektorisse elemendid 0, 2, 4, 6 ja 8
// IntVector v(0, 2, 1) lisab vektorisse elemendid 0 ja 1
IntVector
(
const
int
begin
,
const
int
end
,
const
int
step
)
{
for
(
auto
i
=
begin
;
i
<
end
;
i
+=
step
)
{
m_Vec
.
push_back
(
i
);
}
}
// `set(size_t i, int val)` liikmefunktsioon, mis lisab elemendi `val`
// vektoris kohale `i`. Pane tähele, et kui vektori suurus on väiksem kui i,
// siis ära elementi lisa. Liikmefunktsioon tagastab tõeväärtuse, kas element
// lisati
bool
set
(
size_t
i
,
int
val
)
{
if
(
m_Vec
.
size
()
<=
i
)
{
return
false
;
}
m_Vec
[
i
]
=
val
;
return
true
;
}
// `int sum()` liikmefunktsioon tagastab elementide summa
[[
nodiscard
]]
int
sum
()
{
return
std
::
accumulate
(
m_Vec
.
begin
(),
m_Vec
.
end
(),
0
);
}
// `int min()` liikmefunktsioon tagastab minimaalse elemendi
// Elementide puudumise korral tagastada 0
int
min
()
{
return
std
::
min_element
(
m_Vec
.
begin
(),
m_Vec
.
end
())
-
m_Vec
.
begin
();
}
// `int max()` liikmefunktsioon tagastab minimaalse elemendi
// Elementide puudumise korral tagastada 0
int
max
()
{
return
std
::
max_element
(
m_Vec
.
begin
(),
m_Vec
.
end
())
-
m_Vec
.
begin
();
}
// Kuna `m_Vec` on privaatne, siis on testimiseks hea, kui saame selle
// klassist välja ka anda. Selleks teeme getter-funktsiooni. Pane tähele, et
// antud liikmefunktsioon ei tee vektorist koopiat – selle olulisusest räägime
// järgmisel nädalal.
[[
nodiscard
]]
auto
&
vec
()
const
{
return
m_Vec
;
}
// Liikmefunktsioonid `begin` ja `end` on vajalikud for-of tsükli
// kasutamiseks. Ära neid siin modifitseeri
[[
nodiscard
]]
auto
begin
()
const
{
return
m_Vec
.
begin
();
}
[[
nodiscard
]]
auto
end
()
const
{
return
m_Vec
.
end
();
}
[[
nodiscard
]]
auto
begin
()
{
return
m_Vec
.
begin
();
}
[[
nodiscard
]]
auto
end
()
{
return
m_Vec
.
end
();
}
private
:
std
::
vector
<
int
>
m_Vec
{};
};
// 2. Ülesanne
// Kirjuta funktsioonimall `sum(T)`, millel on tüübiparameeter T.
// Funktsioonimall tagastab antud konteineri summa. Võid eeldada, et T on alati
// konteiner ehk saad kasutada for-of tsüklit ning et konteiner hoiab endas
// int-tüüpi elemente. NB! Ära kasuta kuskil siin funktsioonimallis võtmesõna
// `auto`
template
<
typename
T
>
int
sum
(
const
T
&
t
)
{
return
std
::
accumulate
(
std
::
begin
(
t
),
std
::
end
(
t
),
0
);
}
// 3. Ülesanne
// Kirjuta funktsioonimall `negate(T)`, millel on tüübiparameeter T. Piira
// parameetrit T nii, et funktsioon oleks kutsutav ainult täisarvude ning
// ujukoma arvudega. Selleks uuri võtmesõna requires ning päist <concepts>.
// Funktsioon ise tagastab antud arvu vastandarvu, s.t 1 -> -1, 0 -> 0, -1 -> 1
// jne. NB! Ära kasuta kuskil siin funktsioonimallis võtmesõna `auto`
template
<
typename
T
>
requires
std
::
integral
<
T
>
||
std
::
floating_point
<
T
>
T
negate
(
T
t
)
{
return
-
t
;
}
// Ära seda funktsioonimalli modifitseeri!
template
<
typename
T
>
bool
testNegateType
()
{
return
requires
(
T
t
)
{
negate
(
t
);
};
}
// 4. Ülesanne [kuni 0.3 lisapunkti]
// Kirjuta funktsioonimall `variadicSum`, mida saab välja kutsuda ükskõik mis
// arvu argumentidega. Võid eeldada, et argumentide tüübid on samad.
template
<
typename
...
T
>
auto
variadicSum
(
T
...
args
)
{
return
(...
+
args
);
}
// 5. Ülesanne [kuni 0.5 lisapunkti]
// Kirjuta klass `MinuMap`, mis simuleerib `HashMap` või `dict`-tüüpi
// andmestruktuuri. Olgu klassil liikmefunktsioonid:
// set(std::string key, T value)
// std::optional<T> get(std::string key)
// bool exists(std::string key)
// void clear()
// void print()
// bool empty()
//
// 1. Pane tähele, et liikmefunktsioon `get` tagastab tühja std::optional<T>
// objekti (või std::nullopt) kui soovitud võtmega elementi ei leidu.
// 2. Pane tähele, et liikmefunktsioon `print` peab väljastama antud formaadis:
// <key1> -> <value1>
// <key2> -> <value2>
// Pane tähele, et iga rea lõpus peab olema reavahetus (vt ka testi
// main-funktsioonis).
// 3. Võid eeldada, et klass peab töötama ainult antud testide piires (vt
// main-funktsioon). Küll aga ei tohi lahendust hard-code'ida.
//
// Vihje: Elementide hoidmiseks võib abiks olla klass `std::pair<std::string,
// T>`. Lisaks uuri klassi `std::optional<T>`. NB! Ära kasuta standardteegi
// klassi `std::map`! Hästi sobib näiteks vektor ;)
template
<
typename
T
>
class
MinuMap
{
public:
MinuMap
()
=
default
;
void
set
(
std
::
string
key
,
T
value
)
{
m_Map
.
emplace_back
(
std
::
move
(
key
),
std
::
move
(
value
));
}
std
::
optional
<
T
>
get
(
std
::
string
key
)
{
auto
it
=
std
::
find_if
(
m_Map
.
begin
(),
m_Map
.
end
(),
[
&
key
](
auto
&
pair
)
{
return
pair
.
first
==
key
;
});
if
(
it
==
m_Map
.
end
())
{
return
std
::
nullopt
;
}
return
it
->
second
;
}
bool
exists
(
std
::
string
key
)
{
auto
it
=
std
::
find_if
(
m_Map
.
begin
(),
m_Map
.
end
(),
[
&
key
](
auto
&
pair
)
{
return
pair
.
first
==
key
;
});
return
it
!=
m_Map
.
end
();
}
void
clear
()
{
m_Map
.
clear
();
}
void
print
()
{
for
(
const
auto
&
[
key
,
value
]
:
m_Map
)
{
std
::
cout
<<
key
<<
" -> "
<<
value
<<
'\n'
;
}
}
bool
empty
()
{
return
m_Map
.
empty
();
}
private
:
std
::
vector
<
std
::
pair
<
std
::
string
,
T
>>
m_Map
;
};
// Ära neid muutujaid ja funktsioone redigeeri.
static
int
g_TotalTestCount
=
0
;
static
int
g_SuccessfulTestCount
=
0
;
#define TEST(condition) testAssert(condition, __FILE__, __LINE__)
void
testAssert
(
bool
condition
,
const
char
*
file
,
int
line
)
{
g_TotalTestCount
++
;
if
(
!
condition
)
{
std
::
cout
<<
"VIGA: Kontroll asukohas "
<<
file
<<
":"
<<
line
<<
" ei olnud õige.
\n
"
;
}
else
{
g_SuccessfulTestCount
++
;
}
}
template
<
typename
T
>
auto
equal
(
const
T
&
a
,
const
T
&
b
)
{
if
(
a
.
size
()
!=
b
.
size
())
{
return
false
;
}
return
std
::
equal
(
a
.
begin
(),
a
.
end
(),
b
.
begin
());
}
auto
all
(
const
auto
&
c
,
const
auto
val
)
{
return
std
::
all_of
(
c
.
begin
(),
c
.
end
(),
[
&
val
](
const
auto
&
v
)
{
return
v
==
val
;
});
}
class
CoutCapture
{
std
::
stringstream
&
m_Buffer
;
std
::
streambuf
*
m_Prevcout
;
public:
explicit
CoutCapture
(
std
::
stringstream
&
buf
)
:
m_Buffer
(
buf
)
{
m_Prevcout
=
std
::
cout
.
rdbuf
(
m_Buffer
.
rdbuf
());
}
~
CoutCapture
()
{
std
::
cout
.
rdbuf
(
m_Prevcout
);
}
};
int
main
()
{
// 1. ülesanne. IntVector
{
// Vaikekonstruktor
IntVector
v
;
TEST
(
v
.
vec
().
empty
());
}
{
// Ühe argumendiga konstruktor
IntVector
v
(
10
);
TEST
(
v
.
vec
().
size
()
==
10
);
TEST
(
all
(
v
,
0
));
}
{
// Kahe argumendiga konstruktor
IntVector
v
(
10
,
1
);
TEST
(
v
.
vec
().
size
()
==
10
);
TEST
(
all
(
v
,
1
));
}
{
// "Range" konstruktor
IntVector
v
(
0
,
10
,
2
);
TEST
(
equal
(
v
.
vec
(),
{
0
,
2
,
4
,
6
,
8
}));
}
{
// `set` liikmefunktsioon
IntVector
v
(
10
);
TEST
(
v
.
set
(
0
,
1
));
TEST
(
!
v
.
set
(
11
,
1
));
v
=
IntVector
(
0
);
TEST
(
!
v
.
set
(
0
,
1
));
}
{
// `sum` liikmefunktsioon
IntVector
v
(
10
);
TEST
(
v
.
sum
()
==
0
);
v
=
IntVector
(
10
,
1
);
TEST
(
v
.
sum
()
==
10
);
}
{
// `min` ja `max` liikmefunktsioonid
IntVector
v
(
0
,
10
,
1
);
TEST
(
v
.
min
()
==
0
);
TEST
(
v
.
max
()
==
9
);
v
=
IntVector
(
0
);
TEST
(
v
.
min
()
==
0
);
TEST
(
v
.
max
()
==
0
);
}
// 2. ülesanne. Funktsioonimall `sum`
{
std
::
vector
v
{
1
,
2
,
3
,
4
,
5
};
// Pane tähele, et antud funktsioonimalli peab saama kutsuda kahel viisil:
TEST
(
sum
(
v
)
==
15
);
TEST
(
sum
<
std
::
vector
<
int
>>
(
v
)
==
15
);
std
::
array
<
int
,
5
>
a
{
1
,
2
,
3
,
4
,
5
};
TEST
(
sum
(
a
)
==
15
);
}
// 3. ülesanne. Funktsioonimall `negate`
{
TEST
(
negate
(
1
)
==
-
1
);
TEST
(
negate
(
-
1
)
==
1
);
TEST
(
negate
(
0
)
==
0
);
TEST
(
testNegateType
<
int
>
());
TEST
(
testNegateType
<
float
>
());
TEST
(
testNegateType
<
double
>
());
TEST
(
!
testNegateType
<
std
::
string
>
());
}
// Kui testid on siiani läbitud, on ülesanne lahendatud
// Siit edasi on lisaülesanded
// 4. ülesanne. Variadic funktsioonimall
#if 0
{
TEST(variadicSum(1, 2, 3, 4, 5) == 15);
TEST(variadicSum(0) == 0);
TEST(variadicSum(1) == 1);
}
#endif
// 5. ülesanne. Klassimall, hashmap'i "emulatsioon"
#if 0
{
MinuMap<int> map{};
TEST(map.empty());
map.set("tere", 1);
TEST(!map.empty());
TEST(map.get("tere") == std::optional(1));
TEST(map.get("tere").value() == 1);
TEST(!map.get("maailm"));
map.set("maailm", 2);
TEST(map.get("maailm").value() == 2);
TEST(map.exists("tere"));
TEST(map.exists("maailm"));
TEST(!map.exists("koer"));
std::stringstream buf;
if (CoutCapture c(buf); true) {
map.print();
}
auto str = buf.str();
TEST(str == "tere -> 1\nmaailm -> 2\n");
map.clear();
TEST(map.empty());
}
#endif
std
::
cout
<<
"Testide tulemus: "
<<
g_SuccessfulTestCount
<<
"/"
<<
g_TotalTestCount
<<
'\n'
;
return
g_SuccessfulTestCount
!=
g_TotalTestCount
;
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment