つよつよエンジニアになりたい

つよつよエンジニアになりたいエンジニアが日々の学びや気づきをアウトプットしていきます

AtCoder Beginner Contest 282に参加してきました

12/17(土)に開催されたHHKBプログラミングコンテスト2022 Winter(AtCoder Beginner Contest 282に参加してきました。

C問題まで解けて得点は600でした。最近C問題を徐々に解けるようになってきて嬉しいのですが、AtCoder Problemsを見るとC問題までは灰色コーダーでもある程度は解ける難易度のようなのでC問題解答までの速度を上げつつD問題もなんとか解けるようにしていきたいです。茶色コーダーまでの道のりはまだ遠いなと思いました、、 今回は自分が解けたC問題までの解法を記していきます。

A問題

解法

少し面倒だが英大文字A~Zまでの文字列を用意してそれをk個出力するようにしました。

提出コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    int k;
    cin >> k;
    string S = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for (int i=0; i<k; i++) cout << S.at(i);
    cout << endl;
}

公式

c++では char('A' + i) とすることで英大文字を順番に出力してくれるらしいです。0がA、1がBといった感じ。

int main() {
    cout << char('A' + 0) << endl;
    cout << char('A' + 1) << endl;
    cout << char('A' + 2) << endl;
    cout << char('A' + 3) << endl;
}

// 結果
// A
// B
// C
// D

解説コード

#include <bits/stdc++.h>
using namespace std;
int main() {
    int k;
    cin >> k;
    for(int i = 0; i < k; i++) {
        cout << char('A' + i);
    }
}

B問題

解法

N人の内から2人を選び、両方に✖️がなければカウントするという方法で解きました。

N人の内から2人を選ぶプログラムは2重ループで実現できます。以下は5つのグループから2つを選択するプログラムです。この場合は1:2と2:1を区別しています。問題では参加者のペアを順番は関係なく選択するためこの方法では選び方のかぶりが出てしまいます。

int main() {
    for (int i=1; i<=5; i++) {
        for (int j=1; j<=5; j++) {
            cout << i << ":" << j << " ";
        }
        cout << endl;
        cout << "====================" << endl;
    }
}

// 結果
// 1:1 1:2 1:3 1:4 1:5 
// ====================
// 2:1 2:2 2:3 2:4 2:5 
// ====================
// 3:1 3:2 3:3 3:4 3:5 
// ====================
// 4:1 4:2 4:3 4:4 4:5 
// ====================
// 5:1 5:2 5:3 5:4 5:5 
// ====================

被りをなくすためには2番目のforループの開始を i+1 にすればOKです。

int main() {
    int n;
    cin >> n;
    for (int i=1; i<=n; i++) {
        for (int j=i+1; j<=n; j++) {
            cout << i << ":" << j << " ";
        }
        cout << endl;
        cout << "====================" << endl;
    }
}

// 結果
// 1:2 1:3 1:4 1:5 
// ====================
// 2:3 2:4 2:5 
// ====================
// 3:4 3:5 
// ====================
// 4:5 
// ====================
//  
// ====================

上記のプログラムを活用してN人の中から2人を選びます。選んだ2人のそれぞれの問題が○か✖️かを判定するためにforループを使います。両方✖️の問題はフラグをfalseにしてカウントしません。

提出コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n,m,count=0;
    cin >> n >> m;
    vector<string> s(n);
    for (int i=0; i<n; i++) cin >> s.at(i);
    for (int i=0; i<n-1; i++) {
        for (int j=i+1; j<n; j++) {
            bool flg = true;
            for (int k=0; k<m; k++) {
                if(s.at(i).at(k) == 'x' && s.at(j).at(k) == 'x') {
                    flg = false;
                }
            }
            if (flg) count++;
        }
    }
    cout << count << endl;
}

C問題

解法

  • , を一旦全て . に置き換える
  • 最初の " が来たらフラグをtrueにしてその間に . があれば , に置き換える
  • 次に " が来たらフラグをfalseにする

というようなアルゴリズムを考えコードに落とし込みました。

今考えると全て . に置き換える必要はなく、フラグがfalseの場合は . に置き換えるという処理とすればもう少し短いコードが書けたかなと思いました。

提出コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    string s;
    cin >> n >> s;
    s = regex_replace(s, regex(","), ".");
    bool flg = false;
    for (int i=0; i<n; i++) {
        if (s.at(i) == '.' && flg) {
            s.at(i) = ',';
        };
        if (s.at(i) == '"' && flg){
            flg = false;
            continue;
        }
        if (s.at(i) == '"' && !flg){
            flg = true;
            continue;
        }
    }
    cout << s << endl;
}