Python AtCoder入門 第7講 文字列処理

>100 Views

September 19, 26

スライド概要

シェア

またはPlayer版

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

ダウンロード

関連スライド

各ページのテキスト
1.

Python AtCoder入門 第7講 文字列処理 AtCoderの問題で扱うデータは、数値だけではありません。 文字列が主役になる問題も、A・B問題に数多く登場します。 1

2.

今回のテーマ この講で新しく覚えることは、あまり多くありません。 第5講の、 インデックス スライス 第6講の、 イミュータブル 内包表記 が、そのまま文字列にも通用します。 2

3.

この講のゴール 文字列ならではの道具を上乗せします。 インデックスとスライス 文字列のループ split / join replace / count ord / chr f-string 3

4.

コードファイル名の方針 この講でも、コード例ごとにファイル名を付けます。 string_basic.py count_char.py palindrome.py split_join.py shift_chars.py answer_7_1.py 4

5.

7-1 文字列の基本 文字列は、 1文字ずつが並んだもの として扱えます。 リストとほとんど同じ感覚です。 5

6.

インデックス S = "abcdef" print(S[0]) print(S[-1]) print(len(S)) 出力: a f 6 インデックスは0始まりです。 6

7.

スライス S = "abcdef" print(S[1:4]) print(S[:3]) print(S[3:]) print(S[::-1]) 出力: bcd abc def fedcba 7

8.

S[::-1] S[::-1] で文字列を逆順にできます。 回文判定などで非常によく使います。 第5講のリストのスライスと同じです。 8

9.

文字列は変更できない リストとは違い、文字列は中身を書き換えられません。 S = "abcdef" S[0] = "z" # TypeError 文字列は イミュータブル です。 9

10.

一部を書き換えたいとき いったんリストにして、書き換えて、文字列に戻します。 S = "abcdef" A = list(S) A[0] = "z" S = "".join(A) print(S) 出力: zbcdef 10

11.

文字列の連結 + で連結できます。 S = "abc" + "def" print(S) 出力: abcdef ただし、ループの中で += を繰り返すと遅くなることがあります。 11

12.

文字を溜めるならjoin parts = [] for c in S: parts.append(c) result = "".join(parts) 文字数が多いときは、 リストに溜めてから join するのが安全です。 12

13.

string_basic.py S = "competitive" # Index access print(S[0], S[-1], len(S)) # Slicing print(S[0:6]) print(S[6:]) # Reverse print(S[::-1]) # Convert to a list to modify A = list(S) A[0] = "C" print("".join(A)) 13

14.

string_basic.py の出力 c e 11 compet itive evititepmoc Competitive 文字列でも、インデックスとスライスが使えます。 14

15.

7-2 文字列のループと判定 文字列は for で回すと、1文字ずつ取り出せます。 S = "abc" for c in S: print(c) 出力: a b c 15

16.

enumerateも使える インデックスも必要なら、 enumerate が使えます。 for i, c in enumerate(S): print(i, c) リストと同じ感覚です。 16

17.

count_char.py # Read a string S = input() # Count the letter 'a' count = 0 for c in S: if c == "a": count += 1 print(count) 入力例: banana 出力例: 3 17

18.

カウントパターン 第4講のカウントパターンがそのまま使えます。 count = 0 for c in S: if 条件: count += 1 単純な数え上げなら S.count() も使えます。 18

19.

部分文字列の判定 文字列にも in が使えます。 S = "banana" print("a" in S) print("nan" in S) print("ban" in S) print("nnn" in S) 連続した部分文字列が含まれるかを調べます。 19

20.

in_string.py S = "banana" print("a" in S) print("nan" in S) print("ban" in S) print("nnn" in S) 出力: True True True False 20

21.

回文判定 前から読んでも後ろから読んでも同じ文字列を、 回文 と言います。 判定は簡単です。 if S == S[::-1]: print("Yes") else: print("No") 21

22.

palindrome.py # Read a string S = input() # A palindrome reads the same forwards and backwards if S == S[::-1]: print("Yes") else: print("No") 入力例: level 出力例: Yes 22

23.

7-3 文字列メソッド 文字列には便利なメソッドがあります。 まずは、よく使うものを押さえます。 split join replace count upper lower 23

24.

split split() は、文字列を区切ってリストにします。 S = "3 1 4" print(S.split()) S = "a,b,c" print(S.split(",")) 出力: ['3', '1', '4'] ['a', 'b', 'c'] 24

25.

join join() は、リストを1つの文字列にまとめます。 A = ["a", "b", "c"] print("".join(A)) print(" ".join(A)) print(",".join(A)) 出力: abc a b c a,b,c 25

