AtCoder

ABC277 B問題(Playing Cards Validation)を解く

AtCoder_ABC277_B

AtCoder が提供しているABC(AtCoder Beginner Contest)277 のB問題をC++とPythonで解いてみました。ABC277は、2022年11月12日21:00に実施されました。

AtCoder の紹介はこちらに、プログラミングの方針はこちらに記事があります。

B問題 Playing Cards Validation(Difficulty : 60)

問題はリンク先をご覧ください。

ABC277 B問題 Playing Cards Validation

トランプのカードを表す一組の文字列が正しいか判断する問題です。AtCoder Problems による Difficulty は、60 でした。ABC B問題として、標準的な問題です。

解答案

問題を解く方針を書きだします。

  • N 個の文字列を読み込む。
  • 以下の条件を確認する。
    • 1文字目が H、D、C、S のどれかである。
    • 2文字目が A、2、3、…、9、T、J、Q、K のどれかである。
    • 文字列がすべて異なる
  • 確認結果に従い、”Yes” か ”No” を出力する。

C++ プログラム例(ABC277B)

最初の版では、候補の文字を char 配列 mark 、number として用意しました。候補の文字のどれかに一致しているかを判断しています。文字列がすべて異なっているかは、set コンテナ u に登録して、u に登録された個数が N に等しいか調べています。

また、条件を満たさないことが判明した時点で、”No” を出力して、プログラムを終了しています。

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

int main()
{
	char mark[] = {'H', 'D', 'C', 'S'};
	char number[] = {'A', '2', '3', '4', '5', '6', '7'
	               , '8', '9', 'T', 'J', 'Q', 'K'};

	int n;
	cin >> n;
	vector<string> s(n);
	set<string> u;
	for (int i = 0; i < n; ++i) {
		cin >> s[i];
		u.insert(s[i]);
	}

	for (int i = 0; i < n; ++i) {
		bool b = false;
		for (int j = 0; j < 4; ++j) {
			if (s[i][0] == mark[j]) {
				b = true;
			}
		}
		if (!b) {
			cout << "No" << endl;
			return 0;
		}
		b = false;
		for (int j = 0; j < 13; ++j) {
			if (s[i][1] == number[j]) {
				b = true;
			}
		}
		if (!b) {
			cout << "No" << endl;
			return 0;
		}
	}

	if (u.size() != n) {
		cout << "No" << endl;
		return 0;
	}

	cout << "Yes" << endl;

	return 0;
}

最初の版から以下2点を改良します。

  • char 配列ではなく、文字列を用意して count 関数で判断する。
  • 複数の return で制御を抜けていて、プログラミング作法上、好ましくない。bool 変数 result に判定結果を保持して、最後に出力する。

この改良2点に対応したプログラムが以下です。最初の版より読みやすくなっています。

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

int main()
{
	string mark = "HDCS";
	string number = "A23456789TJQK";

	int n;
	cin >> n;
	vector<string> s(n);
	set<string> u;
	for (int i = 0; i < n; ++i) {
		cin >> s[i];
		u.insert(s[i]);
	}

	bool result = true;
	for (int i = 0; i < n; ++i) {
		if (count(mark.begin(), mark.end(), s[i][0]) == 0) {
			result = false;
		}
		if (count(number.begin(), number.end(), s[i][1]) == 0) {
			result = false;
		}
	}

	if (u.size() != n) {
		result = false;
	}

	if (result) {
		cout << "Yes" << endl;
	} else {
		cout << "No" << endl;
	}

	return 0;
}

どちらも AC(Accepted=正しいプログラム)と判定されました。

Python プログラム例(ABC277B)

Python 版は、C++ 後者の版をベースにしました。文字列の重複は set を使って確認しました。

"""AtCoder Beginner Contest 277 B"""
n = int(input())
s = [input() for i in range(n)]
mark = "HDCS"
number = "A23456789TJQK"
u = set()
for i in range(n):
    u.add(s[i])

result = True
for i in range(n):
    if mark.count(s[i][0]) == 0:
        result = False
    if number.count(s[i][1]) == 0:
        result = False

if len(u) != n:
    result = False

print("Yes" if result else "No")

こちらも「AC」と判定されました。

最後に

この問題は、条件を漏れなくプログラムできるかが問われています。問題文には、3つの条件が明記されていました。文字列と、重複がないコンテナの操作によって、条件を判断することができました。

ABC277 について、引き続き、C問題まで紹介します。

COMMENT

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

CAPTCHA