Skip to content
Snippets Groups Projects
main.cpp 7.21 KiB
#include <iostream>
#include <random>
#include <sstream>
#include <string>

// Ülesanne 1.
// Kirjuta funktsioon `is_palindrome`, mis kontrollib kas sõne on palindroom
// (https://et.wikipedia.org/wiki/Palindroom). Ignoreeri tühikuid (whitespace)
// ja suurtähelisust, s.t et "a A" on palindroom.
//
// Kasuta funktsioonide üle defineerimist, et funktsioon kasutaks mõlemat
// tüüpi argumente, nii `std::string` kui ka C-tüüpi sõne `const char*`.
// Mõlemad üle defineerimised peavad tagastama tõeväärtustüübi `bool`.
//
// Näide:
//   is_palindrome("racecar") tagastab true
//   is_palindrome(std::string("racecar")) tagastab true
//   is_palindrome("") tagastab true
//   is_palindrome("ab") tagastab false
//
// NB! Pane tähele, et ainult `bool is_palindrome(std::string)` loomisel
// töötavad mõlemat tüüpi argumendid. Uuri iseseisvalt lähemalt miks see nii
// juhtub.

bool is_palindrome(const char *s) {
  size_t left = 0;
  auto length = std::strlen(s);

  if (length == 0) {
    return true;
  }

  size_t right = length - 1;

  while (left < right) {
    if (left < right && std::tolower(s[left]) != std::tolower(s[right])) {
      return false;
    }

    left++;
    right--;
  }

  return true;
}

bool is_palindrome(std::string s) { return is_palindrome(s.c_str()); }

// Ülesanne 2.
// Kirjuta funktsioon `word_count`, mis loeb sõnade arvu antud sõnes.
// Siin kontekstis tähendab sõna tühikutega (whitespace) eraldatud karakterite
// jada. Tühjas sõnes on 0 sõna.
//
// Näide:
//   word_count("Tere maailm!") tagastab 2 ja toimib järgmiselt:
//     1. sõna on "Tere"
//     2. sõna on "maailm!"

size_t word_count(std::string s) {
  std::stringstream ss(s);

  size_t count = 0;
  std::string sona;
  while (ss >> sona) {
    count++;
  }

  return count;
}
// Ülesanne 3.
// Kirjuta funktsioon `words`, mis tagastab konteineri
// `std::vector<std::string>`, ning tagastab iga sõna antud sõnes. Sõna on siin
// kontekstis sama, mis ülesandes 2.
//
// Näide:
//   words("Tere maailm!") tagastab vektori, kus on sõnad "Tere" ja "maailm!"
//   words("a b c d ") tagastab vektori, kus on sõnad "a", "b", "c" ja "d"
//     Pane tähele, et viimane sõna on "d" mitte "", s.t ignoreeri ülejäänud
//     tühikuid
//
// Vihje: Proovi kasutada klassi `std::stringstream`

std::vector<std::string> words(std::string s) {
  std::vector<std::string> words;
  std::stringstream ss(s);

  std::string sona;
  while (ss >> sona) {
    words.push_back(sona);
  }

  return words;
}

// Ülesanne 4.
// Kirjuta funktsioon `random_diff`, mis saab argumendiks täisarvu n ning
// konstrueerib 2 täisarvuvektorit (`std::vector<int>`). Seejärel lisab
// funktsioon mõlemasse vektorisse juhuslikke arve senikaua kuni mõlema vektori
// pikkus on n. Vali ise, mille alusel vektoreid täita. Funktsioon tagastab
// vektori vastavate elementide vahede summa. See tähendab, et kui vektor a =
// {1, 2, 3} ja b = {4, 5, 6} siis tagastatakse sum({1 - 4, 2 - 5, 3 - 6}) = -9
// Üleval toodud näidis on pseudokood ja ei ole valiidne C++ keeles.
//
// NB! Ära kasuta funktsiooni `rand()`.
// NB! Ülesannet on võimalik lahendada ilma vektoriteta, aga lahenda siiski
// kasutades vektoreid.

