Accelerated C++ Chapter 03
どもどす。
ネスペの午後1は通ってるだろとかぶっこいたのが,先日。
ほいで,あぁ,あれって午後1で落ちているというフラグが立った
ということだったのか,と気づいたのが本日。
ま,どっちみち,午後2で落ちているのでいいんですけど。
さて,やってまいりました,Chapter3です。
メモ
- streamsize は,iomanip で宣言されている。
- median のサンプルは,vector のサイズが1の時に out of bounds する。
- median[mid - 1] => median[-1] にアクセスするので。
そろそろ Exercise 1問の解答が長くなってくるので,分けていきます。
解答については基本的に投げっぱなしジャーマンですお。
リファクタリングの練習とか言っていたのは誰だっ!?
いや,だって,このへんの章では,まだ使える武器がそろってないし・・・という言い訳。
Exercise 3-2
en.wikipedia によると,quartile の定義は色々あるようだけど,
この解答では,大体 meidan というざっくりとした感じで。
というか,これ書いていて気づいたけど,すごい面倒なことをしている気がしてきた。
もっとさっぱりした方法がありそうだ。
#include <iostream> #include <vector> #include <algorithm> #include <iomanip> #include <cstdlib> #include <ctime> #include <cassert> using namespace std; void print_vec(const vector<int>& v) { for (vector<int>::size_type i = 0; i < v.size(); ++i) { cout << v[i] << ", "; } cout << endl; return; } // return a median of elements in [start, end) double median(vector<int> vec, size_t start, size_t end) { assert(start < end); // we don't assume the vector is sorted beforehand. sort(vec.begin(), vec.end()); // target: [start, end) size_t size = end - start; size_t mid = size / 2; if (size == 1) { return vec[start]; } if (size % 2 == 0) { return (vec[start + mid - 1] + vec[start + mid]) / 2; } else { return vec[start + mid]; } } void quartiles(vector<int> vec) { double first_quartile = -1, second_quartile = -1, third_quartile = -1; sort(vec.begin(), vec.end()); second_quartile = median(vec, 0, vec.size()); size_t mid = vec.size() / 2; if (vec.size() % 2 == 0) { // vec[0], ..., vec[mid-2], vec[mid-1], vec[mid], vec[mid+1], ..., vec[vec.size()-1] // ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // the first half the second half first_quartile = median(vec, 0, mid - 1); third_quartile = median(vec, mid + 1, vec.size()); } else { // vec[0], ..., vec[mid-2], vec[mid-1], vec[mid], vec[mid+1], ..., vec[vec.size()-1] // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // the first half the second half first_quartile = median(vec, 0, mid); third_quartile = median(vec, mid + 1, vec.size()); } cout << first_quartile << ", " << second_quartile << ", " << third_quartile << endl; } int main() { vector<int> ivec; const int num_elem = 10; srand(time(NULL)); for (int i = 0; i < num_elem; ++i) { ivec.push_back(rand() % 100); } sort(ivec.begin(), ivec.end()); cout << "Sorted vector:" << endl; print_vec(ivec); cout << "Quartiles are:" << endl; quartiles(ivec); cout << endl; return 0; }
Exercise 3-3
ここで,まだご登場してらっしゃらないmapを使うのはチートか。
#include <iostream> #include <map> using namespace std; int main() { map<string, int> word_occurrences; string w; while (cin >> w) { ++word_occurrences[w]; } map<string, int>::iterator iter; for (iter = word_occurrences.begin(); iter != word_occurrences.end(); ++iter) { cout << "Word: " << iter->first << ", Count: " << iter->second << endl; } return 0; }
Exercise 3-4
#include <iostream> #include <map> using namespace std; int main() { string s, longest, shortest; string tmp; string::size_type max = 0, min = tmp.max_size(), l = 0; while (cin >> s) { l = s.length(); if (l > max) { max = l; longest = s; } else if (l < min) { min = l; shortest = s; } } cout << "Longest: " << longest << endl; cout << "Shortest: " << shortest << endl; return 0; }
Exercise 3-5
うーん,C 臭いコードだね。
おぉ,律儀に関数に static をつけていたのか。えらいね,オレ。
#include <iostream> #include <vector> #include <iomanip> #include <algorithm> using namespace std; static void read_name(string& name) { cout << "Please enter your first name: "; cin >> name; cout << "Hello, " << name << "!" << endl; } static void read_mid_and_final(double& midterm, double& final) { cout << "Please enter your midterm and final exam grades " "separated by whitespace: "; cin >> midterm >> final; } static void read_homeworks(vector<double>& hw) { cout << "Enter all your homework grades separated by whitespace, " "followed by end-of-file: "; double x; while (cin >> x) { hw.push_back(x); } cin.clear(); } static int calc_median(vector<double>& homework, double& median) { vector<double>::size_type size = homework.size(); if (size == 0) { return -1; } else if (size == 1) { median = homework[0]; } else { sort(homework.begin(), homework.end()); vector<double>::size_type mid = size / 2; median = (size % 2 == 0) ? (homework[mid] + homework[mid-1]) / 2 : homework[mid]; } return 0; } static double calc_final_grade(double midterm, double final, double median) { return 0.2 * midterm + 0.4 * final + 0.4 * median; } static void print_final_grade(const vector<string>& names, const vector<double>& final_grades) { streamsize prec = cout.precision(); for (uint i = 0; i < names.size(); ++i) { cout << endl << names[i] << ", Your final grade is " << setprecision(3) << final_grades[i] << setprecision(prec) << endl; } } int main() { vector<string> names; vector<double> final_grades; while (true) { string name; read_name(name); double midterm = 0, final= 0; read_mid_and_final(midterm, final); vector<double> homework; read_homeworks(homework); double median = 0; int ret = calc_median(homework, median); if (ret < 0) { return 1; } double final_grade = 0; final_grade = calc_final_grade(midterm, final, median); // Store a studnet's name names.push_back(name); // Store the corresponding grade final_grades.push_back(final_grade); string cont; cout << "Another student? (y/n): "; cin >> cont; if (cont.compare("n") == 0) { break; } } print_final_grade(names, final_grades); return 0; }
まとめ
vectorとかsortとかでてきて楽しくなる予感がする章でした。
けど,クラスがはまだだいぶ先だ。
それにこの頃はまだ,テストを書いていなかったようだ。