Help us understand the problem. What is going on with this article?

ABC 過去問で始める競技プログラミング #5

ABC 過去問で始める競技プログラミング第五回です。
前回の記事はこちらです。
今回は for 文と while 文について書いていきます。

0. for 文とは

for 文は決まった回数同じ操作を繰り返したいときに使う構文です。

#include<bits/stdc++.h>
using namespace std;
int main(){
    for(int i = 0; i < 5; i++){
        cout << 1 << endl;
    }
}

このコードを実行すると次のような結果になります。

1
1
1
1
1

「 1 を出力して改行 」 が 5 回実行されています。
それでは具体的に構文の意味を見ていきましょう。
for 文の () の中には ; で区切られた三つの要素があります。
一つ目は i の宣言と初期化です。 二つ目は条件式。条件式が真である間 for 文が実行されます。三つ目は for 文が一周するごとに行われる操作です。

i の初期化は 0 で行われることが一般的です。これによりうれしいことがあるのですがそれはのちほど。

図で表すと下のようなことが行われています。
スクリーンショット 2020-02-10 13.37.45.png

i++ というのは i = i + 1 と同じで i に 1 を足す操作を表します。
つまり {} の中身を 1 回実行するごとに i に 1 足されていき、 i < N の間実行されます。
言い換えると i が N になったら for 文から抜けるのでそれまでの N 回ループするということです。

では問題を解いて実際に使ってみましょう。

1. ABC101-A Eating Symbols Easy

問題へのリンクはこちら。
https://atcoder.jp/contests/abc101/tasks/abc101_a

ans という答えとなる変数を考えます。
そして S の 1 文字目から 4 文字目をそれぞれ見て、 + か - かをチェックし、答えに 1 を足すか引くかすればよいです。
四つだけなのでまずは一つずつチェックする解答例を挙げます。

#include<bits/stdc++.h>
using namespace std;
int main(){
    string S;
    cin >> S;
    int ans = 0;
    if(S [ 0 ] == '+'){
        ans++;
    }
    else{
        ans--;
    }
    if(S [ 1 ] == '+'){
        ans++;
    }
    else{
        ans--;
    }
    if(S [ 2 ] == '+'){
        ans++;
    }
    else{
        ans--;
    }
    if(S [ 3 ] == '+'){
        ans++;
    }
    else{
        ans--;
    }
    cout << ans <<endl;
}

とても長いコードになってしまいましたが確かにこれで AC できます。
しかしこんなコードを書くのは面倒ですよね。
そこで見直してみると 4 回ともほぼ同じ操作をしていることに気付きます。
同じ操作を 4 回...... ! for 文を使えばいいじゃない ( ゴリ押し ) 。

そこで 4 回ループを回しますが、そのときの i は 0 → 1 → 2 → 3 となって終了します。
それを踏まえてもう一度コードを見ると if 文の条件式の中に i と一致するものがでてきていますね。
一回目のループ ( i = 0 ) では S [ 0 ] をチェック、二回目のループ ( i = 1 ) では S [ 1 ] をチェックしているのです。 S [ i ] をチェックしているということですね。
これが i を 0 で初期化するときにうれしいことです。

これをまとめると次のようなコードを書くことができます。

#include<bits/stdc++.h>
using namespace std;
int main(){
    string S;
    cin >> S;
    int ans = 0;
    for( int i = 0; i < 4; i++){
        if( S [ i ] == '+'){
            ans++;
        }
        else{
            ans--;
        }
    }
    cout << ans << endl;
}

これはさっきのコードとまったく同じ挙動をすることがおわかりでしょうか。
このように同じ操作の繰り返しをするときに便利なのが for 文になります。

今回は文字列の長さが 4 で固定だったのですが、次はループの回数が定数でない場合について考えてみましょう。

2. ABC072-B OddString

問題へのリンクはこちら。
https://atcoder.jp/contests/abc072/tasks/abc072_b

与えられた奇数番目の文字だけ出力する操作になります。
注意すべきは人とコンピュータで数え方が 1 つずれているので、人間にとっての奇数番目はコンピュータにとって偶数番目だということです。
解答例はこちらです。

#include<bits/stdc++.h>
using namespace std;
int main(){
    string S;
    cin >> S;
    for(int i = 0; i < S.size(); i++){
        if(i % 2 == 0){
            cout << S [ i ];
        }
    }
    cout << endl;
}

文字列の長さが 4 のときはループの条件式を i < 4 にしたので今回は i < S.size() にすると S の各文字を網羅できます。

i を 0 から S.size() - 1 まで増やしていき、 i を 2 で割ったあまりが 0 のとき S [ i ] を出力するというコードになっています。
i が 偶数のときのみ S [ i ] を出力するので問題に合うコードですね。

最後の改行を忘れないようにしましょう。


今回はこれで以上になります。
お読みいただきありがとうございました。
for 文の理解ができましたでしょうか。
少し慣れないかもしれませんが、練習して使えるようになりましょう。

関連問題を挙げます。
ABC111-A AtCoder Beginner Contest999
ABC084-B Postal Code
ABC058-B ∵∴∵

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした