🔙
🔝

【paiza問題集 解説】
Bランクレベルアップメニュー

5以上の整数の合計

5以上の整数の合計

STEP: 1 インクリメント

インクリメント

    n = int(input())
    n += 1
    print(n)
    

    他言語では ++nn++ といった書き方ができますが、Python3ではこの書式は採用されていません。代わりに += (加算代入演算子) を使って 1 を足します。 『 += があるんだからわざわざ別に用意しなくてもいいじゃん?』ということらしいです。

STEP: 2 複数行の入力と出力

複数行の入力と出力

  • 例1

  • n = int(input())
    
    for _ in range(n):
        a = int(input())
        print(a)
    
  • 例2

  • n = int(input())
    
    for _ in range(n):
        a = input()
        print(a)
    

    例1は、問題文に『自然数』とありますので、数値に変換してから出力しています。

    例2は、入力から出力までの間に何も処理が無いので、入力時に文字列として受け取ってそのまま出力しています。

STEP: 3 配列(リスト)要素の合計

配列(リスト)要素の合計

  • 例1

  • a = [1, 3, 5, 6, 3, 2, 5, 23, 2]
    
    n = 0
    for i in a:
        n += i
    
    print(n)
    
  • 例2

  • a = [1, 3, 5, 6, 3, 2, 5, 23, 2]
    n = sum(a)
    print(n)
    

    このトレーニングが「STEP: 1 インクリメント」から始まっていますので、例1の書き方のほうが流れに沿っていますが、 sum() 関数を使うと簡単です。

STEP: 4 5以上か4以下か

5以上か4以下か

  • 例1

  • n = int(input())
    
    if n >= 5:
        print('high')
    else:
        print('low')
    
  • 例2

  • n = int(input())
    print('high' if n >= 5 else 'low')
    

    問題文が『整数nが与えられるので、nが5以上なら"high"、そうでないなら"low"と出力してください。』なので、「4 以下の時」の条件式を用意する必要はありません。「そうでないなら」なので else で書きます。

STEP: 5 配列(リスト)データの足し合わせ

配列(リスト)データの足し合わせ

  • 例1

  • a = [4, 0, 5, -1, 3, 10, 6, -8]
    
    n = 0
    for i in a:
        if i >= 5:
            n += i
    
    print(n)
    
  • 例2

  • a = [4, 0, 5, -1, 3, 10, 6, -8]
    n = sum(i for i in a if i >= 5)
    print(n)
    
  • 例3

  • a = [4, 0, 5, -1, 3, 10, 6, -8]
    
    b = []
    for i in a:
        if i >= 5:
            b.append(i)
            
    print(sum(b))
    

    2つ前の問題「配列(リスト)要素の合計」と同じような考え方です。

    例3は、新しく作ったリストに 5 以上の数を集めてから最後に sum() 関数で合計しています。例2を分解したような形です。

FINAL問題 5以上の整数の合計

5以上の整数の合計

  • 例1

  • n = int(input())
    
    m = 0
    for _ in range(n):
        a = int(input())
        if a >= 5:
            m += a
    
    print(m)
    
  • 例2

  • n = int(input())
    a = [int(input()) for _ in range(n)]
    result = sum(i for i in a if i >= 5)
    print(result)
    
  • 例3

  • n = int(input())
    m = sum(a for _ in range(n) if (a:=int(input())) >= 5)
    print(m)
    

    例3は無理矢理感が強いので、初期化時以外では使わないほうがよさそうです。

足すか掛けるか

足すか掛けるか

STEP: 2 文字列の出力

文字列の出力

  • 例1

  • n = int(input())
    
    for _ in range(n):
        a = input()
        print(a)
    
  • 例2

  • n = int(input())
    a = [input() for _ in range(n)]
    print(*a, sep='\n')
    

    時と場合によってどちらも使います。まずは例1の書き方ができれば問題ありません。

STEP: 3 文字列の分割

文字列の分割

  • 例1

  • s = input().split()
    print(s[0])
    print(s[1])
    
  • 例2

  • s = input().split()
    
    for s_i in s:
        print(s_i)
    
  • 例3

  • s = input()
    
    for s_i in s.split():
        print(s_i)
    
  • 例4

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

    .split() メソッドの使い方が理解できていれば悩むことは無いはずです。

    .split() メソッドの使い方は「文字列の操作を使いこなす機能一覧」をご覧ください。

STEP: 4 整数の足し算

整数の足し算

  • 例1

  • a, b = input().split()
    print(int(a) + int(b))
    
  • 例2

  • a, b = map(int, input().split())
    print(a + b)
    

    入力のしかたが問題なだけですね。

FINAL問題 足すか掛けるか

足すか掛けるか

  • 例1

  • n = int(input())
    
    result = 0
    for _ in range(n):
        a, b = map(int, input().split())
        if a == b:
            result += a * b
        else:
            result += a + b
    
    print(result)
    
  • 例2

  • n = int(input())
    
    result = sum(a * b if a == b else a + b
            for _ in range(n)
            for a, b in [map(int, input().split())]
        )
    
    print(result)
    

    無理して例2の書き方を覚える必要はありませんが、内包表記に慣れたいなら解読してみてください。
    スキルチェックでも例2の書き方をすることはまずありません。

