C++ Test

valarray

valarray 可以直接丟整進 cmath function 裡

[2]:
#include <valarray>
#include <iostream>
#include <cmath>

std::valarray<double> nums = {1, 2, 3, 4, 5};
std::valarray<double> sqrts = sqrt(nums);

for(const double& num : sqrts)
    std::cout << num << ", ";

1, 1.41421, 1.73205, 2, 2.23607,

Range Enumeration 貌似不能用 Temporary Object

下面這樣不行:

[ ]:
#include <valarray>
#include <iostream>
#include <cmath>

std::valarray<double> nums = {1, 2, 3, 4, 5};

for(const double& num : sqrt(nums))
    std::cout << num << ", ";

cast 成 valarray<double> 就可以:

[4]:
#include <valarray>
#include <iostream>
#include <cmath>

std::valarray<double> nums = {1, 2, 3, 4, 5};

for(const double& num : static_cast<std::valarray<double>>(sqrt(nums)))
    std::cout << num << ", ";

1, 1.41421, 1.73205, 2, 2.23607,

py

  • structured binding

  • std::max(定義在 algorithm 裡)對三個數以上要這樣用 std::max({1, 2, 3})。直接寫 std::max(1, 2, 3) 的時候第三個 arg 是 comp

    • std::max({1, 2, 3}) 可以用是因為有一個 constructor takes in initializer_list

    • 不能直接丟 container,例如 vector 給 std::max

    • std::max_element(v.begin(), v.end()) 回傳 iterator,要用 * 取值

  • python list append = c++ vector push_back

  • python math.inf = c++ std::numeric_limits<double>::infinity(),定義在 <limit>

  • deque 比較

deque<T>pop_front()pop_back() 不回傳 element

  • 如果設計成回傳 element 會有兩個問題:

    • return element 會呼叫 copy ctor。如果 copy ctor 在 return 時 throw exception,該 element 也已經消失了

    • 對於不真正需要 popped element 的程序,return 時的 copy 是浪費時間

[ ]:
template<class T>
class queue {
    T* elements;
    std::size_t top_position;
    // stuff here
    T pop()
    {
        auto x = elements[top_position];
        // TODO: call destructor for elements[top_position] here
        --top_position;  // alter queue state here
        return x;        // calls T(const T&) which may throw
    }
};

Ranges (C++ 20)

