競技プログラミング風 標準C++ライブラリ入門【第11回】
競技プログラミング風 標準C++ライブラリ入門【第11回】
今回も、標準C++ライブラリの基本をマスターするための競技プログラミング風問題を解いていただこう。
問題を理解したら、テストコードをコンパイル・実行していただきたい。そのままだと実行時に「NG」が表示される。 コードを完成させ、「Good Job!」を表示させてすっきりしてほしい。グッドラック!
目次
Nの倍数を0に置換(難易度:★★☆☆☆)
引数で渡された vector<int>& lst の各要素が第2引数Nの倍数の場合は0に置換する関数 void replaceNxTo0(vector<int>& lst, int N) を実装しなさい
例えば、lst: {3, 1, 4, 1, 5, 9, 2, 6}, N: 2 の場合、lst は {3, 1, 0, 1, 5, 9, 0, 0} となる。
ただし、N>0 とし、Nが0以下の場合は、何も処理を行わないものとする。
[java]
#include <iostream> // 標準入出力ライブラリ
#include <algorithm>
#include <vector>
using namespace std; // std 名前空間使用
#define DO_TEST(exp) do_test(exp, __LINE__)
void do_test(bool b, int line) {
if( b ) return; // OK
cout << "\nNG at line " << line << "\n";
exit(1);
}
void replaceNxTo0(vector<int>& lst, int N) {
// ToDo: 標準関数を使い、ここを書き換えて、Nの倍数のlst要素を0に置換する
}
int main() {
vector<int> lst1 = {3, 1, 4, 1, 5, 9, 2, 6};
replaceNxTo0(lst1, 2);
DO_TEST( lst1 == vector<int>({3, 1, 0, 1, 5, 9, 0, 0}) );
cout << "\nGood Job!\n";
return 0;
}
[/java]
スマートポインタ(難易度:★★☆☆☆)
テストコードの「ここから」「ここまで」の部分を修正して、lst を resize() で縮小するとオブジェクトが自動的に破棄されるようにしなさい。
テストコードで定義している CTest クラスは、コンストラクタがコールされるとカウンタをインクリメントし、 デストラクタがコールされるとカウンタをデクリメントするようになっている。
[java]
#include <iostream> // 標準入出力ライブラリ
#include <vector>
//#include <memory>
using namespace std; // std 名前空間使用
#define DO_TEST(exp) do_test(exp, __LINE__)
void do_test(bool b, int line) {
if (b) return; // OK
cout << "\nNG at line " << line << "\n";
exit(1);
}
int g_objCount = 0; // オブジェクト数
struct CTest {
CTest() { ++g_objCount; } // オブジェクト数をインクリメント
~CTest() { –g_objCount; } // オブジェクト数をデクリメント
};
int main() {
const int N_OBJECT = 10;
const int N_RESIZED = 7;
//—–ここから—–
// ToDo: 以下を書き換え、lst を resize() で縮小するとオブジェクトが自動的に破棄されるよう修正
vector<CTest*> lst;
for (int i = 0; i != N_OBJECT; ++i)
lst.push_back(new CTest);
//—–ここまで—–
DO_TEST(g_objCount == N_OBJECT);
lst.resize(N_RESIZED); // lst を縮小
DO_TEST(g_objCount == N_RESIZED);
cout << "\nGood Job!\n";
return 0;
}
[/java]
マルチスレッド(難易度:★★☆☆☆)
テストコードの ToDo 部分を書き換え、複数の関数 foo(char) が同時並行的に実行されるようにしなさい。
テストコードをそのまま実行すると、foo(‘A’) で「AAAAAAAAAA」が、foo(‘Z’) で「ZZZZZZZZZZ」が表示されるので、 トータルで「AAAAAAAAAAZZZZZZZZZZ」と表示され。 それらを同時並行的に実行すると「AZAZAZAZAZAZAZAZAZAZ」のように ‘A’ と ‘Z’ が混ざって表示される (ただし、このようにキレイに交互に混ざるとは限らない)。
[java]
#include <iostream> // 標準入出力ライブラリ
#include <thread>
using namespace std; // std 名前空間使用
#define DO_TEST(exp) do_test(exp, __LINE__)
void do_test(bool b, int line) {
if( b ) return; // OK
cout << "\nNG at line " << line << "\n";
exit(1);
}
string g_out;
void foo(char ch) {
for(int i = 0; i != 10; ++i) {
g_out += ch;
cout << ch;
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100ミリ秒ウェイト
}
}
int main() {
//—–ここから—–
// ToDo: マルチスレッドで foo(‘A’), foo(‘Z’) を起動するよう修正
foo(‘A’);
foo(‘Z’);
// ToDo: マルチスレッドで起動された foo(‘A’), foo(‘Z’) が終了するまで待つよう修正
//—–ここまで—–
DO_TEST(g_out != "AAAAAAAAAAZZZZZZZZZZ");
cout << "\nGood Job!\n";
return 0;
}
[/java]
競技プログラミング風 標準C++ライブラリ入門 連載目次リンク
筆者:津田伸秀 プロフィール:テニス・オセロ・ボードゲーム・パズル類が趣味の年齢不詳のおじさん。 自宅研究員(主席)。vi と C++が好き。迷走中・・・ ボードゲーム・パズル系アプリ開発・リリースしてます。 |