AIZU ONLINE JUDGE ITP1_6_Bをpythonで解いてみた

python

本サイトAIZU ONLINE JUDGE ITP1_6_B へはこちらから

目次

問題:不足しているカードの発見

太郎が花子と一緒にトランプ遊びをしようとしたところ、52枚あるはずのカードが n 枚のカードしか手元にありません。これらの n 枚のカードを入力として、足りないカードを出力するプログラムを作成して下さい。

太郎が最初に持っていたトランプはジョーカーを除く52枚のカードです。

52枚のカードは、スペード、ハート、クラブ、ダイヤの4つの絵柄に分かれており、各絵柄には13のランクがあります。

Input

最初の行に太郎が持っているカードの枚数 n (n ≤ 52)が与えられます。

続いて n 組のカードがそれぞれ1行に与えられます。各組は1つの空白で区切られた文字と整数です。文字はカードの絵柄を表し、スペードが’S’、ハートが’H’、クラブが’C’、ダイヤが’D’で表されています。整数はそのカードのランク(1 〜 13)を表しています。

Output

足りないカードをそれぞれ1行に出力して下さい。各カードは入力と同様に1つの空白で区切られた文字と整数です。出力するカードの順番は以下の通りとします:

  • 絵柄がスペード、ハート、クラブ、ダイヤの順番で優先的に出力する。
  • 絵柄が同じ場合は、ランクが小さい順に出力する。

Sample Input

47
S 10
S 11
S 12
S 13
H 1
H 2
S 6
S 7
S 8
S 9
H 6
H 8
H 9
H 10
H 11
H 4
H 5
S 2
S 3
S 4
S 5
H 12
H 13
C 1
C 2
D 1
D 2
D 3
D 4
D 5
D 6
D 7
C 3
C 4
C 5
C 6
C 7
C 8
C 9
C 10
C 11
C 13
D 9
D 10
D 11
D 12
D 13

Sample Output

S 1
H 3
H 7
C 12
D 8

解答例

all_cards = [(s, n) for s in ['S', 'H', 'C', 'D'] for n in range(1, 14)]

n = int(input())
hold_cards = []
for _ in range(n):
    suit, num = input().split()
    num = int(num)
    hold_cards.append((suit, num))
for card in all_cards:
    if card not in hold_cards:
        print(*card)

解説

以下のように解いていきます。

  1. 全てのカードの作成
  2. 1組のカードの組み合わせ(マーク,数字)の取得をn組取得
  3. 足りないカードの出力

(‘S’, 1)から(‘S’, 13)までの13組
(‘H’, 1)から(‘H’, 13)までの13組
(‘C’, 1)から(‘C’, 13)までの13組
(‘D’, 1)から(‘D’, 13)までの13組

上記52組の組み合わせをリスト内包表記で作ります。

リスト内包表記とは

リストを作成する時の方法の一つです。次のような書式を使用します。

[式 for 変数 in イテラブルオブジェクト]

例えば、数値の 0 から 5 までの連続した値を要素に持つリストを作成する場合で考えてみます。要素を直接指定する方法や、空のリストを作成したあとで for 文を使って要素を追加する方法、リストのコンストラクタに range オブジェクトを指定してリストを作成する方法などがあります。

# 要素を直接指定する方法
sample_lst = [1, 2, 3, 4, 5]
print(sample_lst)
# [1, 2, 3, 4, 5]

# 空のリストを作成したあとで for 文を使って要素を追加する方法
max = 5
sample_lst = []
for i in range(1, max + 1):
    sample_lst.append(i)
print(sample_lst)
# [1, 2, 3, 4, 5]

# リストのコンストラクタに range オブジェクトを指定する方法
sample_lst = list(range(1, max + 1))
print(sample_lst)
# [1, 2, 3, 4, 5]

これに対してリスト内包表記を使用した場合は、次のように記述することができます。

