🔙
🔝

【paiza問題集 解説】
文字列処理メニュー

文字列の出力

文字列の出力

    print('paiza')
    
文字列の受け取り

文字列の受け取り

    S = input()
    print(S)
    
i 文字目の出力

i 文字目の出力

    S = input()
    i = int(input())
    print(S[i-1])
    

    問題文に直接は書かれていませんが、i 文字目というのは 1 文字目から数えます。
    文字列の位置は 0 から始まりますので、i から 1 を引く必要があります。

文字列の条件判定

文字列の条件判定

  • 例1

  • S = input()
    if S == 'paiza':
        print('YES')
    else:
        print('NO')
    
  • 例2

  • S = input()
    print('YES' if S == 'paiza' else 'NO')
    

    YES と NO はどちらもすべて大文字ですので、そこだけ注意してください。

文字列の文字数

文字列の文字数

    S = input()
    print(len(S))
    

    文字数を数えるlen()関数を使います。
    全角半角関係無く一文字として数えられます。絵文字や記号も一文字として数えられます。

文字の検索

文字の検索

    S = input()
    c = int(input())
    print(S.find(c) + 1)
    

    引数に与えられた文字の位置を調べる.find()メソッドを使います。
    問題文には書かれていませんが、何文字目というのは一文字目から数えられます。文字列は 0 文字目から数えられるので、S.find(c) の結果に 1 を足す必要があります。
    この問題は.index()メソッドを使っても同様の結果が得られます。

文字列の連結

文字列の連結

  • 例1

  • N = int(input())
    s = ''
    for _ in range(N):
        S = input()
        s += S
    
    print(s)
    
  • 例2

  • N = int(input())
    s = [input() for _ in range(N)]
    print(''.join(s))
    

    例1が文字列のみの操作、例2はどちらかというとリストの操作と言えなくもないです。
    例1は予め空の文字列 s を作ってから、そこに入力した文字を追加していき、最後に s を画面に出力して完了です。
    例2はリストを文字列に変換する.join()メソッドを使って画面に出力しています。

    .join()は「2章 リストの操作を使いこなす機能一覧」で学習できます。

部分文字列

部分文字列

    S = input()
    i, j = map(int, input().split())
    print(S[i-1: j])
    

    スライスを使うと便利です。
    問題文に直接は書かれていませんが、i j 文字目というのは 1 文字目から数えます。文字列の位置は 0 から始まりますので、i から 1 を引く必要があります。j はそのままで大丈夫です。

    スライスは「2章 リスト型」で学習できます。

文字列の挿入

文字列の挿入

  • 例1

  • S = input()
    T = input()
    N = int(input())
    
    text = S[:N] + T + S[N:]
    print(text)
    
  • 例2

  • S = input()
    T = input()
    N = int(input())
    
    text = f"{S[:N]}{T}{S[N:]}"
    print(text)
    

    例1と例2のどちらもスライスを使って文字列 S を前半と後半に分割し、その間に挿入する文字列 T をはさみ込むと出力する文字列が完成します。

    例2の f"{S[:N]}{T}{S[N:]}"の書き方については、現在作成中ですので、もうしばらくお待ちください。🙏

文字列の書き換え

文字列の書き換え

  • 例1

  • S = input()
    i, c = [[int(i), c] for i, c in [input().split()]][0]
    
    text = S[:i-1] + c + S[i:]
    print(text)
    
  • 例2

  • S = input()
    i, c = [[int(i), c] for i, c in [input().split()]][0]
    
    text = f"{S[:i-1]}{c}{S[i:]}"
    print(text)
    
  • 例3

  • S = list(input())
    i, c = [[int(i), c] for i, c in [input().split()]][0]
    
    S[i-1] = c
    print(''.join(S))
    

    2行目の標準入力は「3章 標準入力」で学習できます。

    位置番号 0 1 2 3 4
    文字列 p a i z a
    スライス :0 1:

    i が 1 の時がわかりにくいのですが、[:i-1] は 1-1=0 で [0:0] となりますが、このスライスは 0 〜 -1 になって範囲としてはありえず無効になるので、結果、

    text = c + S[i:]
    

    と同等になります。c が位置番号 0 です。

    例3は S の入力をリストに変換して、要素番号 i-1 を直接書き換えています。これでも正解ですし、わかりやすくてよいのですが、この問題は文字列のスライスを使っての書き換えを求めているようですので、スライスでも書けるようになっておきましょう。

    スライスは「2章 リスト型」で学習できます。

文字列から数値への変換

