ABC 212 A問題 Python解説

ABC212 A-Alloy

問題はこちら

Pythonでの解法】

まず解答例を下に示します。

A,B = map(int,input().split())
result = ["Gold", "Silver", "Alloy"]
ans = ""

if A > 0 and B == 0:
  ans = result[0]
elif A == 0 and B > 0:
  ans = result[1]
else:
  ans = result[2]

print(ans)

1. 問題文の把握

純金と純銀の量が与えられるので、混ぜて生成された金属が「純金」「純銀」「合金」のどれに該当するかを判定します。判定基準は問題文にある通りで、純銀の量が0なら「純金」、純金が0なら「純銀」、純金、純銀ともに0より大きい量であれば「合金」となります。

2. コードを考える

(0) 標準入力
スペース区切りで2つの文字列が与えられます。この文字列は後々、数値として扱うためint型にしておきます。そこで、map()を用いてintinput().split() をまとめて行い、2つの数値を変数A,Bにそれぞれ代入します。

A,B = map(int,input().split())

(1) 下準備
今回の出力内容はGold,Silver,Alloyなので、これを要素とするリストresultを予め用意しておくこととします。さらに、この出力内容を代入する変数ansも空の状態で事前に用意します。
ここまでのコードは次の通りです。

A,B = map(int,input().split())
#以下が新規追加分
result = ["Gold", "Silver", "Alloy"]
ans = ""

(2) 根幹
問題文の条件の通りにif文を書いていきます。 0 \lt Aかつ B=0なら変数ansにreslut[0]を代入することでansにはGoldが格納されます。同様に、条件に応じてresult[1],result[2]をansに代入します。
尚、 0 \lt Aかつ 0 \lt Bの場合は条件式を書かずelseで事足ります。( 0 \lt A+Bという式があるため、A,B共に0ということはあり得ません。従って、「純金」「純銀」の条件以外は「合金」となります。)

A,B = map(int,input().split())
result = ["Gold", "Silver", "Alloy"]
ans = ""
#以下が新規追加分
if A > 0 and B == 0:
  ans = result[0]
elif A == 0 and B > 0:
  ans = result[1]
else:
  ans = result[2]

(3) 出力
変数ansにはGold,Silver,Alloyのいずれかが格納されているので、最後にansを出力しておしまいです。

A,B = map(int,input().split())
result = ["Gold", "Silver", "Alloy"]
ans = ""

if A > 0 and B == 0:
  ans = result[0]
elif A == 0 and B > 0:
  ans = result[1]
else:
  ans = result[2]
#以下が新規追加分
print(ans)

これで解答例のコードが完成しました!

3. まとめ

いかがでしたでしょうか?問題文も決して抽象的ではなく題意の把握は容易だったのではないでしょうか。
コードで用いる文法もif文が中心でしたので、書きやすかったはずです。
次回は引き続きABC212のB問題を扱う予定です。次回もお楽しみに!

ABC 211 B問題 (別解)Python解説

この記事では前回も扱ったABC211 B問題の別解をご紹介します。たったの2行だけで完結するコードです!

AtCoder Beginner Contest 211 B-Cycle Hit

問題はこちら

Pythonでの解法】

まず解答例を下に示します。

S = [input() for _ in range(4)]
print("Yes" if len(set(S)) == 4 else "No")

1. 問題文の把握

題意の把握は前回と同じ内容になるため割愛します。

2. コードを考える

(0) 標準入力
前回と同様に、リスト内包表記を使って改行区切りで与えられた4つの文字列を1つのリストに格納します。

S = [input() for _ in range(4)]