文字列を切り取る

文字列を切り取る

STEP: 1 文字列の分割

文字列の分割

  • 例1

  • s = input().split()
    print(s[0])
    print(s[1])
    
  • 例2

  • s = input().split()
    
    for s_i in s:
        print(s_i)
    
  • 例3

  • s = input()
    
    for s_i in s.split():
        print(s_i)
    
  • 例4

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

    1つ前の「足すか掛けるか」の「STEP: 3 文字列の分割」と全く同じ問題です。

STEP: 2 整数の足し算

整数の足し算

  • 例1

  • a, b = input().split()
    print(int(a) + int(b))
    
  • 例2

  • a, b = map(int, input().split())
    print(a + b)
    

    1つ前の「足すか掛けるか」の「STEP: 4 整数の足し算」と全く同じ問題です。

STEP: 3 文字列の長さ

文字列の長さ

    s = input()
    print(len(s))
    

    素直に len() 関数を使いましょう。

STEP: 5 あいだの整数

あいだの整数

    a, b = map(int, input().split())
    
    for i in range(a, b+1):
        print(i)
    

    b に +1 しなければならないことに注意してください。

FINAL問題 文字列を切り取る

文字列を切り取る

    a, b = map(int, input().split())
    s = input()
    
    print(s[a-1:b])
    

    Python3ではスライスを使って範囲を切り取ることができます。ab は「1文字目」から数えていますので、a から 1 を引く必要があります。b はそのままでOK。

指定範囲だけ大文字

指定範囲だけ大文字

STEP: 1 文字列の分割

STEP: 1 文字列の分割

  • 例1

  • s = input().split()
    print(s[0])
    print(s[1])
    
  • 例2

  • s = input().split()
    
    for s_i in s:
        print(s_i)
    
  • 例3

  • s = input()
    
    for s_i in s.split():
        print(s_i)
    
  • 例4

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

    2つ前の「足すか掛けるか」の「STEP: 3 文字列の分割」と全く同じ問題です。

STEP: 2 整数の足し算

整数の足し算

  • 例1

  • a, b = input().split()
    print(int(a) + int(b))
    
  • 例2

  • a, b = map(int, input().split())
    print(a + b)
    

    2つ前の「足すか掛けるか」の「STEP: 4 整数の足し算」と全く同じ問題です。

STEP: 3 文字列の長さ

文字列の長さ

    s = input()
    print(len(s))
    

    1つ前の「文字列を切り取る」の「STEP: 3 文字列の長さ」と全く同じ問題です。

STEP: 4 文字列の1文字目

文字列の1文字目

    s = input()
    print(s[0])
    

    1つ前の「文字列を切り取る」の「STEP: 4 文字列の1文字目」と全く同じ問題です。

STEP: 5 大文字にする

大文字にする

  • 例1

  • c = input()
    print(c.upper())
    
  • 例2

  • c = input()
    print(chr(ord(c) - 32))
    

    例1は.upper() メソッドを使った方法です。
    このメソッドについては こちら をご覧ください。

    例2は unicode の a(97) から A(65) を引くと 32 になります。小文字のアルファベットの文字コードから 32 を引くと対応した大文字が得られます。一度 ord() 関数で文字コードに変換してから 32 を引き、chr() 関数でまた文字に戻します。

STEP: 6 あいだの整数

あいだの整数

    a, b = map(int, input().split())
    
    for i in range(a, b+1):
        print(i)
    

    1つ前の「文字列を切り取る」の「STEP: 5 あいだの整数」と全く同じ問題です。

FINAL問題 指定範囲だけ大文字

指定範囲だけ大文字

  • 例1

  • a, b = map(int, input().split())
    s = input()
    
    s_sub = s[a-1:b]
    
    print(s.replace(s_sub, s_sub.upper()))
    
  • 例2

  • a, b = map(int, input().split())
    s = input()
    
    result = ''
    for i in range(len(s)):
        if a-1 <= i <= b-1:
            result += s[i].upper()
        else:
            result += s[i]
    
    print(result)
    
  • 例3

  • a, b = map(int, input().split())
    s = input()
    
    result = ''
    for i, c in enumerate(s, start=1):
        if a <= i <= b:
            result += c.upper()
        else:
            result += c
    
    print(result)
    

    例1は、指定範囲の部分文字列を取得し、大文字に置き換えたものを出力しています。
    .replaceメソッドの使い方は こちら をご覧ください。

    例2と例3は、文字列 s を先頭から一文字ずつチェックし、指定範囲内の文字は大文字に、それ以外はそのままの文字で文字列を作り直しています。内包表記で書けなくもないですが、例1が簡単なのでそこまですることはないでしょうけど、やってみたいと思ったならば内包表記で書いてみましょう!

文字の重複カウント

文字の重複カウント

STEP: 1 文字列の長さ

文字列の長さ

    s = input()
    print(len(s))
    

    2つ前の「文字列を切り取る」の「STEP: 3 文字列の長さ」と全く同じ問題です。