文字列から数値への変換

    S = input()
    n = int(S) - 813
    print(n)
    

    今まで散々入力を整数に変換して受け取っておきながら今さらな問題ですが、せっかくなので入力を文字列で受け取った場合の書き方で書いてみました。
    と言っても数値に変換可能な文字列を整数に変換するint()関数を S に使うだけです。

数値から文字列への変換

数値から文字列への変換

    X = int(input())
    Y = int(input())
    N = int(input())
    
    s = str(X + Y)
    print(s[N-1])
    

    数値から文字列へ変換するstr()関数を使います。
    str()関数は、浮動小数(float) からも文字列に変換できます。

大文字から小文字への変換

大文字から小文字への変換

    S = input()
    print(S.lower())
    

    文字列全体を大文字から小文字に変換する時は.lower()メソッドを使います。

小文字から大文字への変換

小文字から大文字への変換

    S = input()
    print(S.upper())
    

    文字列全体を小文字から大文字に変換する時は.upper()メソッドを使います。

大文字小文字の反転

大文字小文字の反転

  • 例1

  • S = input()
    
    text = ''
    for s in S:
        if s.islower():
            text += s.upper()
        else:
            text += s.lower()
            
    print(text)
    
  • 例2

  • S = input()
    lst = [s.upper() if s.islower() else s.lower() for s in S]
    print(*lst, sep='')
    

    .islower()は、文字列が小文字かどうかを判定するメソッドです。小文字の時に True を返します。
    反対に、文字列が大文字かどうかを判定する.isupper()メソッドもあります。
    滅多に使うことは無いかもしれませんが、頭の片隅に残しておくといつか役に立つかもしれません。

文字列の検索

文字列の検索

    S = input()
    T = input()
    
    if T in S:
        print('YES')
    else:
        print('NO')
    

    「部分文字列」なんて難しい言葉が使われていますが、要は T の文字列が S の中に含まれているかどうかを判定するということです。
    in 〜 を使って調べましょう。

    in については「2章 文字列の操作を使いこなす機能一覧」で学習できます。

文字列の反転

文字列の反転

  • 例1

  • S = input()
    print(S[::-1])
    
  • 例2

  • S = input()
    print(''.join(reversed(S)))
    

    例1の様なスライスを使うと文字列が反転します。これはリストにも全く同じ書き方で使えますので便利です。

    例2はreversed()関数を使って文字列を反転させているのですが、そのままprint()で画面に出力すると次のようになります。

    S = input()
    print(reversed(S))
    
    <reversed object at 0x1456702a9130>

    それを.join()メソッドで文字列にして見える化しているのですが、面倒ですね。😓

    [::-1] という書き方は意味を知らない人にはわかりにくいかもしれませんが、市民権を得た書き方なので気後れせずにどんどん使って構わないと思います。

    [::-1]reversed()については「2章 見える化ちゃん 2期 - 見えない値の映し方」でそれなりに学習できます。

    もう1つ、リストを反転するメソッドがあるのですが、それは「リスト型データを使いこなす機能一覧」で学習できます。

回文判定

回文判定

  • 例1

  • S = input()
    if S == S[::-1]:
        print('YES')
    else:
        print('NO')
    
  • 例2

  • S = input()
    print('YES' if S == S[::-1] else 'NO')
    

    元の文字列と、反転した文字列が一致するかを評価にかけるだけです。

文字列の分割

文字列の分割

  • 例1

  • S = input()
    for s in S.split(','):
        print(s)
    
  • 例2

  • S = input().split(',')
    print(*S, sep='\n')
    

    注目すべきは.split()メソッドです。
    引数に与えた文字列を区切り文字として分割し、リストとなって返ります。

    .split()については「2章 文字列の操作を使いこなす機能一覧」で学習できます。

    例2のprint()の書き方については「2章 見える化ちゃん」で学習できます。

日時データの変換その1

日時データの変換その1

  • 例1

  • s1 = input().split('/')
    s2 = s1[3].split(':')
    print(*s1[:3], *s2, sep='\n')
    
  • 例2

  • import re
    S = input()
    re_matched = re.split('[/:]', S)
    print(*re_matched, sep='\n')
    

    残念ながら.split()メソッドの区切り文字は1つしか指定できません。1つだけなら何文字でも区切り文字に書けますが、今回の様に /: の2つを区切り文字にする方法はありません。

    仕方がないので先に / から分割し、次に : で分割して、print()で調整して出力します。(例1)

    例2は 正規表現 を使って書いたものです。文字列の操作を学んでいる段階ではまだ難しいものと思われますが、この方法を使うと区切り文字が複数使えて便利です。

    正規表現 は paiza問題集「テキストや文字列処理の習得 - 正規表現メニュー」で学習しながら解いていくことができます。気分転換が欲しくなった時にでも是非やってみてください!