(1) 根幹
所与の文字列群にH,2B,3B,HRの全てがあるかどうかを判定するには、それらを格納したリストの要素数を調べることで事足ります。ただし、純粋にリストSではなくsetを用います。set(リスト名)とすることで、当該リストの要素のうち重複するものは1つに集約されます。
そこで、set(S)素数が4(つまり、len(set(S)) == 4)であればH,2B,3B,HRが揃っていると判断できます。(例えば仮に、S[2B,2B,3B,HR]であれば set(S){2B,3B,HR}となりlen(set(S)) == 3ですし、Sが[H,H,H,H]であればset(S){H}となりlen(set(S)) == 1となります

(2) 出力
三項演算子を用いることで、set(S)の要素数が4の場合はYes、そうでない場合はNoを出力するコードを1行にまとめて書くことができます。

S = [input() for _ in range(4)]
#以下が新規追加分
print("Yes" if len(set(S)) == 4 else "No")

以上で、解答例が完成しました!

3. まとめ

今回はABC211 B問題の別解を解説しました。考え方を変え、コードを変えることでたった2行で済ますことができました。絶対に必要な標準入力を除けば1行で、この問題のコードを書くことができたわけです。このように複数パターンのコードを考えるのは良い勉強になりますし、最初に書いたコードよりも短く書けるとテンションが上がりますね!
次回はまた新しい問題に取り組んでいきますので、お楽しみに!

ABC211 B問題 Python解説

AtCoder Beginner Contest 211 B-Cycle Hit

問題はこちら

Pythonでの解法】

まず解答例を下に示します。

S = [input() for _ in range(4)]
hits = ["H", "2B", "3B", "HR"]
flag = True

for i in hits:
  if i not in S:
    flag = False
    break

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

1. 問題文の把握

文字列 S_iはH,2B,3B,HRのどれかであり、 S_1から S_4までにH,2B,3B,HRが揃っているか?(1つずつ存在しているか?)を判定する問題です。
野球のルールを知っている方ならタイトル"Cycle Hit"から、理解が容易かもしれません。問題文に明記はないものの、Hはヒット、2Bはツーベースヒット(二塁打)、3Bは スリーベースヒット(三塁打)、HRはホームラン(本塁打)を指していると思われます。

2. コードを考える

(0) 標準入力
本問では、改行区切りで文字列が与えられます。そこで、input().split()は使えません。与えられる文字列は4つと決まっているため、各行の文字列をinput()で受け取るという処理を4回行えば文字列全てを得ることができます。ですので、最も原始的な方法は次の通りです。

#一番原始的な方法
S1 = input()
S2 = input()
S3 = input()
S4 = input()

しかし、折角繰り返し処理の書き方を知っている訳ですから、使わない手はありません。上のコードをfor文で書き換えようとするとき、初心者が最初に思いついてうっかり書いてしまいそうな間違ったコードを下に示します。

#間違ったコード
for i in range(4):
  S = input()

確かにこれはinput()を4回繰り返す処理です。しかし、これでは標準入力で受け取る度に変数Sに格納される文字列が更新されてしまい、繰り返し処理が終わった時には  i = 3 の時の文字列( S_4)しか残っていません。つまり  S_1,  S_2,  S_3 がどこにも記憶されず、後々処理に使えません。
そこで、標準入力で受け取った文字列を記憶させる場所を用意する必要があります。それがリストです。リストを使うと次のような書き方になります。

#書き方その1
S = []
for i in range(4):
  hit = input()
  S.append(hit)
#ラスト2行をまとめてS.append(input())と書いても同じ

まず空のリストSを用意しておきます。その後、「標準入力で文字列( S_i)を変数hitに格納した上でhitをappend()でリストSの要素として加える」という処理をfor文を用いて4回繰り返しています。これにより、リストSに標準入力で与えられるデータ全てを記憶させることができます。
基本的にはこれで良いのですが、解答例ではこの処理を1行にひとまとめにしています。それが解答例の1行のコードです。

#書き方その2
S = [input() for _ in range(4)]

リスト内包表記という書き方を用いて4行(3行)を1行に短縮しています。内包表記の詳細については割愛するので各自調べ頂きたいのですが、[]の中に標準入力の受け取り処理input()とfor文を書くことで、書き方その1と同じように改行区切りの文字列をそれぞれ要素に持つリストを作ることができます。(繰り返し変数に代入することはないため、_を用いています。書き方その1でも_で問題ありません)
今回の解答例では、この書き方その2を採用しております。長くなりましたが、標準入力の説明は以上になります。
(1) 方針と下準備
与えられた4つの文字列(リストSに格納した文字列群)にH, 2B, 3B, HRが1つずつあるかを調べたいので、予めH, 2B, 3B, HRを要素に持つリストhitsを用意して、このリストhitsの要素がそれぞれリストSにもあるかを調べていくことにします。
さらに、H, 2B, 3B, HRが1つずつあったかどうかを記憶させる変数flagも用意しておきます。(出力する時の判断基準的役割です)この時、ブール値を用いてflagをTrueとしておきます。(4つ全て揃っている前提としておき、もしそうでなければflagをFalseに変える方針でいきます)
ここまでのコードは次の通りです。

S = [input() for _ in range(4)]
#以下が新規追加分
hits = ["H", "2B", "3B", "HR"]
flag = True

(2) 根幹
for文を用いてリストhitsの要素(H, 2B, 3B, HR)を取り出し、リストSにあるかどうかを調べます。 この時、予めflag = True としたので、リストSになかった場合にflagを変えるため、not in を用いてif文を書きます。 また、flagがFalseになった時点でfor文を繰り返す必要がなくなるため、ここではbreak も書いています。

S = [input() for _ in range(4)]
hits = ["H", "2B", "3B", "HR"]
flag = True
#以下が新規追加分
for i in hits:
  if i not in S:
    flag = False
    break

(3) 出力
最後はお馴染みの三項演算子を用いて、flagがTrueならYesFalseならNoを出力します。この時点でflagがTrueということは、if文の条件式が一度も成立しないままfor文が終わったことを意味します。つまり、H, 2B, 3B, HRの4つ全てが与えられた文字列群に揃っていたということになります。

S = [input() for _ in range(4)]
hits = ["H", "2B", "3B", "HR"]
flag = True

for i in hits:
  if i not in S:
    flag = False
    break
#以下が新規追加分
print("Yes" if flag else "No")

これで解答例が完成しました!

3. まとめ

お疲れ様でした。いかがでしたでしょうか?今回はリスト内包表記を用いるに至るまでの標準入力の説明もあり、これまでの最長の記事となってしまいました。データの与えられ方はいつもスペース区切りではありません。改行区切りにもちゃんと対応できるようにしておく必要があります。
それ以外の文法はif文、for文がメインとなっているため、そこまで難しくはなかったかもしれません。
それでは、次回の記事もお楽しみに!(次回は211 B問題の別解をご紹介します!別解はたったの2行で書き終えてしまう方法となっています!是非そちらもご覧下さい)

AtCoder Beginner Contest 210 B問題 Python解説

ABC210 B-Bouzu Mekuri

問題はこちら

Pythonでの解法】

まず解答例を下に示します。

N = int(input())
S = input()
X = 0

for i in range(N):
  if S[i] == "1":
    X = i + 1
    break

print("Takahashi" if X % 2 != 0 else "Aoki")

1. 問題文の把握

与えられる文字列Sが何を意味しているかをまず把握する必要がありますが、端的に言うと、0と1からなる文字列Sは山札を表しています。
カードには良い悪いの2種類があり、1枚目から順に良いカードなら0悪いカードなら1として表現されます。 入力例1で言えば00101 ですので、この例の山札は良い良い悪い良い悪いの順になっているということです。
そして、「高橋君と青木君のどちらが負けるか」というのを言い換えると「どちらが先に悪いカードを食べるか」ということであり、それは「文字列Sを左から順に見ていき最初に1が出てくるのは何文字目(何番目)か?」という意味になります。あとは、これをコードに落とし込んでいくだけですので、早速具体的にコードを考えていきましょう。

2. コードを考える

(0) 標準入力
今回は非常にシンプルなデータの受け取りです。Nは整数として、Sは文字列として受け取ります。
(1) 準備
問題文の把握の最後に述べた通り、「文字列Sにおいて最初に現れる1が何番目か?」が敗者決定の判定基準となりますので、その数字を格納する変数を予め自分で用意し、その初期値を0としておきます。 (0) 標準入力と合わせて、次のようなコードとなります。

N = int(input())
S = input()
X = 0

(2) 根幹
文字列Sにおいて1が何番目に出てくるかを知りたいので、Sを一文字ずつ取り出して調べてみることにします。
そこで、for文if文を使い、一文字ずつ取り出して1かどうかを確認します。もし1であればそれが何番目かをXに記憶させます。よって、次のようなコードを書いていきます。

N = int(input())
S = input()
X = 0
#以下が新規追加分
for i in range(N):
  if S[i] == "1":
    X = i + 1
    break

このとき、1は整数ではないのでif文の条件式では"1" と書くことに注意が必要です。また、for文の繰り返し変数iには0から順に代入されていきますので、順番を表す変数Xに代入するときは1を加えることも忘れないようにしましょう。
そして、このゲームでは最初に悪いカードを食べた人が負けというルールのですので、最初の1が出たらそこで繰り返し処理は終了する必要があります。(もし、複数枚の悪いカードがあり、それらが奇数番目、偶数番目それぞれにあった場合に繰り返し処理を続けてしまうと変数Xが更新されてしまい正しい答えが得られません。)そこで、if文の中に1が出たらその時にfor文が終了するようにbreakを書いておきます。

(3) 出力
問題文より、カードを引くのは奇数番目が高橋君、偶数番目が青木君だと分かるので、Xが奇数ならTakahashi、偶数ならAokiが出力されるようにprint()を書きます。今回も解答例では三項演算子を用いています。
コードは次のようになります。

N = int(input())
S = input()
X = 0

for i in range(N):
  if S[i] == "1":
    X = i + 1
    break
#以下が新規追加分
print("Takahashi" if X % 2 != 0 else "Aoki")

以上で解答例のコードが完成しました!

3. まとめ

いかがでしたか?A問題と違い、問題文をそのままコードにはできない問題でした。「どちらが負けるか?」という問題を「文字列において最初に現れる1の順番は?」という問題に帰着できれば、B問題と言っても文法的に難しい部分は無かったのではと思います。自力でできなかった方は是非、再度チャレンジしてみてください。
今回も最後までお読みいただきありがとございました。次回の記事もお楽しみに!

AtCoder Beginner Contest 210 A問題 Python解説

ABC210 A-Cabbages

問題はこちら

Pythonでの解法】

まず解答例を下に示します。

N,A,X,Y = map(int,input().split())
ans = 0

for i in range(N):
  if i < A:
    ans += X
  else:
    ans += Y

print(ans)

1. 問題文の把握

題意は簡潔です。全部でキャベツをN個買います。その時に必要な金額を求めます。
但し価格に注意が必要で、A個目までは1個X円、A+1個目からは1個Y円で買うことができます。 本問ではN,A,X,Yという4つの値が与えられるので、それぞれの数字が何を意味しているかを正しく把握する必要があります。

2. コードを考える

(0) 標準入力
4つの変数それぞれに標準入力で受け取ったデータを整数にし代入するので map(int,input().split())を使います。

(1) 準備
本問は金額の出力が求められています。そこで、N,A,X,Yとは異なる新たな変数を用意する必要が出てきます。 今回の解答例では変数ansを用意し、初期値として0を設定します。後は、この変数ansにキャベツの購入価格を加算していくだけになります。
(0)標準入力と合わせて、まずは次のコードを書いていきます。

N,A,X,Y = map(int,input().split())
ans = 0

これで下準備は終了です。

(2) 根幹
変数ansにN回だけ、価格を加算していくのでfor文を使います。さらに、A個目までか否かによって価格が異なるのでfor文の中にif文を書いていきます。
つまり、次のようなコードとなります。

N,A,X,Y = map(int,input().split())
ans = 0
#以下が新規追加分
for i in range(N):
  if i < A:
    ans += X
  else:
    ans += Y

ここでは、if文の条件式i < Aに注意が必要です。A個目まではX円買うことができても条件式の不等号に=は付きません。
入力例1をもとに考えてみます。Nが5、Aが3と与えられますので、5個のうちはじめの3個までがX(20)円で買うことができます。この時、for i in range(5):iには0から始まり1,2,3,4と代入されていきます。つまり、はじめの3個に対応するiは0,1,2となる訳です。 そこで、条件式ではiは3(A)未満(3より小さい)と書くことになります。対応関係を表として下に示します。

何個目? i 価格
1 0 X
2 1 X
3 2 X
4 3 Y
5 4 Y

(3) 出力
繰り返し処理が終わった後の変数ansの値が「キャベツを N 個買うために必要な金額」となりますので、print()を書いて完成になります!

N,A,X,Y = map(int,input().split())
ans = 0

for i in range(N):
  if i < A:
    ans += X
  else:
    ans += Y
#以下が新規追加分
print(ans)

3. まとめ

いかがでしたでしょうか?
競技プログラミングを始めたばかりの方にとっては、まず自分で変数を用意するということがポイントだったと思います。これは、慣れてくればスムーズにできるようになると思います。
また、for文の条件式における繰り返し変数iにも注意が必要でした。もやもやする、スッキリしない人は別の入力例や自分で設定した入力例の対応関係などを紙に書いて整理してみると良いと思います。
今回も最後までお読みいただきありがとうございました。

AtCoder Beginner Contest 209 B問題 Python解説

ABC209 B-Can you buy them all?

問題はこちら

Pythonでの解法】

まず解答例を下に示します。

N,X = map(int,input().split())
A = list(map(int,input().split()))

for i in range(N):
  if (i + 1) % 2 == 0:
    X -= A[i] - 1
  else:
    X -= A[i]

print("Yes" if X >= 0 else "No")

1. 問題文の把握

本問の内容は数学的考察なども不要で日常シーンのようなものなので、イメージや理解は容易く、即座にコードを考えるフェーズに進めるかと思います。

2. コードを考える

(0) 標準入力
NとXはこれまで通りの変数への代入になります。
一方、 A_{1}  A_{2} ...  A_{N}のようにAの数が定まっていない(与えられるNの値次第となる)場合にはA = list(map(int,input().split()))という書き方で対応します。これにより A_{1}  A_{2} ...  A_{N}を要素とするリストAが作られます。
両者を比べると次のようになります。

"""標準入力で受け取った文字をリストの要素としてから整数にし、
それらの要素をそれぞれの変数に代入している"""
N,X = map(int,input().split())
"""標準入力で受け取った文字をリストの要素としてから整数にし、
それらを要素とするリストを作成している"""
A = list(map(int,input().split()))

どちらも幾度となく使うことがあると思うので、データの与えられ方によって正しく使い分けられるように整理しておくことをおすすめします。

(1) 根幹
本問の出力は「N 個の商品を全て買うことができるか?」の判定によって異なって参ります。そこで、何を判断基準とするかを考えます。
今回の解答例では所持金(X)から商品の購入価格を順に引いていき、最終値が0以上かマイナスかで判断しています。(Xが0の時、手元にはお金は残っていないものの商品は全て買うことができているので"Yes"の出力になります)
そこで、問題文より偶数番目と奇数番目とで購入価格が異なることが分かるのでif文を用いて場合分けをしながら、Xから減算していくこととします。 それが次のコードです。

N,X = map(int,input().split())
A = list(map(int,input().split()))
#以下が新規追加分
for i in range(N):
  if (i + 1) % 2 == 0:
    X -= A[i] - 1
  else:
    X -= A[i]

for文を書く際、繰り返し変数iには0から順に代入されていくため、if文の条件式にはi + 1とする点に注意が必要です。 A_{i} iの範囲が 1 \le i \le Nと問題文に書いてあるためです。
for文を使うことで、リストAに格納されている商品それぞれの定価を取り出すことができます。取り出した後は、偶数番目なら定価から1を引いた額、奇数番目なら定価そのままを所持金から減算していきます。
for文による繰り返し処理が全て終わった後のXが最終的な所持金となります。

(2) 出力
所持金(X)の最終的な値が0以上なら"Yes"、マイナスなら"No"と出力するので、場合分けが必要となります。 そこで、解答例では209Aでも触れた三項演算子を用いていてprint文を書いています。

N,X = map(int,input().split())
A = list(map(int,input().split()))

for i in range(N):
  if (i + 1) % 2 == 0:
    X -= A[i] - 1
  else:
    X -= A[i]
#以下が新規追加分
print("Yes" if X >= 0 else "No")

これで解答例が完成しました!

3. まとめ

今回は初めてB問題を扱いました。文法としては、if文とfor文の組み合わせがメインとなっており、その他にリストの扱い方やそれに関連してfor文の繰り返し変数にも注意が必要なポイントがありました。
また、冒頭の標準入力は本問に限らず競技プログラミングにおいて必要不可欠な知識ですので、必要であればmap()split()list()について各自で詳しく調べてみるとより知識が身につくと思います。

AtCoder Beginner Contest 209 A問題 Python解説

ABC209 A-Counting

問題はこちら

Pythonでの解法】

まず解答例を下に示します。

A,B = map(int,input().split())
if A < B:
  print(B - A + 1)
else:
  print(0)

1. 問題文の把握

本問はとても簡潔な問題文になっております。A以上B以下の整数の個数を考えるだけです。

2. コードを考える

(0) 標準入力
半角スペースで区切られた二つの整数を変数AとBに代入します。この際、map()を使うことでintinput().split()を同時に使うことができます。

A,B = map(int,input().split())

(1) 根幹
入力例1で出力される3は4-2+1によって算出されることが分かると思います。4-2では「3」と「4」しか拾えません。本問はA以上とあるので、+1を行います。 入力例2を見てみても100-90+1=91となっており、式が成り立つことが確認できます。 すると、次のようなコードが考えられます。

A,B = map(int,input().split())
#以下が新規追加分
print(B - A + 1)

(2) 入力例3を考える
ところが入力例3を見てみると、該当する整数が一つも存在しないケースがあることに気付かされます。そうです。これまでに入力例はA<B となっていたのに対し、A>Bの場合は「A以上B以下の整数」というものが存在しません。また、AとBが等しい場合も該当する整数の個数は0 となります。 そこで、if文を使って場合分けを行います。

A,B = map(int,input().split())
#if文による場合分け
if A < B:
  print(B - A + 1)
else:
  print(0)

これで上述の解答例が完成しました!

(3) より短く書いてみる
(2)まででも良いのですが、別解として最初に示した解答例より短く書く例も下に示したいと思います。(余力のある方、興味のある方はお読み下さい)

A,B = map(int,input().split())
#if文を1行にした
print(B - A + 1 if A < B else 0)

print()の中に
if文の条件式がTrueの時の出力内容、if、条件式、else、条件式がFalseの時の出力内容の順に書くことで1行にまとめることができますのでご紹介しておきます。(三項演算子を用いた記述)
この2行(コメントを除いた2行)だけでもACとなりますので、試してみて下さい。
初めは書き方や順番に戸惑うかもしれませんが、慣れてくると簡潔に書けることに快感を覚えるようになると思います。詳細が気になる方は是非「Python 三項演算子」で調べてみて下さい!

3. まとめ

前回に引き続き今回も、思考の流れを噛み砕くイメージで段階的にコードを書いていくことを意識して解説してみましたが、いかがでしたでしょうか?整数という言葉さえ知っていれば、題意の把握は容易な問題ではなかったでしょうか。あとは、いかにコードに落とし込めるかが今回のポイントだったと思います。
それでは、また次回の記事もぜひご期待下さい。