STEP: 2 文字列の1文字目

文字列の1文字目

    s = input()
    print(s[0])
    

    2つ前の「文字列を切り取る」の「STEP: 4 文字列の1文字目」と全く同じ問題です。

STEP: 3 配列(リスト)の要素の出力

配列(リスト)の要素の出力

  • 例1

  • prefectures = ["Nara", "Shiga", "Hokkaido", "Chiba"]
    
    for prefecture in prefectures:
        print(prefecture)
    
  • 例2

  • prefectures = ['Nara', 'Shiga', 'Hokkaido', 'Chiba']
    print(*prefectures, sep='\n')
    

    要素番号を使った出力方法もありますが、例1の書式が一般的です。

STEP: 4 1文字ずつ出力

1文字ずつ出力

  • 例1

  • s = input()
    
    for c in s:
        print(c)
    
  • 例2

  • s = input()
    print(*s, sep='\n')
    

    展開の * は文字列にも使えます。

FINAL問題 文字の重複カウント

文字の重複カウント

  • 例1

  • c = input()
    s = input()
    print(s.count(c))
    
  • 例2

  • c = input()
    s = input()
    
    cnt = 0
    for char in s:
        if char == c:
            cnt += 1
    
    print(cnt)
    

    .count() メソッドを使うと簡単です。

文字列の重複カウント

文字列の重複カウント

STEP: 1 文字列の長さ

文字列の長さ

    s = input()
    print(len(s))
    

    3つ前の「文字列を切り取る」の「STEP: 3 文字列の長さ」と全く同じ問題です。

STEP: 2 文字列の1文字目

文字列の1文字目

    s = input()
    print(s[0])
    

    入力例は異なっていますが、3つ前の「文字列を切り取る」の「STEP: 4 文字列の1文字目」と全く同じ問題です。

STEP: 3 1文字ずつ出力

1文字ずつ出力

  • 例1

  • s = input()
    
    for c in s:
        print(c)
    
  • 例2

  • s = input()
    print(*s, sep='\n')
    

    入力例は異なっていますが、1つ前の「文字の重複カウント」の「STEP: 4 1文字ずつ出力」と全く同じ問題です。

STEP: 4 文字列の1、2文字目

文字列の1、2文字目

    s = input()
    print(s[0], s[1])
    

    添字を使って抽出します。print() 関数内で、出力する値をカンマ , で区切ると、値と値の間が半角スペースで区切られて出力されます。

STEP: 5 文字列の n 文字目と n + 1 文字目

文字列の n 文字目と n + 1 文字目

  • 例1

  • n = int(input())
    s = input()
    
    if n < len(s):
        print(s[n-1], s[n])
    

    問題文の『n + 1 文字目がない場合は何も出力しないでください。』とは、n 文字目は出力するけど n + 1 文字目は出力しないという意味ではなく、本当に何も出力しないという意味のようです。

FINAL問題 文字列の重複カウント

文字列の重複カウント

    s = input()
    t = input()
    s_len = len(s)
    t_len = len(t)
    
    cnt = 0
    for i in range(t_len - s_len+1):
        if t[i : i + s_len] == s:
            cnt += 1
    
    print(cnt)
    

    入力例1を見ると、AAA には AA が2つあると認識されています。.count() メソッドは AAAAA を区別しますので使えません。仕方がないので王道の「先頭から順にスライドして調べていく」方法をとります。

    t の文字数から s の文字数を引いた範囲を調べます。スライスを使うと範囲外でもエラーにはなりませんが、無駄な処理を省くために s の文字数を引いています。

文字と整数の組のソート

文字と整数の組のソート

STEP: 1 インクリメント

インクリメント

    n = int(input())
    n += 1
    print(n)
    

    初めの「5以上の整数の合計」の「STEP: 1 インクリメント」と同じ問題です。

STEP: 2 数字のみの出力

数字のみの出力

  • 例1

  • n = int(input())
    
    for _ in range(n):
        s = input()
        print(s[2:])
    
  • 例2

  • n = int(input())
    
    for _ in range(n):
        _, d = input().split()
        print(d)
    
  • 例3

  • n = int(input())
    nums = [d for _ in range(n) for _, d in [input().split()]]
    print(*nums, sep='\n')
    

    例1は、数字の部分が必ず3文字目から始まっていますので、一行まるごと入力で取得し、3文字目以降をスライスを使って抽出しています。

    例2は、半角スペースを区切り文字として分割し、数字の部分のみを出力しています。

    例3は内包表記で書いたものです。後にリストとして活用する場合に有効な入力方法です。

STEP: 3 昇順ソート出力

