始めに
競技プログラミングサイトAtCoder にて
AtCoder Beginner Contest (以下ABC) 最新回 (2019年2月11日現在) の
第117回から さかのぼって第1回まで、Aの問題を全て解いてみました。
とても楽しかったです。
Python3 は 覚えることは 少なく、実装量も 少ない ので
大変ラクなのですが、なんとなく組んでいるような気がしてました。
これまでに解いた問題を振り返り、
しっかり確認しておきたいと思い書きました。
予告無く、内容は削除、修正することがあります。
ご了承下さい。
ABC 117 A Entrance Examination
T, X = map(int, input().split())
print(T / X)
map(function, iterable, ...)
iterable の全ての要素に function 適用した結果を 「イテレータ」 として返す。
iterable は 複数指定 できる。
複数の iterable が与えた場合、その中の最短の iterable が尽きた時点で止まる。
l = map(int, input().split())
for i in l:
print(i)
入力
3 2 1
出力
3
2
1
input([prompt])
1行を読み込む、通常[prompt]無しで使う。
input() により得られる値は、「文字列」(str)。
「文字列」.split(sep=None, maxsplit=-1)
sep は区切り「文字列」。デフォルトは半角スペース。
maxsplit は分割する回数、デフォルトは無制限。
区切った「リスト」を返す。
末尾改行で出力。
toStringするとかは気にしなくてよい。
ABC 116 A Right Triangle
AB, BC, CA = map(int, input().split())
print((AB * BC) // 2)
// は 整数の割り算 (小数点以下を切り捨てる)。
/ は 浮動小数点数の割り算 (小数点以下を切り捨てない)。
ABC 115 A Christmas Eve Eve Eve
D = int(input())
s = "Christmas"
if (D <= 24):
s += " Eve"
if (D <= 23):
s += " Eve"
if (D <= 22):
s += " Eve"
print(s)
if、コロンとインデント
インデントが if ブロックの範囲を決める。
TypeError 比較
ここでは int( input() ) でなくてはならない、比較で TypeError になる。
繰り返しになるが、input() により得られる値は、「文字列」(str)。
「文字列」の結合は+でできる。
ABC 114 A 753
X = int(input())
if (X in [7, 5, 3]):
print("YES")
else:
print("NO")
「リスト」
[7, 5, 3] は「リスト」。
「リスト」は角括弧で囲む。
in 「リスト」
in で 「リスト」 に 値 があるかどうかをテストする。
in は 「リスト」 だけでなく 「辞書」 の Key や 「集合」に対しても使うことができる。
if、else、コロンとインデント
インデントが if ブロック、else ブロックの範囲を決める。
ABC 111 A AtCoder Beginner Contest 999
n = input()
for c in n:
if (c == '1'):
print('9', end='')
elif (c == '9'):
print('1', end='')
else:
print(c, end='')
print()
for ~ in 「文字列」:
「文字列」を1文字ずつイテレートする。
print(~, end='')
end= で改行に代わるものが指定できる。
end='' で改行無しの出力になる。
sep= で区切り指定、デフォルト半角スペース。
print(x, y, z, sep=',')で、x,y,zの出力になる。
if、elif、else、コロンとインデント
インデントが if ブロック、elif ブロック、else ブロックの範囲を決める。
else if が elif。
if、elifの条件は、丸括弧で囲わなくても良い。
ABC 110 A Maximize the Formula
A, B, C = sorted(map(int, input().split()), reverse=True)
print(10 * A + B + C)
降順ソート
sorted(map(int, input().split()), reverse=True) は 降順ソート。
論理値(bool)
論理値(bool) は True、False であって、 true、falseではない。
ABC 109 A ABC333
A, B = map(int, input().split())
print("Yes" if A % 2 != 0 and B % 2 != 0 else "No")
剰余
% は剰余 (割り算の余り) の演算子。
A % 2 != 0 は、A を 2 で割った余りが 0 でないという条件になる。
条件のANDは、小文字で「and」。
条件のORは、小文字で「or」。
三項演算子
C++ や Java の場合
条件 ? 真の場合 : 偽の場合
Python3の場合
真の場合 if 条件 else 偽の場合
となる。
ABC 108 A Pair
from collections import defaultdict
K = int(input())
d = defaultdict(lambda: 0)
for i in range(1, K + 1):
d[i % 2] += 1
print(d[0] * d[1])
「辞書」
「辞書」は、key : value の ペア を カンマで区切って並べ、波括弧で囲む。
連想配列。
d = {"one": 1, "two": 2, "three": 3}
defaultdict は 「辞書」の要素が無くてもデフォルトを0とする。
これでいきなりインクリメントが可能になる。
繰り返し処理 for ~ in range( [始まりの数値,] 最後の数値 [, 増加する量] ):
[始まりの数値,] と [, 増加する量] は省略できる。
[始まりの数値,] と [, 増加する量] 両方を省略することはできる。
[, 増加する量] だけ省略することはできるが、
[始まりの数値,] だけ省略することはできない。
[始まりの数値,] デフォルト 0。
[, 増加する量] デフォルト 1。
in range(1, K + 1) は [, 増加する量]を省略している。
最後の数値 と イコール になった時
for ブロック の処理を行わず、for ブロック の処理を抜けるので注意する。
C++ や Java の場合の
for (int i = 始まりの数値; i < 最後の数値; i += 増加する量)
と同じ。
TypeError 演算
ここでは input() は int( input() ) でなくてはならない。
演算、if の K + 1 で TypeError になる。
ABC 103 A Task Scheduling Problem
a = [int(i) for i in input().split()]
print(max(a) - min(a))
max と min
max、min を シーケンス の「リスト」で行う。
map(int, input().split())の場合、
「リスト」ではなく「イテレータ」の為、実行時エラーになる。
シーケンス は、「文字列」、「バイト列」、「タプル」、「リスト」、「range」 等。
ABC 098 A Add Sub Mul
A, B = map(int, input().split())
print(max(A + B, A - B, A * B))
2個以上の項目のmax
ABC 097 A Colorful Transceivers
a, b, c, d = map(int, input().split())
AB = abs(a - b)
BC = abs(b - c)
CA = abs(c - a)
print("Yes" if CA <= d else "Yes" if AB <= d and BC <= d else "No")
abs
abs で 絶対値 を得ることができる。
ABC 094 A Cats and Dogs
A, B, X = map(int, input().split())
print("YES" if A <= X <= A + B else "NO")
条件をまとめて書ける
A <= X <= A + B のように
A <= X and X <= A + B という 2つ の 条件 を まとめて書ける。
ABC 093 A abc of ABC
a = set(input())
print("Yes" if len(a) == 3 else "No")
「集合」
set は「文字列」から重複を取り除いて「集合」を作ることができる。
set("letters") を実行すると {'e', 't', 's', 'r', 'l'} になる。
並び順は保障されず、入力順でもアルファベット順でもない。
「集合」の要素数は len で得ることができる。
ABC 090 A Diagonal String
c1 = input()
c2 = input()
c3 = input()
print(c1[0] + c2[1] + c3[2])
「文字列」のインデックス
「文字列」のインデックスを指定すると該当する文字が得られる。
「文字列」c1 の 1文字目、「文字列」c2 の 2文字目、「文字列」c3 の 3文字目の
各文字を結合して「文字列」を出力する。
1文字目のインデックスはゼロ。
ABC 089 A Grouping 2
import math
N = int(input())
print(math.floor(N / 3))
floor
math のインポートが必要。
math.floor(x) で 引数以下 でもっとも 大きい 整数を返す。
引数以上 でもっとも 小さい 整数を返すのが ceil。
ABC 086 A Product
a, b = map(int, input().split())
print("Odd" if a * b % 2 else "Even")
ゼロの論理値(bool)
ゼロ(0, 0.0 など) は 論理値(bool) で False になる。
ゼロ(0, 0.0 など) 以外 は 論理値(bool) で True になる。
ABC 085 A Already 2018
S = input()
print(S.replace("2017/", "2018/", 1))
replace
「文字列」.replace で 「文字列」置換。
置換後の「文字列」 =
対象の「文字列」.replace( 置換される「文字列」, 置換する「文字列」 [, 置換回数] )
置換される「文字列」 全てを 置換する「文字列」 に置換して返す。
置換回数 が与えられている場合、先頭から 置換回数 個だけを置換する。
ABC 079 A Good Integer
N = list(input())
len = len(N)
num = 0
for i in range(0, len, 1):
cnt = 1
for j in range(i + 1, len, 1):
if (N[i] != N[j]):
break
else:
cnt += 1
num = max(num, cnt)
print("Yes" if 3 <= num else "No")
list( input() ) で「リスト」にする
この問題では数字の「文字列」が入力される。
例えば、12312 という「文字列」が与えられた時
「リスト」は ['1', '2', '3', '1', '2'] となる。
「集合」のように重複を取り除くことはありません。
もし [ input() ] ならば
もし list( input() ) を [ input() ] と書いたならば
意外にも「リスト」は ['12312'] となる。
「リスト」 の要素数
len で得ることができる。
len で以下の要素数を得ることができる。
シーケンス (「文字列」、「バイト列」、「タプル」、「リスト」、「range」 等) か
コレクション (「辞書」、「集合」、「凍結集合」等)
変数名 が Python3 の 組み込み関数名 と同じは良くない
len という変数名 が Python3 の 組み込み関数名「len」と同じになっている。
思いもよらない挙動をすることがあるので、「num」とか別の変数名を使う。
break文
continue文やbreak文は、for文やwhile文のブロック処理中に使用する。
continue文を使用すると、それ以降の処理を行わず、
for文やwhile文のブロックの先頭に戻り、次のレコードから処理を継続する。
break文を使用すると、現在処理しているfor文やwhile文の処理を終了し、
ブロックから抜ける。
ABC 075 A One out of Three
A = [int(i) for i in input().split()]
for i in range(0, len(A), 1):
if A.count(A[i]) == 1:
print(A[i])
「リスト」 でインデックス指定で参照
シーケンス の 「リスト」 でインデックス指定で参照する。
map(int, input().split())の場合、「リスト」ではなく「イテレータ」の為、
len(A)で実行時エラーになる。
「リスト」.count
「リスト」.count(検索値)で、検索値の出現回数を得ることができる。
ABC 074 A Bichrome Cells
N = int(input())
A = int(input())
print(N ** 2 - A)
指数
a ** b で a の b 乗。
a * b で通常の掛け算。
ABC 073 A September 9
N = int(input())
flg = False
while 0 < N:
if N % 10 == 9:
flg = True
N //= 10
print("Yes" if flg else "No")
繰り返し処理 while ~:
~の条件を満たす間、処理を継続する。
ABC 066 A ringring
a, b, c = sorted(map(int, input().split()))
print(a + b)
昇順ソート
sorted(map(int, input().split())) は 昇順ソート。
ABC 062 A Grouping
x, y = map(int, input().split())
a = {1, 3, 5, 7, 8, 10, 12}
b = {4, 6, 9, 11}
c = {2}
print("Yes" if x in a and y in a else "Yes" if x in b and y in b else "Yes" if x in c and y in c else "No")
in 「辞書」
波括弧は 「辞書」。
角括弧は 「リスト」。
ここでは in で key だけの「辞書」 に 値 があるかどうかをテストする。
「リスト」でもできる。
ABC 060 A Shiritori
A, B, C = [str(i) for i in input().split()]
print("YES" if A[-1] == B[0] and B[-1] == C[0] else "NO")
「文字列」の先頭と末尾
「文字列」のインデックスによる参照。
先頭は「0」、末尾は「-1」。
ABC 059 A Three-letter acronym
s1, s2, s3 = [str(i) for i in input().split()]
print(s1[0].upper() + s2[0].upper() + s3[0].upper())
大文字にする
upperで大文字にする。
ABC 050 A Addition and Subtraction Easy
A, op, B = map(str, input().split())
print(int(A) + int(B) if '+' == op else int(A) - int(B))
int、str混在の場合
ABC 048 A AtCoder *** Contest
s = [str(i) for i in input().split()]
print(s[0][0] + s[1][0] + s[2][0])
「文字列」の「リスト」、文字の結合、「文字列」の作成
「文字列」の「リスト」、各「文字列」の先頭文字を結合して、「文字列」を作成する。
map(str, input().split())の場合、「リスト」ではなく「イテレータ」の為、
インデックスによる参照は、実行時エラーになる。
ABC 046 A AtCoDeerくんとペンキ / AtCoDeer and Paint Cans
abc = set([int(i) for i in input().split()])
print(len(abc))
「リスト」から「集合」
set で 「リスト」 から重複を取り除いて「集合」を作る。
ABC 025 A 25個の文字列
S = str(input())
N = int(input())
l = []
for i in range(0, len(S), 1):
x = S[i]
for j in range(0, len(S), 1):
l.append(S[i] + S[j])
l = sorted(l)
print(l[N - 1])
「文字列」の各文字の2個の組合せ
input() は str( input() ) で無くてもでも大丈夫。
空の「リスト」を作成。
与えられた「文字列」の各文字の2個の組合せを「リスト」に格納。
sorted(「リスト」)で「リスト」の昇順ソート。
ここでは「文字列」が昇順である為、ソートは不要。
ABC 021 A 足し算
N = int(input())
l = []
c = 0
for i in range(0, N.bit_length(), 1):
if (N % 2 == 1):
c += 1
l.append(2 ** i)
N //= 2
print(len(l))
for i in range(0, len(l), 1):
print(l[i])
2進法と10進法
空の「リスト」を作成。
与えられた数字を2進法で表したときに、
その各桁の値を10進法で表して「リスト」に格納。
bit_length() は整数を2進法で表すために必要なビットの数を返す。
ABC 018 A 豆まき
class Mame:
def __init__(self, ABC, point, rank):
self.ABC = ABC
self.point = point
self.rank = rank
def __repr__(self, ABC, point, rank):
return repr((self.ABC, self.point, self.rank))
A = int(input())
B = int(input())
C = int(input())
l = []
l.append(Mame('A', A, 0))
l.append(Mame('B', B, 0))
l.append(Mame('C', C, 0))
l = sorted(l, key=lambda x: x.point, reverse=True)
for i in range(0, len(l), 1):
l[i].rank = i + 1
l = sorted(l, key=lambda x: x.ABC)
for i in range(0, len(l), 1):
print(l[i].rank)
「リスト」に格納されたクラスをソート
少しやり過ぎですが、ソート2回で。
Mameクラスを定義する。
Mameクラスは以下の項目をもつ。
ABC : 値は'A', 'B', 'C'
point : 豆まきの得点
rank : 順位
空の「リスト」を作成する。
Mameクラスのインスタンスを生成し、「リスト」に格納する。
豆まきの得点を降順ソート。
得られたソート済みの「リスト」に、最初から順に 1 から順序を振る。
ABC順に並べ替える。
順位を出力する。
ABC 017 A プロコン
import math
l = []
l.append([int(i) for i in input().split()])
l.append([int(i) for i in input().split()])
l.append([int(i) for i in input().split()])
ans = 0
for i in range(0, len(l), 1):
ans += l[i][0] * l[i][1] // 10
print(math.floor(ans))
「リスト」を「リスト」に格納
ABC 015 A 高橋くんの研修
A = input()
B = input()
print(A if len(B) < len(A) else B)
「文字列」の長さ
len で 「文字列」の長さを得ることができる。
ABC 013 A A
X = str(input())
print(ord(X[0]) - ord('A') + 1)
文字 を表す整数
input() は str( input() ) で無くてもでも大丈夫。
ord は 文字 を表す整数。
文字を表す整数 は Unicode コードポイント と呼ばれている。
ord('A') は 65、ord('B') は 66。
文字を表す整数 を 文字にするのが chr()。
ABC 012 A スワップ
A, B = map(int, input().split())
B, A = A, B
print(A, B)
スワップ
B, A = A, B で 値をスワップ (入れ替え)。
終わりに
「基本情報技術者試験」で、Pythonが採用されるようです。
競技プログラミングでは、3大人気言語 (C++、Python、Java) の一つです。
型がはっきりしないなど、今ひとつ抵抗があり、これまで触れてきませんでした。
ついこの間、初めて Python3 でプログラミングしてみると
楽しい、気持ちいい、コーデングが手っ取り早すぎる。
なぜ、これまで1度もやらなかったか不思議です。
プログラムがほとんどの時間をなんらかの計算に使っている (CPUバウンド) の場合
他のプログラミング言語で書かれたプログラムの方が高速に動作するそうです。
どこかで、スピードが理由で Python をあきらめないといけないところがあると思います。
できるところまでやってみようと思います。
ABC B問題 をすべて解き終わった時には、また別の記事で書きたいと思います。
※2019年2月28日
記事「AtCoder ABC B問題 を Python3 で解いてみた」を追加しました。
https://qiita.com/ShinjiSHIBATA/items/8dce42fb253b20f80d89