学習内容について

 どうも、ネタ用の本を部屋中探しまわってたら、
読みたい本が大量に出てきたしがないITエンジニアです。
本日は、「Modern C++チャレンジ C++17プログラミング力を鍛える100問」
の内容を見ていこうと思う。

 Modern C++とは、C++11以降の規格を指し、スマートポインターや右辺値参照などの導入により、
従来のC++とは劇的に進化したためそう呼ばれるようになった。

 この本は、外国の方が執筆した内容を翻訳したもので、C++の問題をひたすら解いていく内容となっている。
通常翻訳された本は独特な言い回しだったり、やたらと長ったらしい文章なことが多いのだが、
この書籍は、問題文と解答、解説だけのシンプルな構成で非常に読みやすい部類だと思う。

御託はここまでにして問題を見ていこうと思う。

[問題1]3または5で割り切れる正の整数の総和

与えられた上限までの3または5で割り切れる
正の整数の総和を計算して出力するプログラムを書きなさい。

ヒント

ヒント

何のことはない。単にfor文で指定した値までループしながら、
if文で3で割った余りが0、または、5で割った余りが0の値を探し出し、
その値を加算していくだけである。

ただし、効率的な処理を書くにはもう一工夫いるようだ。

解答

解答

int main()
{
    unsigned int limit = 0;
    std::cout << "Upper limit:";
    std::cin >> limit;
    
    unsigned long long sum = 0;
    for (unsigned int i = 3; i< limit; ++i)
    {
        if (i % 3 == 0 || i % 5 == 0)
            sum += i;
    }
    
    std::cout << "sum=" << sum << std::endl;
}

解説

解説

この問題の解法は、3から(1と2は3で割り切れないから飛ばします)与えられた上限まで、すべての数を反復処理することです。
剰余演算子(%)で、3と5で割った余りが0か調べます。
大きな上限まで加算するためには、変数sumの方にintやlongではなくlong longを使うのがコツです。
そうでないと、ループカウンタが100,000になる前にオーバーフローします。

最後に

ちなみに筆者の解答は以下のような感じだったりする。

筆者の解答例


// 3 または 5 で割り切れる正の整数の総和

// 与えられた上限までの3または5で割り切れる
// 正の整数の総和を計算して出力するプログラムを書きなさい

#include <iostream>

using UINT = uint32_t;

UINT func1(UINT limit)
{
	UINT result = 3;
	for (UINT i = 4; i < limit; ++i)
	{
		// 3または5で割り切れない場合はループを回す
		if (i % 3 && i % 5) continue;
		result += i;	// 3または5のいずれかで割り切れる場合は加算
	}

	return result;
}

int main()
{
    std::cout << func1(50) << std::endl;
    
    return 0;
}

 学びたての型だったりを使ってみたくてこのような解答になった記憶がある。
大きな数字を取り扱えない点に関してはまだまだ未熟といったところである。。。
しかも、よくよく考えると3未満の値を指定した場合も3が入ってしまっている。。。
完全にミスである。上手く書こうとして前提条件を見誤っていたのだろう。
皆には私のミスを反面教師にし、正しく動くプログラムを作る事を優先してほしい。

PS:自分のプログラムのミスに気付いて更新しようとした際、ショートコード内に書いていたコードが全部消えていた時は愕然とした。
何とか元に戻したが、エラーもなく消えるのは勘弁してほしい。。。

 なお、次の問題は下記リンクに貼っておく。
次の問題は最大公約数である。ユークリッドの互除法など数学的な知識があると解きやすいかもしれない。

By ta-boss

One thought on “[C++]Modern C++チャレンジの問題を解く~1問目~”

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です