昇順ソート出力

  • 例1

  • _ = input()
    a = list(map(int, input().split()))
    
    for i in sorted(a):
        print(i)
    
  • 例2

  • _ = input()
    a = list(map(int, input().split()))
    print(*sorted(a), sep='\n')
    
  • 例3

  • _ = input()
    a = list(map(int, input().split()))
    
    a.sort()
    
    print(*a, sep='\n')
    

    ソート関数やメソッドを使ったソート方法です。

  • 例4

  • _ = input()
    a = list(map(int, input().split()))
    
    while a:
        min_ = min(a)
        print(min_)
        a.remove(min_)
    
  • 例5

  • _ = input()
    a = list(map(int, input().split()))
    
    while a:
        print(a.pop(a.index(min(a))))
    

    ソート関数やアルゴリズムを使用しないでソートして画面出力する方法です。効率悪いし、リストが再利用できなくなるのでおすすめしません。😅

FINAL問題 文字と整数の組のソート

文字と整数の組のソート

  • 例1

  • n = int(input())
    a = [[s, int(d)] for _ in range(n) for s, d in [input().split()]]
    
    b = [lst[::-1] for lst in a]
    
    for _, c in sorted(b):
        print(c)
    
  • 例2

  • n = int(input())
    a = [[int(d), s] for _ in range(n) for s, d in [input().split()]]
    
    for _, c in sorted(a):
        print(c)
    
  • 例3

  • n = int(input())
    a = {int(d): s for _ in range(n) for s, d in [input().split()]}
    
    for _, c in sorted(a.items()):
        print(c)
    

    例1は、入力をそのままの順で取得し、各要素のリストを逆順にしてから昇順ソートしています。

    例2は、文字と数値を入力の時点で入れ替えています。

    例3は辞書を使いましたが、流れは例2のリストとほとんど変わりがありません。

文字と整数の組のソート2

文字と整数の組のソート2

STEP: 1 インクリメント

インクリメント

    n = int(input())
    n += 1
    print(n)
    

    初めの「5以上の整数の合計」の「STEP: 1 インクリメント」と同じ問題です。

STEP: 2 重複の判定

重複の判定

  • 例1

  • lst = ['HND', 'NRT', 'KIX', 'NGO', 'NGO']
    
    for s in lst:
        if lst.count(s) > 1:
            print('true')
            break
    else:
        print('false')
    
  • 例2

  • lst = ['HND', 'NRT', 'KIX', 'NGO', 'NGO']
    
    flg = False
    lst_len = len(lst)
    for i in range(lst_len-1):
        for j in range(i+1, lst_len):
            if lst[i] == lst[j]:
                print('true')
                flg = True
                break
        if flg:
            break
    else:
        print('false')
    
  • 例3

  • lst = ['HND', 'NRT', 'KIX', 'NGO', 'NGO']
    
    if len(set(lst)) != len(lst):
        print('true')
    else:
        print('false')
    

    Dランクレベルなら例1でじゅうぶんです。

STEP: 3 配列(リスト)の重複カウント

配列(リスト)の重複カウント

  • 例1

  • lst = ["HND", "NRT", "KIX", "NGO", "NGO", "NGO", "NGO", "NGO"]
    
    num = 0
    lst_len = len(lst)
    for i in range(lst_len-1):
        cnt = 0
        for j in range(i, lst_len):
            if lst[i] == lst[j]:
                cnt += 1
    
        if num < cnt:
            num = cnt
    
        if lst_len - i == num:
            break
        
    print(num)
    
  • 例2

  • lst = ["HND", "NRT", "KIX", "NGO", "NGO", "NGO", "NGO", "NGO"]
    
    for word in lst:
        cnt = lst.count(word)
        if cnt > 1:
            print(cnt)
            break
    
  • 例3

  • lst = ["HND", "NRT", "KIX", "NGO", "NGO", "NGO", "NGO", "NGO"]
    words = set(lst)
    
    for word in words:
        cnt = lst.count(word)
        if cnt > 1:
            print(cnt)
            break
    
  • 例4

  • from collections import Counter
    
    lst = ["HND", "NRT", "KIX", "NGO", "NGO", "NGO", "NGO", "NGO"]
    dic = Counter(lst)
    print(max(dic.values()))
    

    問題が微妙にわかりづらいですが、重複している要素を見つけてその要素数を出力してくださいということのようです。

    例1は、前問の「STEP: 2 重複の判定」の応用です。

    例2は、重複する文字列が1種類しかないので、カウントが1以外(1より大きい)の数を出力します。

    例3は、リストをセットにして重複する要素を削除してからそれぞれの要素の出現数をカウントしています。

    例4は、各ワードの出現数を辞書にしてから各出現数の最大値を出力しています。

STEP: 4 配列のソート

配列のソート

    a = [1, 3, 5, 6, 3, 2, 5, 23, 2]
    print(*sorted(a), sep='\n')
    

    1つ前の「文字と整数の組のソート」の「STEP: 3 昇順ソート出力」と同じような問題ですので、そちらを参考にしてください。こちらは入力が与えられていないので自分で準備します。

STEP: 5 数字のみの出力

数字のみの出力

  • 例1

  • n = int(input())
    
    for _ in range(n):
        s = input()
        print(s[2:])
    
  • 例2

  • n = int(input())
    
    for _ in range(n):
        _, d = input().split()
        print(d)
    
  • 例3

  • n = int(input())
    D = [d for _ in range(n) for _, d in [input().split()]]
    print(*D, sep='\n')
    

    1つ前の「文字と整数の組のソート」の「STEP: 2 数字のみの出力」と同じ問題です。

