#include <catch2/catch_test_macros.hpp>

/*
ZADANIE:

Przy użyciu szablonów zaimplementuj funkcję, która (w sposób rekursywny) liczy silnię.
Wartość, dla której liczona jest silnia przyjmowana jest jako parametr szablonu
będący liczbą bez znaku. Pamiętaj o warunku stopu.

*/

// ROZWIĄZANIE:

template<unsigned N> unsigned factorial() {
    return N * factorial<N-1>();
}

template<> unsigned factorial<0>() { return 1; }


// TESTY:

TEST_CASE("1!") {
    CHECK(factorial<1>() == 1);
}

TEST_CASE("3!") {
    CHECK(factorial<3>() == 6);
}

TEST_CASE("5!") {
    CHECK(factorial<5>() == 120);
}

/*
ZADANIE:

Korzystając z algorytmów biblioteki standardowej skonstruuj algorytm,
który dla danego zakresu łańcuchów tekstowych (stringów) zwraca liczbę łańcuchów,
które składają się wyłącznie z wielkich liter.
Załóż, że istnieje funkcja std::isupper(), która sprawdza,
czy dany znak jest wielką literą.
*/

// PRZYKŁADOWE ROZWIĄZANIE:

template<typename Iter>
auto count_upper_strings(Iter from, Iter to) {
    auto all_upper = [](const std::string& text) {
        return std::all_of(text.begin(), text.end(), [](char c) { return std::isupper(c); });
    };
    return std::count_if(from, to, all_upper);
}

// TESTY:

TEST_CASE("['ABC', 'DEF']") {
    const auto data = {"ABC", "DEF"};
    CHECK(count_upper_strings(data.begin(), data.end()) == 2);
}

TEST_CASE("['AbC', 'Def']") {
    const auto data = {"AbC", "Def"};
    CHECK(count_upper_strings(data.begin(), data.end()) == 0);
}

TEST_CASE("['abc', 'D']") {
    const auto data = {"abc", "D"};
    CHECK(count_upper_strings(data.begin(), data.end()) == 1);
}
