Python AtCoder入門 第9講 関数と組み込み関数の活用

>100 Views

September 23, 26

スライド概要

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

Python AtCoder入門 第9講 関数と組み込み関数の活用 第2部の最後の講です。 ここまでで、リスト・タプル・文字列・グリッドと、データを扱う道具は一通り揃いました。 1

2.

今回のテーマ この講では、次の2つを学びます。 書いた処理に名前を付けて整理する方法 Pythonが最初から用意している便利な道具 つまり、 関数 と 組み込み関数 です。 2

3.

この講の目的 新しいことを解く力が一気に増える講ではありません。 しかし、 同じことをもっと楽に、間違えずに書けるようになる 講です。 コンテスト中の速度に効いてきます。 3

4.

コードファイル名の方針 この講でも、コード例ごとにファイル名を付けます。 function_basic.py is_prime.py divmod_abs.py any_all.py gcd_lcm.py main_template.py answer_9_1.py 4

5.

9-1 関数の定義 同じような処理を何度も書くのは面倒です。 さらに、同じ処理を何度も書くとミスの原因になります。 処理をひとまとめにして名前を付けたものが、 関数 です。 5

6.

defで処理に名前を付ける 関数は def で定義します。 def 関数名(引数): 処理 return 戻り値 関数の中身は、インデントで表します。 6

7.

double.py def double(x): return x * 2 print(double(5)) print(double(7)) 出力: 10 14 x が引数、 return が戻り値です。 7

8.

関数の用語 def double(x): return x * 2 :関数を定義する合図 x :引数 return :結果を返して関数を終える return に到達した時点で、関数は終わります。 def 8

9.

returnを書かない関数 を書かない関数も作れます。 その場合は、何も返しません。 正確には、 return None という「何もない」値が返ります。 9

10.

function_basic.py # Return the area of a rectangle def area(w, h): return w * h # Return the larger of two values def larger(a, b): if a > b: return a else: return b print(area(3, 4)) print(larger(10, 7)) 10

11.

function_basic.py の出力 12 10 引数は複数書けます。 if で分岐して、別々の値を返すこともできます。 11

12.

returnで関数は終わる def larger(a, b): if a > b: return a else: return b が実行されたら、その時点で関数は終わります。 第4講の break に少し似ています。 return a 12

13.

関数に切り出すメリット 関数にすると、次の利点があります。 1. 同じ処理を再利用できる 2. 本体が読みやすくなる 3. 単体で試せる 短いコードなら関数にしないこともありますが、複雑な処理では強力です。 13

14.

① 同じ処理を何度も使うとき たとえば、 素数かどうか 回文かどうか 条件を満たすかどうか を複数の場所で使うなら、関数にすると便利です。 14

15.

② 判定条件が複雑なとき 長い条件式を if に直接書くと、読みにくくなります。 関数にすると、 if is_prime(x): のように書けます。 名前が説明になります。 15

16.

③ 単体で試せる 関数にしておけば、 print(is_prime(7)) print(is_prime(9)) のように単独で動作確認できます。 バグの原因を切り分けやすくなります。 16

17.

is_prime.py # Return True if n is a prime number def is_prime(n): if n < 2: return False i = 2 while i * i <= n: if n % i == 0: return False i += 1 return True # Read N and the list of N integers N = int(input()) A = list(map(int, input().split())) # Count the primes count = 0 for x in A: if is_prime(x): count += 1 print(count) 17

18.

is_prime.py の実行例 入力例: 6 2 4 7 9 11 15 出力例: 3 素数は 2 , 7 , 11 の3つです。 18

19.

is_primeのポイント 本体側を見ると、 if is_prime(x): だけで意図が伝わります。 判定処理を直接書くより、読みやすくなります。 19

20.

i * i <= n 素数判定では、 while i * i <= n: と書いています。 平方根を計算せず、掛け算で比較しています。 float の誤差を避けられる安全な書き方です。 20

21.

9-2 よく使う組み込み関数 Pythonには、何も準備せずに使える関数がたくさんあります。 すでに使ってきたもの: len sum max min input print range map 21

22.

abs abs() は絶対値を返します。 print(abs(-5)) print(abs(5)) print(abs(-3.2)) 出力: 5 5 3.2 2つの値の差は、 abs(a - b) と書けます。 22

23.

divmod divmod() は、商と余りを同時に求めます。 q, r = divmod(17, 5) print(q, r) 出力: 3 2 タプルを返すので、アンパックで受け取ります。 23

24.

divmod_abs.py # Read two integers A, B = map(int, input().split()) # Absolute difference print(abs(A - B)) # Quotient and remainder at once q, r = divmod(A, B) print(q, r) 入力例: 17 5 出力例: 12 3 2 24

25.