STEP: 6 昇順ソート出力

昇順ソート出力

  • 例1

  • _ = input()
    a = list(map(int, input().split()))
    
    for i in sorted(a):
        print(i)
    
  • 例2

  • _ = input()
    a = list(map(int, input().split()))
    print(*sorted(a), sep='\n')
    
  • 例3

  • _ = input()
    a = list(map(int, input().split()))
    
    a.sort()
    
    print(*a, sep='\n')
    

    1つ前の「文字と整数の組のソート」の「STEP: 3 昇順ソート出力」と同じ問題です。

FINAL問題 文字と整数の組のソート2

文字と整数の組のソート2

  • 例1

  • n = int(input())
    
    dic = {}
    for _ in range(n):
        s, d = input().split()
        if s in dic:
            dic[s] += int(d)
        else:
            dic[s] = int(d)
    
    dic_swaped = {v: k for k, v in dic.items()}
    dic_sorted = sorted(dic_swaped.items(), reverse=True)
    
    for num, c in dic_sorted:
        print(c, num)
    
  • 例2

  • n = int(input())
    
    dic = {}
    for _ in range(n):
        s, d = input().split()
        dic[s] = dic.get(s, 0) + int(d)
    
    dic_swaped = {v: k for k, v in dic.items()}
    dic_sorted = sorted(dic_swaped.items(), reverse=True)
    
    for num, c in dic_sorted:
        print(c, num)
    
  • 例3

  • n = int(input())
    
    dic = {}
    for _ in range(n):
        s, d = input().split()
        dic[s] = dic.get(s, 0) + int(d)
    
    for c, num in sorted(dic.items(), key=lambda x:-x[1]):
        print(c, num)
    

    辞書に値を集めるのと、辞書の値でソートするのが面倒くさいと感じているならば、例3の書き方を身につけると楽になります。ちょっと難しいけど。😓

アルファベット探し

アルファベット探し

STEP: 1 文字列の出力

文字列の出力

  • 例1

  • A = input()
    B = input()
    C = input()
    
    print(A)
    print(B)
    print(C)
    
  • 例2

  • lst = [input() for _ in range(3)]
    print(*lst, sep='\n')
    
  • 例3

  • lst = [input() for _ in range(3)]
    print('\n'.join(lst))
    

    いまさら例1で満足する方はいないと思いますが😅、例1をリストにして出力したものが例2と例3になります。

STEP: 2 アルファベットの範囲の文字の出力

アルファベットの範囲の文字の出力

    S = input()
    
    for c in range(ord(S[0]), ord(S[-1]) + 1):
        print(chr(c))
    

    ord() 関数は、文字を文字コード(unicode)に変換します。
    chr() 関数は、文字コードから相当する文字に変換します。

    前問の存在からして本来はリストを使って予めアルファベットを用意して組むことを想定していたのかもしれませんが、PCに予め備わっている文字コードをリストの代わりに利用すればプログラムがシンプルになります。

STEP: 3 アルファベットの順番

アルファベットの順番

  • 例1

  • S = input()
    
    if ord(S[0]) < ord(S[-1]):
        print('true')
    else:
        print('false')
    
  • 例2

  • S = input()
    
    if S[0] < S[-1]:
        print('true')
    else:
        print('false')
    
  • 例3

  • S = input()
    print('true' if S[0] < S[-1] else 'false')
    

    ord() 関数で文字コードに変換した数値を比較して判定しますが、例2の様に文字同士をそのまま比較することもできます。

    前問では range() 関数の引数を ord() 関数を使って文字コードに変換していましたが、 range() 関数の引数は整数しか扱えませんので、文字コードに変換する必要がありました。


    ついでに、

    'A' <= c <= 'E'

    という書き方ができることも一緒に覚えておきましょう。

FINAL問題 アルファベット探し

アルファベット探し

    X = input()
    Y = input()
    C = input()
    
    if X <= C <= Y:
        print('true')
    else:
        print('false')
    

    前問で紹介したアルファベットの範囲の判定を使えば簡単です。『X が Y よりもアルファベット順で後ろになる場合』else に該当します。

五目並べ

五目並べ

STEP: 1 文字列の出力

文字列の出力

  • 例1

  • s1 = input()
    s2 = input()
    s3 = input()
    s4 = input()
    s5 = input()
    
    print(s1)
    print(s2)
    print(s3)
    print(s4)
    print(s5)
    
  • 例2

  • s = [input() for _ in range(5)]
    
    for row in s:
        print(row)
    
  • 例3

  • s = [input() for _ in range(5)]
    print(*s, sep='\n')
    

    二次元マップは、リストを使うと扱いやすいです。

STEP: 2 五目並べ(1行)

