競技プログラミング風 標準C++ライブラリ入門【第1回】
競技プログラミング風 標準C++ライブラリ入門【第1回】
標準C++ライブラリとは、C++で標準的に用意されているクラス・関数ライブラリのことだ。 ヘッダをインクルードするだけですぐに使える便利なクラス・関数が多数用意されている。 同じようなものを自作しようとすると、そこそこの工数も必要だし、高品質(バグがなく高速)にするのは大変だ。 なので、これを使わないC++erは人生をずいぶん損していることになる。
合計4回の本連載では、標準C++ライブラリの競技プログラミング風問題を全部で12問用意した。 問題難易度は比較的簡単なものなので、気軽にどんどん解けるものばかりだ。 正確に言えば、標準C++ライブラリを使用すれば簡単という問題なので、 標準C++ライブラリをマスターしようという動機づけになることを意図している。 競技プログラミング風の問題を多数解くことで、標準C++ライブラリの基本を少しでも知ってもらいたいというわけだ。
各問題は、「問題文」「テストコード」「ヒント」「解答例」「解説」から構成される。
まず、問題を読んで正しく理解し、テストコード部分をIDEやテキストエディタまたはweb上のコンパイラ (ideonなど)で保存・ビルド・実行し、 NGが出ないようにテストコードの「ToDo:」部分のコードを完成させてほしい。
「ヒント」「解答例」「解説」はデフォルトでは非表示になっており、中身を読みたい場合は【show】ボタンを押せば表示される。 これらをすぐに読むのではなく、ちゃんと解答を考え、使用する標準ライブラりのクラス・関数をweb検索して勉強し、 コード記述・ビルド・実行してからそれらを読むのを強く推奨する。なにごとも自分で考え、いろいろ試した上で、解答などを見るようにするのが肝要だ。 その方が解答が印象に残り問題解決方法が記憶に定着しやすいのだ。
目次
ハローワールド(難易度:★☆☆☆☆)
文字列 “Hello, World.” を返す関数 string hello() を実装しなさい。
[java] #include <iostream> // 標準入出力ライブラリ#include <string>
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 hello() {
return ""; // ToDo: ここを書き換えて "Hello, World." を返す
}
int main() {
DO_TEST( hello() == "Hello, World." );
cout << "\nGood Job!\n";
return 0;
}
[/java]
動的配列生成(難易度:★☆☆☆☆)
参照引数で渡された動的配列に、{3, 1, 4, 1, 5} の要素を設定する関数 void setPI(vector<int>& v) を実装しなさい。
[java]
#include <iostream> // 標準入出力ライブラリ
#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 setPI(vector<int>& v) {
// ToDo: ここにコードを追加し v の要素を {3, 1, 4, 1, 5} に設定する
}
int main() {
vector<int> v;
setPI(v);
DO_TEST( v.size() == 5 );
DO_TEST( v[0] == 3 );
DO_TEST( v[1] == 1 );
DO_TEST( v[2] == 4 );
DO_TEST( v[3] == 1 );
DO_TEST( v[4] == 5 );
cout << "\nGood Job!\n";
return 0;
}
[/java]
下駄を履かせる(難易度:★★☆☆☆)
引数で渡された vector<int>型への参照の各要素に第2引数を加える関数 void geta(vector<int>& v, int a) を実装しなさい。
例えば、v に {1, 2, 3}, a に 1 が渡された場合、v の内容は {2, 3, 4} となる。
※ オーバーフローは考慮しなくてよいものとする。
[java]
#include <iostream>
#include <vector>
using namespace 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 geta(vector<int>& v, int a) {
// ToDo: ここにコードを追加し v の各要素に a を加える
}
int main()
{
vector<int> v1 = {1, 2, 3};
geta(v1, 1);
DO_TEST( v1 == vector<int>({2, 3, 4}) );
vector<int> v2 = {1, 2, 3, 4};
geta(v2, -2);
DO_TEST( v2 == vector<int>({-1, 0, 1, 2}) );
cout << "\nGood Job!\n";
return 0;
}
// ※ vector<int>({1,2,3}) という書き方は まみむめも氏(https://twitter.com/hu_123456)にご教授いただきました。さんくす
[/java]
競技プログラミング風 標準C++ライブラリ入門 連載目次リンク
筆者:津田伸秀 プロフィール:テニス・オセロ・ボードゲーム・パズル類が趣味の年齢不詳のおじさん。 自宅研究員(主席)。vi と C++が好き。迷走中・・・ ボードゲーム・パズル系アプリ開発・リリースしてます。 |