diff --git a/ndl2/CMakeLists.txt b/ndl2/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..80a84408a9796406bc1f92fed6a55c863b571957
--- /dev/null
+++ b/ndl2/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.30)
+project(ndl2)
+
+set(CMAKE_CXX_STANDARD 23)
+
+add_executable(ndl2 main.cpp)
diff --git a/ndl2/main.cpp b/ndl2/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..149532c9dcde6fa1716855a201b250c9e214ef20
--- /dev/null
+++ b/ndl2/main.cpp
@@ -0,0 +1,245 @@
+#include <iostream>
+#include <sstream>
+
+// Proovi lahendada allolevad أ¼lesanded. Lahendusi vaatame pأµgusalt jأ¤rgmises praktikumis ja lahendused panen Git'i
+// jأ¤rgmise nأ¤dala alguses.
+
+// 1. أœlesanne
+// Kirjuta funktsioon, mis lأ¼hendab sأµnena antud inimese nime antud nأ¤idete pأµhjal.
+// أ„ra kasuta klassi `std::stringstream`
+//
+// Nأ¤ide:
+//   lyhenda("Mari-Anne Lill") = "Lill M-A."
+//   lyhenda("Otto Triin Kaido Maastik") = "Maastik O. T. K."
+
+// ...
+
+// 2. أœlesanne
+// Kirjuta funktsioon tagurpidi, mis keerab argumendina antud sأµnevektori sأµned tagurpidi.
+// Seejأ¤rel keerab funktsioon vektori enda tagurpidi. Tagasta muudetud vektor.
+//
+// Nأ¤ide:
+//   tagurpidi({"auto", "koer"}) = {"reok", "otua"}
+
+// ...
+
+// 3. أœlesanne
+// Kirjuta funktsioon, mis saab argumendiks sأµnedevektori ning kustutab sealt kأµik sأµned, mis sisaldavad
+// teises argumendis saadud sأµne. S.t teine argument on kustutatava sأµne alamsأµne. Tagasta muudetud vektor.
+//
+// Nأ¤ide:
+//   kustuta({"tere", "auto", "koer"}, "er") = {"auto"}
+
+// ...
+
+
+// Vأµid allolevad kommentaarid eemaldada, et nأ¤ha, millal mingit puhvrit suuremaks tehakse vأµi uus objekt luuakse
+// Reeglina ei ole see hea praktika, aga saame pisut rohkem informatsiooni allokatsioonide kohta.
+// Allokatsioone ja vأµtmesأµnu `new` ja `delete` vaatame tulevatel nأ¤dalatel.
+//
+// void *operator new(size_t size) {
+//     std::println("new({})", size);
+//     void *p = malloc(size);
+//     return p;
+// }
+//
+// void operator delete(void *p) {
+//     std::println("delete()");
+//     free(p);
+// }
+
+// Lahkame seda funktsiooni tulevate nأ¤dalatel
+template<typename Container>
+void prindi(Container &c) {
+    std::cout << "[";
+    for (auto x : c) {
+        std::cout << x << ' ';
+    }
+    std::cout << "]\n";
+
+    // Kui sul tأ¶أ¶tab std::println, kasuta seda
+    // std::println("{:}", c);
+}
+
+int main() {
+    {
+        // Loob tأ¼hja vektori, kus pole أ¼htegi elementi
+        // ega ruumi أ¼helegi elemendile
+        std::vector<int> vec;
+
+        // vec[0] = 1;
+        // ^ Proovi seda rida jooksutada, see krahhib programmi
+    }
+
+    {
+        // Loob tأ¼hja vektori, kus pole أ¼htegi telementi.
+        // (Liikme)funktsioon reserveerib vektoris ruumi 10 elemendile, kuid ei initsialiseeri أ¼htegi elementi.
+        std::vector<int> vec;
+        vec.reserve(10);
+
+        // vec[0] = 1;
+        // ^ Kas siin on see rida OK?
+    }
+
+    {
+        // Loob vektori, kus on ruumi 10 elemendile
+        // ning initsialiseerib need tavavأ¤أ¤rtusega
+
+        std::vector<int> vec(10);
+
+        // Loob vektori, aga elemendid on vأ¤أ¤rtustatakse vأ¤أ¤rtusega 1
+        std::vector<int> vec1(10, 1);
+    }
+
+    {
+        std::vector<int> vec(10);
+
+        // Klassikaline for-tsأ¼kkel, kuidas elemente vأ¤أ¤rtustada
+        for (size_t i = 0; i < vec.size(); i++) {
+            vec[i] = 1;
+        }
+
+        // Miks allolev for-of-tsأ¼kkel ei vأ¤أ¤rtusta elemente?
+        // Mis on tأ¼أ¼pi on muutuja `x`?
+        for (auto x : vec) {
+            x = 1;
+        }
+
+        // Aga miks allolev for-of-tsأ¼kkel tأ¶أ¶tab?
+        for (auto &x : vec) {
+            x = 1;
+        }
+    }
+
+    {
+        // Vahel on vektori konstrueerimisel vأµimalik أ¤ra jأ¤tta elementide tأ¼أ¼bid
+        // See on vأµimalik, kui konstrueerid vektori kohe elementidega
+        std::vector vec{1, 2, 3};
+
+        // vأµi kasutad konstruktorit, mis mأ¤أ¤rab algvأ¤أ¤rtuse
+        std::vector vec1(10, 0);
+
+        // See on vأµimalik tأ¤nu CTAD feature'ile
+        // Seda vaatame tulevikus pأµhjalikumalt, aga vأµid uurida lأ¤hemalt:
+        // https://en.cppreference.com/w/cpp/language/class_template_argument_deduction
+    }
+
+    {
+        // Miks selline vektori konstrueerimine on ebaefektiivne?
+        // Mأµtle, kuidas dأ¼naamilist vektorit implementeerida
+        // Paljud IDE-d peaksid tegema for-tsأ¼kli vأµi seal sees midagi kollaseks ja viitama, et selline
+        // koodilأµik on ebaefektiivne ja soovitab paremini. Vaata, kas ja kuidas sinu IDE seda teeb.
+        std::vector<int> vec;
+        for (int i = 0; i < 10; i++) {
+            vec.push_back(i);
+        }
+    }
+
+    {
+        // Mأµtle, millal kasutada `std::vector` asemel `std::array`
+        // Vihje: `std::array` ei saa lisada rohkem elemente, kui esialgselt teise "klassi"-argumendiga defineeritud.
+        std::array<int, 4> arr{1, 2, 3, 4};
+
+        // NB! `std::array` suurus peab olema koodis kirjas kompileerimise ajal.
+        // Nأ¤iteks allolev koodilأµik ei ole korrektne:
+        // int n = 0;
+        // std::cin >> n;
+        // std::array<int, n> arr;
+        // Kui on vaja kasutaja sisendit kasutada konteineri suurusena, siis peame kasutama dأ¼naamilist konteinerit
+    }
+
+    {
+        // Massiivi (`std::array`) saab ka konstrueerida ainult suurusega
+        // Mis vأ¤أ¤rtusega on antud massiivi elemendid?
+        std::array<int, 10> arr{};
+    }
+
+    {
+        // Allolev muutuja C-tأ¼أ¼pi sأµne, mis on tأ¼أ¼biga `const char*`
+        // Selle sأµne kasutamine on limiteeritud, uuri iseseisvalt, mis limitatsioonid sellel on.
+        //   Kas saame sinna karaktereid lisada?
+        //   Kas saame seal karaktereid asendada?
+        const char *s = "tere maailm!";
+
+        // C-tأ¼أ¼pi sأµne on sisuliselt karakterite massiiv, mis pannakse reeglina programmi binaari sisse.
+        // C-tأ¼أ¼pi sأµne peab standardi jأ¤rgi lأµppema karakteriga 0 (NULL-byte, '\0'), mis signaliseerib sأµne lأµpu.
+        // Funktsioonid, mille signatuuris on `const char*` eeldavad reeglina, et NULL-byte on olemas.
+        // See tأ¤hendab, et on juhte, et NULL-byte pole vaja. Mأµtle miks see vأµib olla kasulik.
+        // Erandjuhul
+        char s1[] = "tere maailm!";
+        // on see sأµne pinumأ¤lul, millest rأ¤أ¤gime lأ¤hemalt tulevate nأ¤dalatel.
+        // Selles sأµnes saame muuta eraldiseisvaid karaktereid, aga ei saa sأµne suurust muuta.
+
+        // Sأµne pikkuse saame funktsiooniga strlen (samuti eeldab sأµne lأµpus NULL-byte'i). Kuidas muidu sأµne lأµppu saada?
+    }
+
+    {
+        // C-tأ¼أ¼pi massiivid on sarnased C-tأ¼أ¼pi sأµnedele, ainus erinevus on see, et neid ei panda reeglina* programmi
+        // binaari ning ei lأµppe NULL-byte'iga.
+        // Miks ei ole NULL-byte kasutamine vأµimalik massiiviga, aga on vأµimalik C-tأ¼أ¼pi sأµnega?
+        // Vihje: ASCII tabel
+        // NULL-byte'i puudumine tأ¤hendab kأ¼ll seda, et alati C-tأ¼أ¼pi massiivi edasi andmisel funktsiooni vmt
+        // peame kaasa andma ka selle pikkuse.
+        // Miks see on halb? Kas see vأµib olla ka hea?
+
+        // Konstrueerib massiivi, kus on 3 elementi
+        int arr[] = {1, 2, 3};
+
+        // Uuri iseseisvalt, mida teevad jأ¤rgmised konstrueerimised
+        int arr1[3] = {1, 2, 3};
+        int arr2[3] = {};
+        int arr3[3] = {0};
+
+        // Miks see ei kompileeru?
+        // int arr4[];
+    }
+
+    {
+        // Aga kuidas ma leian sأµnest mingi karakteri vأµi alamsأµne?
+
+        // Kasutame siin `using` konstruktsiooni, siis ei pea kogu aeg
+        // `std::string` vأ¤lja kirjutama. Pane tأ¤hele, et liigne selle kasutamine
+        // vأµib teha koodi loetavuse halvemaks.
+        // Uuri seda konstruktsiooni lأ¤hemalt: https://en.cppreference.com/w/cpp/keyword/using
+        using Str = std::string;
+
+        Str s = "see on pikk sأµne ja siin on palju sأµnu";
+        Str as = "tere";
+        // char as = 's';
+        if (const auto pos = s.find(as); pos == Str::npos) {
+            std::println("ei leidnud!");
+        } else {
+            std::println("{} asub positsioonil {}, alles jأ¤أ¤b '{}'", as, pos, s.substr(pos));
+        }
+    }
+
+    {
+        // Miks on allolev kood reeglina* halb?
+        // Vihje: vأµib juhtuda, et teeme peaaegu iga += korral sأµnest koopia (Javas samuti)
+        // Huvi korral uuri konseptsiooni "short string"
+        std::string result;
+        for (int i = 0; i < 100; i++) {
+            result += "a";
+        }
+
+        // Jah, saame tegelt luua sama sأµne ka nii
+        std::string result1(100, 'a');
+        // aga sageli أ¼lesanne seda ei vأµimalda
+
+        // Seepأ¤rast on parem tsأ¼klites sأµnesid luues kasutada klassi `std::stringstream`
+        std::stringstream ss;
+        for (int i = 0; i < 100; i++) {
+            ss << "a";
+        }
+        // ja saame konstrueerida sأµne jأ¤rgnevalt:
+        auto str = ss.str();
+        // Jأ¤llegi hea koht, kus kasutada vأµtmesأµna `auto`
+
+        // Klass `stringstream` vأµimaldab veel mitmeid muid asju, uuri iseseisvalt lأ¤hemalt.
+        if (ss.eof()) {
+            // ...
+        }
+    }
+
+    return 0;
+}