[ ]:
vector data {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto result { data
    | views::filter([](const auto& value) { return value % 2 == 0; })/* 2 4 6 8 10*/
    | views::transform([](const auto& value) { return value * 2.0; })/* 4 8 12 16 20 */
    | views::drop(2)                                                 /* 12 16 20 */
    | views::reverse                                                 /* 20 16 12 */
    | views::transform([](int i) { return to_string(i); })           /* "20" "16" "12" */
}

Comparator

這裡這裡都說 >= 不能當 comparator 因為會破壞 If f(x, y) then !f(y, x) (antisymmetry)。但測試起來沒問題啊???

[1]:
#include <algorithm>
#include <vector>

std::vector<int> a = {1, 2, 3, 3, 3, 4, 5, 6, 7, 8, 8, 9};

std::sort(a.begin(), a.end(), [](int x, int y){ return x >=y; });

a
[1]:
{ 9, 8, 8, 7, 6, 5, 4, 3, 3, 3, 2, 1 }

Raw String

[1]:
#include <iostream>

std::cout << R"(This is a \n "raw string")"<< std::endl;
This is a \n "raw string"

std::greater and std::sort

[6]:
#include <iostream>     // std::cout
#include <functional>   // std::greater
#include <algorithm>    // std::sort
#include <vector>

int main () {
    std::vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    std::sort(a.begin(), a.end(), std::greater<int>());

    for (const int& value : a)
        std::cout << value << ", ";

    return 0;
}

main();
9, 8, 7, 6, 5, 4, 3, 2, 1,

std::to_string and std::stoi

[4]:
#include <iostream>
#include <string>  // std::to_string and std::stoi
#include <vector>

int a = 123;

std::vector<int> v = {};
for(char& c : std::to_string(a))
    v.push_back(std::stoi(std::string(1, c)));

v
[4]:
{ 1, 2, 3 }

Returning a Tuple

[2]:
#include <tuple>
#include <iostream>

std::tuple<int, int> f(){   // cannot define as auto
    return {1, 2};
}

std::cout << std::get<0>(f()) << ", " << std::get<1>(f()) << std::endl;
1, 2

Loop Over a Tuple?

[2]:
#include <iostream>

for (auto x : {1, 2, 3, 4, 5})
    std::cout << x << ", ";
1, 2, 3, 4, 5,

String Literal

[5]:
#include <iostream>
#include <string>

{
//     const char* s = "aaa";  // 可以宣告但不能改內容。string literal 是存在 const 區
//     std::string s = "aaa";  // 可以宣告也可以改內容
//     char* s = "aaa";        // interpreter 不給過。因為 string literal 是 const 所以這樣宣告不合法
    char s[] = "aaa";       // 宣告成 array:可以宣告也可以改內容。其實這樣宣告

    s[0] = 'b';
    std::cout << s << std::endl;
}
baa

Random Practice Questions

[5]:
// reverse a string

#include <algorithm>

std::string s = "The world is a museum of passion projects. ";

std::reverse(s.begin(), s.end());

s
[5]:
" .stcejorp noissap fo muesum a si dlrow ehT"
[3]:
// reverse a string

#include <string>

std::string reverse(std::string& s)
{
    std::string res;
    res.resize(s.size());

    int j = s.size()-1;
    for (const char& c : s)
        res[j--] = c;

    return res;
}

std::string s = "The world is a museum of passion projects. ";

reverse(s)
[3]:
" .stcejorp noissap fo muesum a si dlrow ehT"
[3]:
// 算每個字母出現幾次,不分大小寫,忽略所有非英文字母字元

#include <string>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <cctype>

std::string s = "The world is a museum of passion projects. ";
std::unordered_map<char, int> count_map;

int i = 0, j = s.size() - 1;
while (i <= j) {
    if (!std::isalpha(s[i])) {
        std::swap(s[i], s[j]);
        j--;
    } else {
        s[i] = std::tolower(s[i]);
        i++;
    }
}
s.resize(j + 1);

for (char c : s) {
    count_map[c]++;
}

std::for_each(count_map.begin(), count_map.end(), [](const std::pair<char, int>& e){ std::cout << e.first << ": " << e.second << std::endl; });
n: 1
p: 2
f: 1
j: 1
u: 2
t: 2
h: 1
e: 3
r: 2
s: 5
w: 1
o: 4
l: 1
d: 1
i: 2
c: 1
a: 2
m: 2
[5]:
// 算每個字母出現幾次

#include <string>
#include <unordered_map>
#include <algorithm>
#include <iostream>

std::string s = "The world is a museum of passion projects. ";
std::unordered_map<char, int> count_map;

int i=0, j=s.size()-1;

// 97 - 122: a-z
// 65 - 90: A-Z

while (i<=j){
    if (!((int)s[i] > 96 && (int)s[i] < 123)){
        if (!((int)s[i] > 64 && (int)s[i] < 91)){
            std::swap(s[i], s[j]);
            j--;
        } else {
            s[i] += 32;
            i++;
        }
    } else {
        i++;
    }
}
s.resize(j+1);

for (const char& c : s)
{
    if (count_map.find(c) == count_map.end()){  // not found
        count_map.insert({c, 1});
    } else {
        count_map[c] += 1;
    }
}

std::for_each(count_map.begin(), count_map.end(), [](const std::pair<char, int>& e){ std::cout << e.first << ": " << e.second << std::endl; });   // jupyter c++ kernel can't run structual binding in lambda
n: 1
p: 2
f: 1
j: 1
u: 2
t: 2
h: 1
e: 3
r: 2
s: 5
w: 1
o: 4
l: 1
d: 1
i: 2
c: 1
a: 2
m: 2
input_line_29:2:24: error: use of undeclared identifier 'lambda'
 mime_bundle_repr(*(*((lambda)**)0x7ffcc058a128));
                       ^
input_line_29:2:33: error: expected expression
 mime_bundle_repr(*(*((lambda)**)0x7ffcc058a128));
                                ^

[5]:
[7]:
// 移除重複元素

#include <vector>
#include <unordered_set>
#include <algorithm>
#include <iostream>

void unique(std::vector<int>& a)
{
    std::unordered_set<int> unique_elements;
    int i = 0, j = a.size()-1;
    while (i <= j){
        if (unique_elements.find(a[i]) == unique_elements.end()){  // not found
            unique_elements.insert(a[i]);
            i++;
        } else {
            std::swap(a[i], a[j]);
            j--;
        }
    }
    a.resize(i);
}

std::vector<int> a = {2, 2, 3};

unique(a);

a
[7]:
{ 2, 3 }
[10]:
// 階乘

int factorial(int n)
{
    if (n<2) {
        return 1;
    } else {
        return n*factorial(n-1);
    }
}

factorial(5)
[10]:
120
[9]:
// 判斷是否潤年

bool is_leap_year(int year){
    return ((year%4==0) && (year%100!=0)) || (year%400==0);
}

is_leap_year(1900)
[9]:
false
[6]:
// 找最大值,最小值

#include <iostream>
#include <vector>
#include <limits>

std::vector<int> integers = {0, 5, 2, 6, 3, 1, 5, 7, 8};
int max = -std::numeric_limits<int>::infinity();
int min = std::numeric_limits<int>::infinity();

for(int i : integers){
    max = (i > max) ? i : max;
    min = (i < min) ? i : min;
}

std::vector({max, min})
[6]:
{ 8, 0 }
[2]:
// 找最大值,最小值

#include <iostream>
#include <vector>
#include <algorithm>

std::vector<int> v = {0, 5, 2, 6, 3, 1, 5, 7, 8};

std::vector({*std::max_element(v.begin(), v.end()), *std::min_element(v.begin(), v.end())})
[2]:
{ 8, 0 }
[5]:
// 判斷是否質數

#include <iostream>

bool is_prime(int n)
{
    if (n==1)
        return false;
    for (int i=2 ; i<n ; i++){
        if (n%i==0){
            return false;
        }
    }
    return true;
}

is_prime(98)
[5]:
false
[7]:
// 自訂排序 comp 函數

#include <vector>
#include <utility>
#include <algorithm>

std::vector<std::pair<int, int>> a = {{0, 9}, {5, 4}, {2, 7}, {6, 3}, {3, 6}, {1, 8}, {5, 4}, {7, 2}, {8, 1}};

std::sort(a.begin(), a.end(), [](const std::pair<int, int>& a, const std::pair<int, int>& b){ return a.first < b.first; });

a
[7]:
{ {0 , 9}, {1 , 8}, {2 , 7}, {3 , 6}, {5 , 4}, {5 , 4}, {6 , 3}, {7 , 2}, {8 , 1} }
[10]:
// 算有幾個偶數

#include <vector>
#include <algorithm>

std::vector<int> v = {0, 5, 2, 6, 3, 1, 5, 7, 8, 9, 4, 7, 3, 6, 8, 4, 2, 1};

std::count_if(v.begin(), v.end(), [](const int& n){ return n%2==0; })
[10]:
9
[7]:
// 照字母順序排序並計算出現次數

#include <map>
#include <string>
#include <algorithm>
#include <utility>
#include <iostream>

std::string s = "quantitative";
std::sort(s.begin(), s.end());

std::map<char, int> count;

for (const char& c : s)
    count[c]++;

std::for_each(count.begin(), count.end(), [](const std::pair<char, int>& item){ std::cout << item.first << ": " << item.second << std::endl; } );
a: 2
e: 1
i: 2
n: 1
q: 1
t: 3
u: 1
v: 1