26.

joinの書き方 "区切り文字".join(リスト) という形です。 「リストを連結する」ではなく、 区切り文字でリストをつなぐ と考えると覚えやすいです。 26

27.

joinに渡せるもの join に渡せるのは、文字列のリストだけです。 A = [1, 2, 3] print(" ".join(A)) print(" ".join(map(str, A))) # TypeError # 1 2 3 数値は str に変換します。 27

28.

split_join.py # Read a line and split it into words S = input() words = S.split() print(len(words)) # Join them back with a different separator print("-".join(words)) # Reverse the order of words print(" ".join(words[::-1])) 28

29.

split_join.py の実行例 入力例: apple banana cherry 出力例: 3 apple-banana-cherry cherry banana apple 3つ目は、単語の順序を逆にしています。 29

30.

replace と count S = "banana" print(S.replace("a", "o")) print(S.count("a")) print(S.count("na")) 出力: bonono 3 2 30

31.

replaceの注意 は、該当箇所をすべて置き換えます。 ただし、元の文字列は変わりません。 replace S = "banana" S.replace("a", "o") print(S) 出力: banana 31

32.

代入し直す 変更後の文字列を使いたいなら、代入し直します。 S = "banana" S = S.replace("a", "o") print(S) 出力: bonono 文字列はイミュータブルです。 32

33.

replace_count.py # Read a string S = input() # Count occurrences print(S.count("a")) # Replace all occurrences T = S.replace("a", "*") print(T) # The original string is unchanged print(S) 33

34.

replace_count.py の実行例 入力例: banana 出力例: 3 b*n*n* banana 34

35.

大文字小文字と判定 メソッド S.upper() S.lower() S.isdigit() S.isalpha() 意味 すべて大文字にする すべて小文字にする すべて数字かどうか すべて英字かどうか 35

36.

upper_lower.py S = "AtCoder" print(S.upper()) print(S.lower()) print("123".isdigit()) print("12a".isdigit()) 出力: ATCODER atcoder True False 36

37.

大文字小文字を揃える 大文字小文字を区別せずに比較したいときは、 両方を lower() に揃えます。 if S.lower() == T.lower(): print("Same") 37

38.

7-4 文字コードと文字の計算 文字には、それぞれ番号が割り当てられています。 ord() :文字から番号へ chr() :番号から文字へ 文字を計算で扱うときに使います。 38

39.

ord と chr print(ord("a")) print(ord("b")) print(ord("z")) print(chr(97)) print(chr(122)) 出力: 97 98 122 a z 39

40.

文字を0〜25に変換する a から z は連続した番号になっています。 c = "e" print(ord(c) - ord("a")) 出力: 4 a=0 , b=1 , ..., e=4 です。 40

41.

数字から文字に戻す 逆向きは、 chr(i + ord("a")) です。 print(chr(0 + ord("a"))) print(chr(25 + ord("a"))) 出力: a z 41

42.

ord_chr.py # Character to number for c in "abz": print(c, ord(c) - ord("a")) # Number to character for i in [0, 1, 25]: print(i, chr(i + ord("a"))) 42

43.

ord_chr.py の出力 a 0 b 1 z 25 0 a 1 b 25 z 43

44.

文字をずらす 各文字をアルファベット順に K 個ずらす処理です。 手順: 1. ord(c) - ord("a") で0〜25にする 2. K を足す 3. % 26 で折り返す 4. chr() で文字に戻す 44

45.

% 26 が重要 の次は a に戻る必要があります。 そこで、 z (番号 + K) % 26 とします。 第2講の「周期性を余りで扱う」の実例です。 45

46.

shift_chars.py # Read a lowercase string and the shift amount S = input() K = int(input()) # Shift each character, wrapping around with % 26 parts = [] for c in S: shifted = (ord(c) - ord("a") + K) % 26 parts.append(chr(shifted + ord("a"))) print("".join(parts)) 46

47.

shift_chars.py の実行例 入力例: xyz 3 出力例: abc x → a , y → b , z → c と折り返しています。 47

48.

内包表記でも書ける print("".join(chr((ord(c) - ord("a") + K) % 26 + ord("a")) for c in S)) 短くはなります。 ただし、読みやすいかどうかは別問題です。 読めなくなる手前で止めましょう。 48

49.

7-5 出力フォーマット 最後に、出力形式を整える方法を扱います。 AtCoderでは、答えが合っていても、 出力形式が違うとWA になります。 49

50.