roundは単純な四捨五入ではない は小数を丸める関数です。 しかし、単純な四捨五入ではありません。 round() print(round(0.5)) print(round(1.5)) print(round(2.5)) print(round(3.5)) 25

26.

round_half_even.py print(round(0.5)) print(round(1.5)) print(round(2.5)) print(round(3.5)) 出力: 0 2 2 4 ちょうど .5 のとき、近いほうの偶数に丸められます。 26

27.

roundの罠 AtCoderで、 小数第1位を四捨五入せよ と書かれているときに round() を使うと、WAになることがあります。 round(2.5) が 2 になるからです。 27

28.

整数で四捨五入する 整数 a を整数 b で割った結果を四捨五入したいなら、 answer = (2 * a + b) // (2 * b) と書けます。 / を使わないので、誤差がありません。 28

29.

sorted sorted(A) は、並べ替えた新しいリストを返します。 A = [3, 1, 4] print(sorted(A)) print(A) 出力: [1, 3, 4] [3, 1, 4] 元のリストは変わりません。 29

30.

reversed は逆順にたどるものを返します。 ただし、リストではありません。 reversed(A) A = [3, 1, 4] print(reversed(A)) print(list(reversed(A))) リストとして使うなら list() が必要です。 30

31.

reversed_list.py A = [3, 1, 4] print(list(reversed(A))) print(A[::-1]) 出力: [4, 1, 3] [4, 1, 3] 競技プログラミングでは A[::-1] のほうが手軽です。 31

32.

any と all 条件をまとめて判定する関数です。 any(...) :1つでも True があれば True all(...) :すべて True なら True 第6講のジェネレータ式と組み合わせると便利です。 32

33.

any_all_basic.py A = [3, 1, 4, 1, 5] print(any(x > 4 for x in A)) print(all(x > 0 for x in A)) print(all(x % 2 == 0 for x in A)) 出力: True True False 33

34.

フラグパターンを1行にする 第4講のフラグパターンは、 found = False for x in A: if 条件: found = True break でした。 これは any() で1行にできます。 34

35.

any_all.py # Read N and the list of N integers N = int(input()) A = list(map(int, input().split())) # Is there at least one even number? if any(x % 2 == 0 for x in A): print("Yes") else: print("No") # Are all the values distinct from 0? if all(x != 0 for x in A): print("Yes") else: print("No") 35

36.

any_all.py の実行例 入力例: 5 3 1 4 1 5 出力例: Yes Yes 偶数が1つあり、0は1つもありません。 36

37.

9-3 mathモジュールの頻出関数 は数学関連の関数を集めたモジュールです。 使うには先頭で読み込みます。 math import math 37

38.

最大公約数 gcd 最大公約数は math.gcd() で求めます。 import math print(math.gcd(12, 18)) 出力: 6 3つ以上でも渡せます。 38

39.

最小公倍数 lcm 最小公倍数は math.lcm() で求めます。 import math print(math.lcm(4, 6)) 出力: 12 39

40.

lcmの公式 最小公倍数は、次の式でも求められます。 answer = a * b // math.gcd(a, b) または、 answer = a // math.gcd(a, b) * b 先に割ると、途中の数が小さくなります。 40

41.

ceil と floor import math print(math.ceil(3.2)) print(math.floor(3.8)) 出力: 4 3 ただし、AtCoderでは使わないほうがよい場面があります。 41

42.

math.ceil(N / K) は避ける math.ceil(N / K) は / を使うため、 N が大きいと誤差でずれる可能性があります。 切り上げ割り算は、第2講の定石を使います。 (N + K - 1) // K 42

43.

sqrt import math print(math.sqrt(16)) 出力: 4.0 は float を返します。 整数として扱う問題では、誤差に注意が必要です。 math.sqrt() 43

44.

整数で平方根を扱う 平方数判定などでは、 math.isqrt() を使うか、 i * i <= n のように掛け算で比較するのが安全です。 整数で済むなら整数で処理します。 44

45.

gcd_lcm.py import math # Read two integers A, B = map(int, input().split()) # Greatest common divisor g = math.gcd(A, B) print(g) # Least common multiple print(A // g * B) 入力例: 12 18 出力例: 6 36 45

46.

9-4 main関数スタイル ここまでのコードは、ファイルの先頭から順に書いてきました。 それでも問題なく動きます。 ただし、次のように main 関数にまとめる書き方もあります。 46

47.

main関数テンプレート def main(): N = int(input()) print(N * 2) if __name__ == "__main__": main() main() の中に、問題を解く処理を書きます。 47

48.

決まり文句 if __name__ == "__main__": main() これは、 このファイルが直接実行されたときだけ main() を呼ぶ という意味の決まり文句です。 形として覚えれば十分です。 48