日時データの変換その2

日時データの変換その2

  • 例1

  • s1, s2 = input().split()
    ymd = s1.split('/')
    hm = s2.split(':')
    print(*ymd, *hm, sep='\n')
    
  • 例2

  • import re
    S = input()
    re_matched = re.split('[/: ]', S)
    print(*re_matched, sep='\n')
    

    .split()の区切り文字は複数個指定できませんので、まず半角スペース ' ' (引数省略) で分割してから前半を / で、後半を : で分割したものを画面に出力します。

    例2は「日時データの変換その1」の例2の区切り文字に半角スペースを1つ追加しただけです。ラクチンです。

数値判定

数値判定

    S = input()
    if S.isdigit():
        print('YES')
    else:
        print('NO')
    

    ○○かどうかを判定する.is○○という形のメソッドがいくつか用意されています。
    【 Python 標準ライブラリ - 文字列メソッド 】
    難しい書き方をしているので読みにくいかもしれませんが、理解できる範囲で一読しておくと良いでしょう。

    S.isdigit() は、文字列全体が数字で構成されているかどうかを判定します。数字以外が入っている状態でstr()を使ったらエラーになってしまうので、その前にチェックしておくという時などに適しているメソッドです。

重複の削除

重複の削除

    S = input()
    
    result = ''
    for s in S:
        if s not in result:
            result += s
    
    print(result)
    

    重複なしの数字を result に作っていきます。result になかったら result に追加、あれば何もしないというのを文字列の先頭から全てを調べて、result を完成させていきます。

パスワード作成

パスワード作成

    N = int(input())
    Q = int(input())
    rules = [[int(n), c] for _ in range(Q) for n, c in [input().split()]]
    C = input()
    
    tmp = 0
    password = ''
    for n, c in rules:
        password += C*(n-1-tmp) + c
        tmp = n
    
    password += C*(N - tmp)
    print(password)
    

    n 文字目より前を C で埋め、N文字目に c を追加する流れです。そして最後に N 文字目まで C を埋めれば完了です。

    n = 2
    c = 'T'
    C = 'K' の場合

    真ん中辺りの C*(n-1-tmp) + c では、'K'*(2-1-0)'K'* 1 → 'K' を1つ、それから 'T' を password に追加します。(現在 password = 'KT') tmp には直前の n を記憶させています。これは「(現在の n) - (直前の n [tmp])」で埋めるべき C の個数を割り出す為です。
    最後までループを終えたら N 文字目まで C で埋める為、下の password += C*(N - tmp) で、'K'*(5 - 2)'K'* 3 → 'KKK' を password に追加します。(現在 password = 'KTKKK')
    これを画面に出力して完了です。

    リストを使うとめちゃくちゃ簡単です。

    N = int(input())
    Q = int(input())
    rules = [[int(n), c] for _ in range(Q) for n, c in [input().split()]]
    C = input()
    
    password = [C] * N 
    for n, c in rules:
        password[n-1] = c
    
    print(*password, sep='')
    

    初めに C で埋めたリストを作ってから、n-1 の箇所を c に書き換えるだけです。

表記の訂正

表記の訂正

    s = input()
    
    str_zero = '0'
    dot = '.'
    dot_count = s.count(dot)
    if s[0] == str_zero:        # 1番
        dot_idx = s.find(dot)
        num = int(s[:dot_idx])
        s = str(num) + s[dot_idx:]
    
    if dot_count >= 1:          # 2番
        s = s.rstrip(str_zero)
    
    if dot_count >= 2:          # 3番
        dot_idx = s.find(dot)
        s = s.replace(dot, '')
        s = s[:dot_idx] + dot + s[dot_idx:]
    
    print(s)
    

    急に複雑で面倒な問題が登場しましたので、落ち着いてやるべき処理をまとめてみます。

    1. 整数部分の頭の余分な 0 を除去する
    2. 小数部分の後ろの余分な 0 を除去する
    3. 小数点が複数ある場合、一番左の小数点以外を除去する

    まず1番からですが、これは簡単に整数部分だけ整数型にすると頭の 0 部分が消えますので、それを文字列型に戻します。浮動小数の場合は小数点以下すべてを整数部分に繋げます。
    小数点が無い場合(整数)は s[dot_idx:]s[-1:] と無効なスライスになり、'' に化けます。結果、エラー無く整数部分のみとなります。

    2番は浮動小数の場合、後ろの余分な 0 を消す為に.rstrip()メソッドを使います。

    .strip(引数) 引数に指定した文字を、文字列の先頭と末尾から複数取り除く
    .lstrip(引数) 引数に指定した文字を、文字列の先頭から複数取り除く
    .rstrip(引数) 引数に指定した文字を、文字列の末尾から複数取り除く

    ほとんど使った試しがないので当サイトの学習内容に載せていません。😅
    詳しく知りたい方はお手数ですが、他のサイトを探してそちらで学んでください。

    要するに.rstrip()メソッドを使って末尾の 0 を一気に取り除いています。

    3番は一番左の小数点の位置を dot_idx で憶えておき、.replace()メソッドを使って . を全て消してから、dot_idx の位置に小数点を付け直すことをしています。
    一度 dot_idx = s.find(dot) を実行しているのにもう一度ここで実行するのは、先頭の 0 が消された場合に小数点の位置がずれるからです。3番の処理を1番の処理より前に置くと、1番の dot_idx = S.find(dot) が不要になります。

    いろいろなやり方が出来ますので、余力がありましたら是非、他の方法でも書いてみてください。😺