max = 5
# range関数の開始値1がiに設定 → i**2 の処理を行う → リストに再設定 ※これを終了値まで繰り返す
sample_lst = [i**2 for i in range(1, max + 1)]
print(sample_lst)
# [1, 4, 9, 16, 25]

リスト内包表記はネストすることも可能です。

sample_lst = [(x, y) for x in [1, 2] for y in ['a', 'b', 'c']]
print(sample_lst)
# [(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c')]

この場合、後に書いた物が内側のループになります。ちょうど以下の二重のfor文と同じです。外側の変数xに1が設定された後、内側のyに’a’, ‘b’, ‘c’が順番に設定され、組み合わせを作成します。

sample_lst = []
for x in [1, 2]:
    for y in ['a', 'b', 'c']:
        sample_lst.append((x, y))
print(sample_lst)
# [(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c')]

今回は、上記のようにリスト内包表記をネスト(2重に)して、トランプの全ての組み合わせを作成します。

以下の場合、for s in [‘S’, ‘H’, ‘C’, ‘D’]の’S’が(s, n)のsに代入された後、次のfor文であるfor n in range(1, 14)を回し、(S,1)~(S,13)までを作り出します。次に(H,1)~(H,13)、(C,1)~(C,13)、(D,1)~(D,13)、という順番で組み合わせを作ります。

# リスト内包表記をネストして全てのカードの組み合わせを作成する
all_cards = [(s, n) for s in ['S', 'H', 'C', 'D'] for n in range(1, 14)]

まずは、キーボードから文字列を受け取る際に使用するinput関数をint関数で囲み、整数値として受け取ります。

続いて、空のリストを用意し、太郎が持っているn 組のカードをひと組みずつinput().split()でsuit(マーク)とnum(数字)に設定、appendメソッドでリストに追加します。

# input()で受け取った値をint関数で囲み、int型として受け取る
n = int(input())
# 空のリストを用意
hold_cards = []
# n組のカードを取得するためにfor文をn回ループする
for _ in range(n):
    # マークと数字を変数suit, numに設定
    suit, num = input().split()
    # 数字numを文字列(str)型から整数(int)型に変換
    num = int(num)
    # リストに追加する
    hold_cards.append((suit, num))

1で作成した全てのカードから2で作成した太郎が持っているカードの差分を出力します。

for文のイテラブルにall_cardsを設定し、全てのカード(all_cards)から変数(card)を一つずつ取り出します。if文ではnot演算子を使用し、変数(card)が太郎が持っているカード(hold_cards)の中にない場合に条件式がTrueになり、そのカードをprint関数で表示します。

# 全てのカード(all_cards)を一つずつ取り出し、変数(card)に代入
for card in all_cards:
    # cardがhold_cardsにないときTrueになる
    if card not in hold_cards:
        # 太郎が持っているカード(hold_cards)に無いものを表示
        print(*card)

最後に、もう一度プログラムを確認してみましょう。

# リスト内包表記をネストして全てのカードの組み合わせを作成する
all_cards = [(s, n) for s in ['S', 'H', 'C', 'D'] for n in range(1, 14)]

# input()で受け取った値をint関数で囲み、int型として受け取る
n = int(input())
# 空のリストを用意
hold_cards = []
# n組のカードを取得するためにfor文をn回ループする
for _ in range(n):
    # マークと数字を変数suit, numに設定
    suit, num = input().split()
    # 数字numを文字列(str)型から整数(int)型に変換
    num = int(num)
    # リストに追加する
    hold_cards.append((suit, num))
# 全てのカード(all_cards)を一つずつ取り出し、変数(card)に代入
for card in all_cards:
    # cardがhold_cardsにないときTrueになる
    if card not in hold_cards:
        # 太郎が持っているカード(hold_cards)に無いものを表示
        print(*card)
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

雇われのシステムエンジニアです。
普段は車載ECUのセキュリティー分野に従事しております。

■保有資格
Salesforce 認定 Platform アプリケーションビルダー
Salesforce 認定 Platform デベロッパー

コメント

コメントする

目次