👌
2つのコードのうち、どっちがよいコードなのかわからなくなったので、記事にしたが自己解決した
int count_report_num(vector<vector<int>> & children, int x){
int mytask = 1;
if(children.at(x).size() == 0){
return mytask;
}
int sum = 0;
for(int c: children.at(x)){
sum+= count_report_num(children,c);
}
sum+=mytask;//自分の分も足す
return sum;
}
int count_report_num(vector<vector<int>> & children,int x){
int mytask = 1;
int sum = mytask;
if(children.at(x).size() == 0){
return mytask; //sumかどっちがいいだろうか
}
for(int c: children.at(x)){
sum+= count_report_num(children,c);
}
return sum;
}
このコードは、atcoderの演習問題で、再帰をしてみましょうというものの一部について、二つの書き方をしてみたもの。
グラフになっているので、子要素を特定し、呼び出して最終的な総数を答える問題。
6
0 0 1 1 4
親要素の番号が入力されて、各それぞれのノードについて、総数を出力する。
各インデックスにおけるそのグラフの大きさを求める問題。
子二つのグラフだったら3
みたいな。
これを、報告に見立てた問題として、演習問題が作成されている。
上は、元コードから、少し変えたもので、
sumの計算を終えた後に、自分自身の分を足し合わせている。
下は、最初に足し合わせている。
下のほうがいいコードな気がする一方で、最初に足したという情報を覚えておけるか心配になってきた。
小さい関数だからいいものの、大きい関数になったときに、
上の書き方のほうが良い気がしている。
使わない段階でsumを定義していることがあまりよくなさそうである。
int count_report_num(vector<vector<int>> & children,int x){
int mytask = 1;
if(children.at(x).size() == 0){
return mytask;
}
int sum = mytask;
for(int c: children.at(x)){
sum+= count_report_num(children,c);
}
return sum;
}
こうすると、mytaskに何が入っているかわかりにくいか。
Atcoderに掲示されていたテストコードが一番いいコードでした。
以下テスト用コードに書かれていたものを引用。
// x番の組織が親組織に提出する枚数を返す
// childrenは組織の関係を表す2次元配列(参照渡し)
int count_report_num(vector<vector<int>> &children, int x) {
// ベースケース
if (children.at(x).size() == 0) {
// 子組織から受け取ることは無いので1枚であることが確定している
return 1;
}
// 再帰ステップ
int sum = 0;
for (int c : children.at(x)) {
sum += count_report_num(children, c);
}
sum += 1; // x番の組織の報告書の枚数(1枚)を足す
return sum;
}
コメントによる補足が保守の観点でもよさそうです。
変数を安易に追加するのも危険だということを学べました。
Discussion