f-string 文字列の中に変数の値を埋め込む書き方です。 name = "Sato" score = 80 print(f"{name} scored {score} points.") 出力: Sato scored 80 points. 50

51.

f-stringの基本 文字列の前に f を付けます。 埋め込みたい部分を { } で囲みます。 print(f"{name} scored {score} points.") str() に変換する必要がなく、読みやすいです。 51

52.

式も書ける { } の中には式も書けます。 score = 80 print(f"{score * 2}") 出力: 160 52

53.

ゼロ埋め h = 9 m = 5 print(f"{h:02d}:{m:02d}") 出力: 09:05 02d は、2桁になるまで0で埋める指定です。 53

54.

小数の桁数指定 x = 3.14159 print(f"{x:.2f}") print(f"{x:.4f}") 出力: 3.14 3.1416 指定した桁で四捨五入されて表示されます。 54

55.
[beta]
format_output.py
# Read hours and minutes
H, M = map(int, input().split())
# Zero-padded time format
print(f"{H:02d}:{M:02d}")
# Embed an expression
print(f"Total minutes: {H * 60 + M}")
# Decimal places
ratio = (H * 60 + M) / 1440
print(f"{ratio:.4f}")

55

56.

format_output.py の実行例 入力例: 9 5 出力例: 09:05 Total minutes: 545 0.3785 56

57.

章末まとめ 文字列は、リストと同じように使える部分があります。 インデックス スライス len for 逆順は、 S[::-1] です。 57

58.

章末まとめ:イミュータブル 文字列は変更できません。 一部を書き換えるなら、 A = list(S) A[i] = "x" S = "".join(A) のように、リストにしてから戻します。 58

59.

章末まとめ:メソッド split() で分割 "区切り".join(A) で連結 で置換 count() で数える upper() / lower() で大文字小文字を変える replace などは元の文字列を変えません。 replace() 59

60.

章末まとめ:文字の計算 ord(c) - ord("a") で a から数えた番号にできます。 chr(i + ord("a")) で番号から文字に戻せます。 文字をずらすときは % 26 で折り返します。 60

61.

章末まとめ:f-string 値を埋め込むなら、 f"{value}" ゼロ埋めは、 f"{h:02d}" 小数桁数は、 f"{x:.3f}" です。 61

62.

練習問題 7-1 母音の個数 英小文字からなる文字列 S が与えられます。 S に含まれる母音、 a i u e o の個数を出力してください。 62

63.

練習問題 7-1:入力と出力 入力: S 入力例: competitive 出力例: 5 63

64.

answer_7_1.py # Read a string S = input() # Count vowels count = 0 for c in S: if c in "aiueo": count += 1 print(count) c in "aiueo" で母音かどうかを判定しています。 64

65.

answer_7_1_generator.py # Read a string S = input() print(sum(1 for c in S if c in "aiueo")) 第6講のジェネレータ式を使うと、1行で数えられます。 65

66.

練習問題 7-2 逆順・大文字化 英小文字からなる文字列 S が与えられます。 S を逆順にし、さらにすべて大文字にした文字列を出力してください。 66

67.

練習問題 7-2:入力と出力 入力例: atcoder 出力例: REDOCTA スライスと upper() を使います。 67

68.

answer_7_2.py # Read a string S = input() # Reverse it and convert to uppercase print(S[::-1].upper()) S[::-1] の結果に対して、続けて .upper() を呼んでいます。 68

69.

練習問題 7-3 時刻の表示 0時0分からの経過時間が、分単位で N 分と与えられます。 そのときの時刻を、 HH:MM の形式で出力してください。 69

70.

練習問題 7-3:入力と出力 入力例: 545 出力例: 09:05 と M は2桁です。 1桁の場合は先頭を0で埋めます。 H 70

71.

answer_7_3.py # Read the elapsed minutes N = int(input()) # Split into hours and minutes H = N // 60 M = N % 60 # Zero-padded output print(f"{H:02d}:{M:02d}") 商が時、余りが分です。 71

72.

answer_7_3_divmod.py # Read the elapsed minutes N = int(input()) # divmod returns the quotient and the remainder at once H, M = divmod(N, 60) print(f"{H:02d}:{M:02d}") divmod() は商と余りをまとめて返します。 72

73.

第7講まとめ この講では、 文字列処理 を学びました。 リストで学んだインデックスやスライスは、文字列にもそのまま使えます。 73

74.

次回予告 次の第8講では、 2次元リストとグリッド問題 を扱います。 第6講で予告した [[0] * W] * H の罠を、実際に実験して確かめます。 74