数式の計算( 1 桁)

数式の計算( 1 桁)

  • 例1 (非推奨)

  • S = input()
    print(eval(S))
    
  • 例2

  • S = input()
    
    total = int(S[0])
    for i in range(1, len(S), 2):
        total += int(S[i:i+2])
    
    print(total)
    

    例1はチートを通り越してもはやチキンなやり方です。😅
    引数として与えられた数式になっている文字列を、eval()関数を使ってそのまま計算させています。
    ただeval()関数は面白い機能ではあるものの、セキュリティ的にかなり取り扱い注意な関数ですので、使用する場合はよく学び、よく理解した上で使用してください。何かあっても自己責任では済まされなくなる恐れも十分ありえますから。🙀

    例2は、但し書きをすべて考慮した上で簡単に書いたものです。
    まず先頭の数を、計算結果を出力する為の total として初期化し、以降は文で二文字ずつ整数化して total に足していく、という処理をしています。

数式の計算

数式の計算

    S = input()
    
    S_len = len(S)
    total = 0
    l, r = 0, 1
    while l < S_len:
        while r < S_len and S[r].isdigit():
            r += 1
            
        total += int(S[l:r])
        l = r
        r += 1
    
    print(total)
    

    ちょっとしたアルゴリズムを使って解いてみます。
    符号を含めた頭から数となる文字列を区切りながら足し算をしていきます。「数式の計算( 1 桁)」と同じ様に、マイナスの符号がある場合はマイナスの数を足す、つまり引き算をするということになります。

    S = 123+456+789 の時、

    位置番号 0 1 2 3 4 5 6 7 8 9 10
    l,r の現在地 l r
    S 1 2 3 + 4 5 6 + 7 8 9

    初めは上の表の様になっています。
    最初のループ while l < S_len: は、l が文字列の末尾の文字を越えたらループを終了するという意味です。

    次のループ while r < S_len and S[r].isdigit(): は、r の位置が

    • 文字数の範囲内 …… r < S_len
    • 数字           …… S[r].isdigit()
    の時には、r に 1 を足して次の文字を調べます。要するに、r符号を探しているわけです。

    位置番号 0 1 2 3 4 5 6 7 8 9 10
    l,r の現在地 l r
    S 1 2 3 + 4 5 6 + 7 8 9

    r の位置で符号が見つかった時、そのループを抜けて S[l:r] の範囲の文字列 '123' を数値 123 に変換し、total にその数を足します。total = 0 + (123)

    それから lr の位置に(l = r)、rr に 1 を足した位置に(r += 1)、再び初期化します。

    位置番号 0 1 2 3 4 5 6 7 8 9 10
    l,r の現在地 l r
    S 1 2 3 + 4 5 6 + 7 8 9

    これを繰り返していきます。

    位置番号 0 1 2 3 4 5 6 7 8 9 10
    l,r の現在地 l r
    S 1 2 3 + 4 5 6 + 7 8 9

    S[l:r] = '+456'
    total = 123 + (+456) = 579

    位置番号 0 1 2 3 4 5 6 7 8 9 10
    l,r の現在地 l r
    S 1 2 3 + 4 5 6 + 7 8 9

    位置番号 0 1 2 3 4 5 6 7 8 9 10 11
    l,r の現在地 l r
    S 1 2 3 + 4 5 6 + 7 8 9

    r は文字数を越えたので、ループを抜けます。(while r < S_len)
    S[l:r] = '+789'
    total = 579 + (+789) = 1368

    位置番号 0 1 2 3 4 5 6 7 8 9 10 11 12
    l,r の現在地 l r
    S 1 2 3 + 4 5 6 + 7 8 9

    l S_len = 11 未満ではなくなった(while l < S_len)ので、ここで1つめのループも抜け、total を画面に出力して完了となります。

    長い解説となってしまいましたが、どうでしょ?
    今後この方法は形を変えながら様々な場面で活躍します。理解するだけでなく、すばやくイメージして感覚として会得できると、今回のような問題に出くわした時に「あ、これはアレが使えそうだ」というひらめきが出来るようになります・・・きっと。😽
    l と r のように、見えない所でこれらがどう動いているか、その変動をイメージするのはまず理解してからでないと難しいのですが、こういうのに限らず、何度も頑張って書いているうちに、いつの間にか出来るようになっています。いつ、何で急にわかるようになったのかがわからないくらいに、いつの間にか出来るようになっています。

    上の例を見ながらで構いませんので、すべて手打ちしながら今どんなことをしている所を書いているのか考えながら何度も書いてみてください。

    この問題でももちろん、例のチキン行為が使えます。😸