五目並べ(1行)

    s = input()
    O = 'OOOOO'
    X = 'XXXXX'
    
    if s == O:
        print('O')
    elif s == X:
        print('X')
    else:
        print('D')
    

    変数 O, X の様に、予め勝ちのパターンを用意しておき、入力のものと比較をすると簡単です。


    余談ですが、問題に書かれている文字とキーボード入力した文字の文字コードが異なっていて、作ったプログラムはどこも間違っていないのになぜ0点になってしまうのだろうと頭を悩ませられることが稀にあったりします。(実際にありました)

    見た目で違いを見極めることは困難というかまず不可能なので、これを避けるためにも、与えられた文字や記号はコピペして使うことをオススメします。また、問題文から取るより、入力例や出力例から取ったほうが確実です。👍

STEP: 3 五目並べ(横)

五目並べ(横)

  • 例1

  • s = [input() for _ in range(5)]
    O = 'OOOOO'
    X = 'XXXXX'
    
    for row in s:
        if row == O:
            print('O')
            break
        if row == X:
            print('X')
            break
    else:
        print('D')
    
  • 例2

  • s = [input() for _ in range(5)]
    O = 'O'
    X = 'X'
    
    for row in s:
        if row == O * 5:
            print(O)
            break
        if row == X * 5:
            print(X)
            break
    else:
        print('D')
    
  • 例3

  • s = [input() for _ in range(5)]
    O = 'O'
    X = 'X'
    
    for i in range(5):
        tmp = ''
        for j in range(5):
            tmp += s[i][j]
    
        if tmp == O * 5:
            print(O)
            break
        if tmp == X * 5:
            print(X)
            break
    else:
        print('D')
    

    盤面が5行になりましたので、判定を5回繰り返します。

    例3は、この問題ではここまでする必要はありませんが、行の先頭から1文字ずつ新しい変数に集めてから比較をしています。この方法は次の問題から使用します。

STEP: 4 五目並べ(縦)

五目並べ(縦)

  • 例1

  • s = [input() for _ in range(5)]
    O = 'O'
    X = 'X'
    
    s_T = list(zip(*s))  # 転置
    
    for row in s_T:
        if row == O * 5:
            print(O)
            break
        if row == X * 5:
            print(X)
            break
    else:
        print('D')
    
  • 例2

  • s = [input() for _ in range(5)]
    O = 'O'
    X = 'X'
    
    for i in range(5):
        tmp = ''
        for j in range(5):
            tmp += s[j][i]  # ←ココ
    
        if tmp == O * 5:
            print(O)
            break
        if tmp == X * 5:
            print(X)
            break
    else:
        print('D')
    

    例1は縦と横を入れ替える転置をしてからチェックしています。縦一列だったのが横一列になれば、前問と同じ方法で判定できるようになります。
    転置については「2章 - 二次元リスト」の「転置有用!」をご覧ください。

    例2は、前問の解説の例3とほぼ同じプログラムになっています。ただ一箇所、8行目の横方向チェックの s[i][j]s[j][i] にすると縦方向を tmp に抽出していきます。

    これ以上は解説しません。二次元マップは頭の中でイメージすることが大切ですので、 print() 関数で画面に表示しながらプログラムをいじりまくって、どうするとどうなるのかを自身で確認してこの方法を身に付けてください。面倒くさがって想像力を養わないままスキルチェックのBランク問題へ進むと必ず後悔します。
    自信が無い方は 2章 - 二次元リスト を一読してみてください。

STEP: 5 五目並べ(斜め)