int random_diff(int n) {
  std::vector<int> v1(n);
  std::vector<int> v2(n);

  std::default_random_engine gen;
  std::uniform_int_distribution<int> jaotus(-100, 100);
  for (int i = 0; i < n; ++i) {
    v1[i] = jaotus(gen);
    v2[i] = jaotus(gen);
  }
  std::vector<int> diffs(n);
  for (int i = 0; i < n; ++i) {
    diffs[i] = v1[i] - v2[i];
  }
  int sum = 0;
  for (int i = 0; i < n; ++i) {
    sum += diffs[i];
  }
  // Võimalus, kuidas vektori elemendid kokku liita
  // return std::reduce(diffs.begin(), diffs.end(), 0);
  return sum;
}

// Ülesanne 5.
// Kirjuta funktsioon `randomize`, mis saab argumendiks C-tüüpi täisarvude
// massiivi ning selle pikkuse (tüüpi size_t). Seejärel täidab fuktsioon antud
// massiivi juhuslike arvudega ning tagastab nende arvude summa. Võid eeldada,
// et n > 0
//
// Näide:
//   int arr[10] = {0};
//   size_t size = 10;
//   int sum = randomize(arr, size);
//   // nüüd on massiivis juhuslikud arvud ja sum võrdne nende summaga

int randomize(int *arr, size_t n) {
  auto sum = 0;
  std::default_random_engine gen;
  std::uniform_int_distribution<int> jaotus(-100, 100);
  for (size_t i = 0; i < n; i++) {
    auto x = jaotus(gen);
    arr[i] = x;
    sum += x;
  }
  return sum;
}

// Ülesanne 6.
// Kirjuta funktsioon `average`, mis saab argumendiks konteineri
// `std::array<int, 10>` ning tagastab nende arvude aritmeetilise keskmise.
//
// Näide:
//   std::array<int, 10> arr{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//   average(arr) tagastab keskmise 5.5
//
// NB! Pane tähele, et funktsioon aktsepteerib argumendina ainult `std::array`
// konteinereid mille pikkus on 10. Selle piirangu eemaldamist vaatame tulevatel
// nädalatel.
//
// Mõtle std::array ja C-tüüpi massiivide erisuse peale

float average(std::array<int, 10> arr) {
  return std::reduce(arr.begin(), arr.end(), 0) /
         static_cast<float>(arr.size());
}

// Ä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++;
  }
}

auto equal(auto a, auto b) {
  if (a.size() != b.size()) {
    return false;
  }

  return std::equal(a.begin(), a.end(), b.begin());
}

template <typename T> auto all(T *ptr, size_t count, T comp) {
  return std::all_of(ptr, ptr + count, [comp](auto v) { return v == comp; });
}

int main() {
  // Ülesanne 1. Palindroom
  TEST(is_palindrome("racecar") == true);
  TEST(is_palindrome("raCecaR") == true);
  TEST(is_palindrome(std::string("racecar")) == true);
  TEST(is_palindrome(std::string("")) == true);
  TEST(is_palindrome(std::string("aa")) == true);
  TEST(is_palindrome(std::string("ab")) == false);
  TEST(is_palindrome(std::string("()()")) == false);
  TEST(is_palindrome(std::string("())(")) == true);

  // Ülesanne 2. Sõnade arv
  TEST(word_count("") == 0);
  TEST(word_count("A B") == 2);
  TEST(word_count("A B ") == 2);
  TEST(word_count("Tere maailm!") == 2);

  // Ülesanne 3. Sõnad
  using StrVector = std::vector<std::string>;
  TEST(words("").empty());
  TEST(equal(words("A B"), StrVector{"A", "B"}));
  TEST(equal(words("A B "), StrVector{"A", "B"}));
  TEST(equal(words("a b c d"), StrVector{"a", "b", "c", "d"}));

  // Ülesanne 4. Suvalised arvud
  // NB! Korrektset tulemust on pisut keerukam testida. Proovi mõelda, kuidas
  // sina seda testiksid.
  TEST(random_diff(10) != std::numeric_limits<int>::min());

  {
    int arr[10] = {0};
    size_t size = 10;
    int sum = randomize(arr, size);
    // Statistiliselt ei tohiks summa olla 0.
    TEST(sum > 0);
    // Arvud ei tohiks olla 0.
    TEST(!all(arr, size, 0));
  }

  // Ülesanne 5. Keskmine väärtus
  {
    std::array arr{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    TEST(average(arr) == 5.5f);
  }

  std::cout << "Testide tulemus: " << g_SuccessfulTestCount << "/"
            << g_TotalTestCount << '\n';
  return 0;
}