巨大な数の足し算(繰り上がりなし)

巨大な数の足し算(繰り上がりなし)

  • 例1

  • S = input()
    T = input()
    print(int(S) + int(T))
    
  • 例2

  • S = input()
    T = input()
    
    total = ''
    for i in range(len(S)):
        total += str(int(S[i]) + int(T[i]))
    
    print(total)
    
  • 例3

  • S = input()
    T = input()
    
    total = ''
    for s, t in zip(S, T):
        total += str(int(s) + int(t))
    
    print(total)
    

    Python3 は整数の範囲に制限はありませんので、そのままint()で整数化して足し算をすれば解答が求められます。

    しかしここは「文字列処理メニュー」なので文字列を処理して解答を求めたいと思います。
    例2は ST 共に先頭から一文字ずつ足し算して total に格納していく流れだけで解答が得られます。条件にある |S| = |T| のとおり、必ず同じ文字数で与えられますので、同じ i を添字にできます。

    例3は STzip()関数を使って先頭から一文字ずつ1セットにして取り出しています。
    zip()関数は「2章 見える化ちゃん 2期」で簡単な使い方が学習できます。

巨大な数の足し算

巨大な数の足し算

    S = input()
    T = input()
    
    d = 0
    total = ''
    for i in range(len(S)-1, -1, -1):
        tmp = int(S[i]) + int(T[i]) + d
        d, m = divmod(tmp, 10)
        total = str(m) + total
    
    if d:
        total = str(d) + total
    
    print(total)
    

    筆算と同じ様に、末尾から計算していく方法です。
    今度は繰り上がりがあります。繰り上がった数の分を d とし、足し算の結果が例えば 15 の時には d = 1 になります。

    この繰り上がり計算を d, m = divmod(tmp, 10) の所で行なっています。

  • divmod() 関数



    (tmp // 10, tmp % 10)
    ||
    divmod(tmp, 10)

  • 足し算した結果を一時的に tmp に入れ、これをdivmod()にかけると以下のようになります。

    tmp = 15 の時

    d, m = divmod(tmp, 10)
    

    d, m = divmod(15, 10)
    

    (15 // 10, 15 % 10) 1 余り 5

    d, m = (1, 5)
    

    余りの m とそれまでの結果の total を繋ぎます。

    total = str(m) + total
    

    この処理を文字列の先頭まで繰り返します。

    最後に忘れてはならないのが、先頭の数同士で足し算した時の繰り上がり分です。ループが終了した時に繰り上がりがある、つまり d1 以上の時にはこれをさらに total の前に付けます。これで正しい解答が得られます。

    文以降は次の様にも書けます。

    print(str(d) + total if d else total)
    

    または

    print((str(d) if d else '') + total)
    

    または

    print(int(str(d) + total))
    

    以上、お好みのトッピングでお召し上がりください。🐈

巨大な数のかけ算

巨大な数のかけ算

    S = input()
    T = int(input())
    
    d = 0
    total = ''
    for i in range(len(S)-1, -1, -1):
        tmp = int(S[i]) * T + d
        d, m = divmod(tmp, 10)
        total = str(m) + total
    
    print(int(str(d) + total))
    

    1つ前の足し算がわかれば、こちらのほうが少し簡単です。😸
    T を入力時に整数型に変換しておきます。あとは掛け算すること以外はほとんど変わりません。

    次のように書くこともできます。

    S = input()
    T = int(input())
    
    d = 0
    total = ''
    for s in S[::-1]:
        tmp = int(s) * T + d
        d, m = divmod(tmp, 10)
        total += str(m)
    
    print(int(str(d) + total[::-1]))
    

    長らくお疲れ様でした。💤🛏