STEP: 5 五目並べ(斜め)

  • 例1

  • s = [input() for _ in range(5)]
    O = 'O'
    X = 'X'
    
    tmp1 = ''
    tmp2 = ''
    for i in range(5):
        tmp1 += s[i][i]
        tmp2 += s[4-i][i]
    
    if tmp1 == O * 5 or tmp2 == O * 5:
        print(O)
    elif tmp1 == X * 5 or tmp2 == X * 5:
        print(X)
    else:
        print('D')
    
  • 例2

  • n = 5
    s = [input() for _ in range(n)]
    O = 'O'
    X = 'X'
    
    tmp = ['', '']
    for i in range(n):
        tmp[0] += s[i][i]
        tmp[1] += s[n-1-i][i]
    
    if O * n in tmp:
        print(O)
    elif X * n in tmp:
        print(X)
    else:
        print('D')
    

    斜めは2つしかありません。なので両方いっぺんにチェックしていきます。座標の取り方にさえ注意すれば難しくないと思います。

  • 例3

  • n = 5
    s = [input() for _ in range(n)]
    
    flg1, flg2 = True, True
    target = s[n//2][n//2]  # 中心の文字を取得する
    
    for i in range(n):
        if flg1 and s[i][i] != target:
            flg1 = False
        if flg2 and s[n-1-i][i] != target:
            flg2 = False
    
        if target == '.' or flg1 == flg2 == False:
            print('D')
            break
    else:
        print(target)
    

    斜めの場合は、必ず中心を取らなければ勝ちはあり得ません。そこでまずは中心の文字を取得し、中心を取った文字で斜めが揃っているかをチェックします。1つでも違う文字に遭遇したら False にして、両方とも False になった時点で引き分け、どちらかが True のままなら最後に取得した中心の文字を勝ったほうとして出力します。

    中心の文字が . だったときの判定が 文の中に埋もれてわかりにくくなってしまっています。

  • 例4

  • s = ''.join(input() for _ in range(5))
    
    target = s[5**2//2]
    result = 'D'
    if target != '.' \
        and s[4 : 5**2-4 : 4] == target * 5 \
        or s[::6] == target * 5:
            result = target
    
    print(result)
    

    斜め取りを座標ではなく、スライスのステップを使って取得しています。何がどうなっているのかを print()文を使って変数の内容を確認しながら読み解いてみてください。

    「五目並べ」なので5×5マス固定となっていますので、N = 5 と定義して変数に置き換えてもみてください。

FINAL問題 五目並べ

五目並べ

  • 例1

  • N = 5
    s = [input() for _ in range(N)]              # 横 (初期盤面)
    s += [''.join(z) for z in zip(*s)]           # 縦 (転置)
    s += [''.join(s[i][i] for i in range(N))]    # 斜め 1 (\)
    s += [''.join(s[i][4-i] for i in range(N))]  # 斜め 2 (/)
    
    O = 'O'
    X = 'X'
    
    if O * N in s:
        print(O)
    elif X * N in s:
        print(X)
    else:
        print('D')
    
  • 例2

  • N = 5
    s = [list(input()) for _ in range(N)]     # 横 (初期盤面)
    s += [list(z) for z in zip(*s)]           # 縦 (転置)
    s += [list(s[i][i] for i in range(N))]    # 斜め 1 (\)
    s += [list(s[i][4-i] for i in range(N))]  # 斜め 2 (/)
    
    # 各列をセットにする。揃っているときのみリストに加わる
    # '.'が加わる場合もあるが、'O'と'X'が両方加わることはない
    win = [a.pop() for i in s if len(a:=set(i)) == 1]
    
    O = 'O'
    X = 'X'
    
    if O in win:
        print(O)
    elif X in win:
        print(X)
    else:
        print('D')
    
  • 例3

  • N = 5
    s = ''.join(input() for _ in range(N))
    result = 'D'
    targets = ('O', 'X')
    
    for target in targets:
        for i in range(N):
            if s[i * N : (i+1) * N] == target * N or \
                s[i :: N] == target * N:
                    result = target
                    break
    
        if s[N-1 : N**2 - (N-1) : N-1] == target * N or \
            s[::N+1] == target * N:
                result = target
                break
    
    print(result)
    

    一貫性の無いプログラム例になってしまいました。😅
    例3はスライスを使用した例です。わかりやすいとは言い難いのでおすすめまではしません。😓

    例1と例2は、1つのリストに全てのパターンを詰め込み、一回でチェックできるようにしたものです。例2は無理矢理感がありますが、列をセットにして重複を省くと、揃っているものは要素数が 1 となりますので、それのみをリストに加えます。揃っているものは 'O''X' のどちらか1つと、 '.....''.' となるパターンもあります。

    【パターン】
    ['O']
    ['X']
    ['.']
    []

    このリストに 'O''X' があればそれを勝者として画面に出力し、'.' またはリストが空のときは D を画面に出力します。

    他にもっとよい方法があるかもしれませんが、この中で選ぶならば例1がシンプルでわかりやすいのではないでしょうか?ツカレタノデコノヘンデ😓

占い

占い

STEP: 1 連想配列(辞書)を使う

連想配列(辞書)を使う

    users = {
        'Kyoko': 'B',
        'Rio': 'O',
        'Tsubame': 'AB',
        'KurodaSensei': 'A',
        'NekoSensei': 'A',
    }
    
    for name, blood_type in users.items():
        print(name, blood_type)
    

    辞書は「2章 辞書型」で学ぶことができます。

STEP: 2 ユーザーの血液型のデータ処理

ユーザーの血液型のデータ処理

    n = int(input())
    users = {k: v for _ in range(n) for k, v in [input().split()]}
    
    for user, blood_type in users.items():
        print(user, blood_type)
    

    手入力していたデータを標準入力から得るようにしたものです。

    この標準入力については「3章 標準入力」で入力の流れを確認することができます。

STEP: 3 1人の血液型

1人の血液型

  • 例1

  • s = input()
    n = int(input())
    users = {k: v for _ in range(n) for k, v in [input().split()]}
    
    print(s, users[s])
    
  • 例2

  • s = input()
    n = int(input())
    users = {k: v for _ in range(n) for k, v in [input().split()]}
    
    for name, blood_type in users.items():
        if name == s:
            print(name, blood_type)
            break
    

    期待する出力に、『A_i をキー、B_i を値として保存し、A_i と s が同じ場合、A_i と B_i を表示してください』とあります。

    『A_i と s が同じ場合』ということは、1つ1つ調べていって、入力の s と辞書のキーに一致するものがあった場合に、そのキーと値を出力するという書き方が求められているように思われますので、例2の書き方をするとよいでしょう。

STEP: 4 1つの血液型を占う

1つの血液型を占う

  • 例1

  • T = input()
    m = int(input())
    users = {k: v for _ in range(m) for k, v in [input().split()]}
    
    print(users[T])
    
  • 例2

  • T = input()
    m = int(input())
    users = {k: v for _ in range(m) for k, v in [input().split()]}
    
    for blood_type, name in users.items():
        if blood_type == T:
            print(name)
            break
    

    前問同様、『A_i と T が同じ場合、B_i を表示してください。』とありますので、例2の書き方をしますが、今回は対応するキーの値のみを出力するだけでよいので、例1の書き方のほうが効率的です。

STEP: 5 1人の占い結果

STEP: 5 1人の占い結果

  • 例1

  • U = input()
    n = int(input())
    users = {k: v for _ in range(n) for k, v in [input().split()]}
    m = int(input())
    results = {k: v for _ in range(m) for k, v in [input().split()]}
    
    print(results[users[U]])
    
  • 例2

  • U = input()
    n = int(input())
    users = {k: v for _ in range(n) for k, v in [input().split()]}
    m = int(input())
    results = {k: v for _ in range(m) for k, v in [input().split()]}
    
    for users_type, result in results.items():
        if users_type == users[U]:
            print(result)
    

    これまでの流れから考えると例2の書き方が求められているのかも知れませんが、問題文や期待する出力に特に条件が書かれていませんので、例1の書き方でも問題ないはずです。むしろ例1の書き方が望ましいです。

    問題文に『「血液型」として「星座」などのさまざまな文字列を利用できるようにすることで、他の占いにも対応する必要があることに注意してください。』とありますが、これは血液型限定とした場合は 文で「'A'のとき、'B'のとき、・・・」と条件文で判定することもできますが、これでは星座占いの「'shishiza'のとき、'yagiza'のとき、・・・」には対応できません。


    辞書は条件文のような使い方ができます。

    文の場合】

    if キーのとき:
      print()

    c = 'b'
    
    if c == 'a':
        print(0)
    elif if c == 'b':
        print(1)
    elif if c == 'c':
        print(2)
    
    1

    【辞書の場合】

    dic = {このキーが指定されたとき: このに化ける}
    print(dic[キー]) ← キーが持つに化ける

    c = 'b'
    dic = {'a': 0, 'b': 1, 'c': 2}
    print(dic[c])
    
    1

    辞書の場合はキーと値をいくらでも書き換えられるので、どのような条件や出力にも対応できますが、 文の場合はどうでしょうか?入力例1と入力例2のどちらにも対応できる 文が書けますか? の個数の変化に対応できますか?

    ただし、指定したキーが辞書に存在しなかったときはエラーになりますので注意してください。この場合は予め 文でこれから指定するキーが辞書に存在するかどうかを調べてから辞書にアクセスするようにします。

    辞書に指定したキーが存在する時

    dic = {'a': 0, 'b': 1, 'c': 2}
    c = 'b'
    if c in dic:
        print(dic[c])
    else:
        print('Key error.')
    
    1

    辞書に指定したキーが存在しない時

    dic = {'a': 0, 'b': 1, 'c': 2}
    c = 'z'
    if c in dic:
        print(dic[c])
    else:
        print('Key error.')
    
    Key error.

    辞書の便利さが理解できたところでも、なんでもかんでも辞書が使えるというわけでもなかったりします。これは実際になんでもかんでも無理やり辞書で書こうとして引っかかる体験をしてみてください。どうしても無理だったり、可読性が下がったりして他の方法のほうがよかったりすることもあることをぜひ肌で感じてみてください。😺

FINAL問題 占い

FINAL問題 占い

    n = int(input())
    users = {k: v for _ in range(n) for k, v in [input().split()]}
    m = int(input())
    results = {k: v for _ in range(m) for k, v in [input().split()]}
    
    for name in users.keys():
        print(name, results[users[name]])
    

    これまでのプログラム例の2つを併せた書き方です。「ユーザー → 血液型 → 占い結果」というように、ユーザーの名前1つから占い結果を導き出せるようになっています。

    といった感じです。おつかれさまでした。

    この「Bランクレベルアップメニュー」は、Cランクの卒業試験とBランクの入門問題が合わさったようなものでした。Bランクでは二次元リストの入力や操作が自在にできるようにならないと変なところで躓きます。また、辞書の入力やメソッドの使い方、難解なのがソートで、辞書のしくみが理解できていないと本当に訳がわからなくなります。ただでさえ複雑な問題の解き方を考えなければならないのに、関数やメソッドの使い方がよくわかっていないと幾重にも難しさが増していきます。

    こういったことを克服するためには、とにかく組んだプログラムをとことん改善していくことが大事です。100点を取ったからといってそこで終わってはもったいないです。Bランク問題は特に改造し甲斐があります。改造しやすいプログラムは良いプログラムです。改造しにくいプログラムは悪いプログラムです。また可能ならば他の人が書いたプログラムも読んで参考にしてみましょう。簡潔だけどわかりにくいものから、まわりくどいけどわかりやすいものまでいろいろ読んでみましょう。私も所詮独学シロウトなので主観的な書き方しかできませんが、良し悪しを含めて参考の1つとして使っちゃってください。