49.

main関数のメリット 主なメリットは3つです。 1. 変数の管理がしやすい 2. 実行が速くなることがある 3. 提出コードの形が毎回同じになる A・B問題で必須ではありません。 49

50.

変数の管理がしやすい 関数の中で作った変数は、その関数の中だけで有効です。 うっかり同じ変数名を使い回して壊す事故を減らせます。 50

51.

main_template.py def main(): # ========================================== # Write your code here # ========================================== N = int(input()) A = list(map(int, input().split())) print(sum(A), max(A)) if __name__ == "__main__": main() 51

52.

main_template.py の実行例 入力例: 5 3 1 4 1 5 出力例: 14 5 本書のコード例では、基本的には先頭から順に書くスタイルも使います。 52

53.

章末まとめ:関数 def 関数名(引数): 処理 return 戻り値 に到達したら関数は終わります。 関数に切り出すと、再利用でき、本体が読みやすくなります。 return 53

54.

章末まとめ:組み込み関数 :絶対値 divmod(a, b) :商と余り sorted(A) :並べ替えた新しいリスト reversed(A) :逆順にたどるもの any(...) :1つでもTrue all(...) :すべてTrue abs(a - b) 54

55.

章末まとめ:roundの注意 は単純な四捨五入ではありません。 round(2.5) は 2 です。 確実に四捨五入したいなら、整数だけで計算します。 round() (2 * a + b) // (2 * b) 55

56.

章末まとめ:math import math よく使うもの: math.gcd math.lcm math.ceil math.floor math.sqrt ただし、整数問題では float を混ぜないように注意します。 56

57.

章末まとめ:main関数 main 関数スタイルは、変数管理と速度に利点があります。 def main(): ... if __name__ == "__main__": main() 使うかどうかは自由です。 57

58.

練習問題 9-1 素数の個数 個の整数 A_1, A_2, ..., A_N が与えられます。 このうち素数であるものの個数を出力してください。 N 58

59.

練習問題 9-1:入力と出力 入力例: 7 2 4 7 9 11 15 1 出力例: 3 素数は 2 , 7 , 11 です。 1 は素数ではありません。 59

60.

answer_9_1.py # Return True if n is a prime number def is_prime(n): if n < 2: return False i = 2 while i * i <= n: if n % i == 0: return False i += 1 return True # Read N and the list of N integers N = int(input()) A = list(map(int, input().split())) # Count the primes print(sum(1 for x in A if is_prime(x))) 60

61.

answer_9_1.py のポイント を必ず入れます。 0 や 1 は素数ではありません。 割る数は、 if n < 2: i * i <= n の範囲までで十分です。 61

62.

練習問題 9-2 平均の四捨五入 個の整数が与えられます。 平均値を求め、 小数第1位を四捨五入した値 を出力してください。 ちょうど .5 の場合は、大きいほうに切り上げます。 N 62

63.

練習問題 9-2:入力と出力 入力例: 4 1 2 3 4 出力例: 3 平均は 2.5 なので、答えは 3 です。 63

64.

roundを使ってはいけない この問題で round() を使うと危険です。 round(2.5) は 2 になります。 問題文の「四捨五入」と違う結果になります。 64

65.

answer_9_2.py # Read N and the list of N integers N = int(input()) A = list(map(int, input().split())) # Round half up using integer arithmetic only S = sum(A) print((2 * S + N) // (2 * N)) float を使わず、整数だけで処理します。 65

66.

練習問題 9-3 最大公約数と最小公倍数 3つの整数 A , B , C が与えられます。 3つの最大公約数と最小公倍数を、この順に空白区切りで1行に出力してください。 66

67.

練習問題 9-3:入力と出力 入力例: 4 6 10 出力例: 2 60 最大公約数は 2 。 最小公倍数は 60 です。 67

68.

answer_9_3.py import math # Read three integers A, B, C = map(int, input().split()) # GCD and LCM of three values print(math.gcd(A, B, C), math.lcm(A, B, C)) math.gcd() と math.lcm() は3つ以上の値にも使えます。 68

69.

answer_9_3_lcm_func.py import math # Least common multiple of two values def lcm(a, b): return a // math.gcd(a, b) * b # Read three integers A, B, C = map(int, input().split()) print(math.gcd(A, B, C), lcm(lcm(A, B), C)) 関数定義と math.gcd() を組み合わせています。 69

70.

第9講まとめ これで第2部は完了です。 データを扱う道具は一通り揃いました。 この講では、 処理に名前を付ける方法 と 便利な組み込み関数 を学びました。 70

71.

次回予告 次の第10講からは第3部に入ります。 テーマは、 辞書と集合 です。 リストと二重ループでも書ける処理を、正しい道具で一瞬で書けるようにします。 71