基本情報ではじめる Python 最終回 試験問題レベルにチャレンジ


2022-01-17 更新

error

この記事は基本情報技術者試験の旧制度( 2022 年以前)の記事です。
この記事の題材となっている「午後問題」は現在の試験制度では出題されません。 ご注意くださいませ。

この連載では、プログラミングの入門者を対象として、基本情報技術者試験の出題範囲にテーマを絞って、 Python の言語構文とプログラムの読み方を説明します。

前回までで、試験の出題範囲をほぼ網羅して学習できました。最終回となる今回は、総仕上げとして、試験問題レベルの Python のプログラムにチャレンジしてみましょう。

report現時点で、 Python の過去問題は公開されていません。この記事に示した問題は、平成 29 年度 秋期 の C 言語の問題の一部を Python に置き換えたものです。

問題

 次の Python プログラムの説明及びプログラムを読んで、設問に答えよ。

〔問題〕

 文字列の中から、回文( palindrome )を探して表示する関数 find_palindrome である。回文とは、先頭から読んだ文字の並びと末尾から読んだ文字の並びが一致する文字の並びのことである。ただし、ここでは次の条件を満たすものとする。

  • 文字列は英字( A ~ Z、 a ~ z )、数字( 0 ~ 9 )、記号( !”#%&'()*+、-./:+<=>?[]^_{|} )及び空白文字から成る。
  • 文字の並びを読むとき、英字の大文字と小文字は区別しない。
  • 文字の並びを読むとき、記号及び空白文字は無視する。
  • 回文は英数字で始まり英数字で終わる。ただし、英数字 1 文字は回文ではない。

 本問のプログラムが表示する回文の例を表 1 に示す。 No.1 で示す文字列において、文字の並び bc0cb は回文である。 c0c も回文であるが、本問のプログラムでは、文字列の先頭に最も近い文字から始まるものを表示する。また、 No.2 で示す文字列において、英字の大文字と小文字は区別しないので、文字の並び Bc0Cb は回文である。さらに、 No.3 で示す文字列において、英字の大文字と小文字を区別せず、かつ、記号及び空白文字を無視するので、文字の並び B!c0Cb は回文である。 No.4 で示す文字列において、文字列の先頭に最も近い b を先頭文字とする文字の並び bc0cb と bc0cb1bc0cb は、いずれも回文である。しかし、本問のプログラムでは、先頭文字位置が同じ回文が複数あれば、長さが最も短いものを表示する。

表 1 本問のプログラムが表示する回文の例
No. 文字列 表示する回文
1 abc0cbe bc0cb
2 ABc0CbE Bc0Cb
3 AB!c0 CbE B!c0 Cb
4 abc0cb1bc0cbe bc0cb
  1. 関数 find_palindrome の仕様は、次のとおりである。ここで、引数の値に誤りはないものとする。
    機能
    文字列 text の中から、回文を探して表示する。文字列 text の中に複数の回文がある場合、先頭文字位置が文字列の先頭に最も近いものを表示する。さらに、先頭文字位置が同じ回文が複数あれば、長さが最も短いものを表示する。
    引数
    text 文字列

     関数 find_palindrome は、関数 is_palindrome 及び関数 find_char を使用する。

  2. 関数 is_palindrome の仕様は、次のとおりである。ここで、引数の値に誤りはないものとする。
    機能
    文字の並び chars の idx 以降が回文かどうかを判定する。
    引数
    chars 文字の並び
    idx チェックする先頭位置の添え字
    size チェックする文字数
    返却値
    回文の場合は 1
    回文でない場合は 0
  3. 関数find_charの仕様は、次のとおりである。ここで、引数の値に誤りはないものとする。
    機能
    文字列 st の idx 以降で、文字 ch が最初に現れる位置を求める。ただし、英字の大文字と小文字は区別しない。
    引数
    st 文字列
    idx チェックする先頭位置の添え字
    ch 文字
    返却値
    文字 ch が現れる場合は、それが最初に現れる位置の添え字
    文字 ch が現れない場合は、 -1
  4. プログラム中で使用している組み込み関数やメソッドの概要は、次のとおりである。
    s.isalnum()
    文字列sの内容がすべて英数字のとき、Trueを返し、それ以外のとき、Falseを返す。
    s.lower()
    文字列sの中にあるすべての英大文字を、英小文字に変換した文字列を返す。
    print(s, end = “”)
    文字列sを表示して、改行しない。

〔プログラム〕

info編集部注: スマートフォンでご覧の際は、プログラムは横スクロールすると全文をご覧になれます
def find_palindrome(text):
    for i in range(len(text)):
        if not text[i].isalnum():
            continue
        # ithは、文字列textの第i文字の添え字
        ith = i
        # hitは、第i文字と一致した文字の添え字
        hit = find_char(text, ith + 1, text[ith]) 
        while hit != -1:
            # psizeは、文字の並びの長さ
            psize = "[  a  ]"
            if is_palindrome(text, ith, psize):
                while ith < hit + 1:
                    print(text[ith], end = "")
                    ith += 1
                print()
                return
            hit = find_char(text, hit + 1, text[ith])

def is_palindrome(chars, idx, size):
    l = idx
    r = idx + size - 1
    while l < r:
        while not chars[l].isalnum():
            l += 1
        while not chars[r].isalnum():
            r -= 1
        if "[  b  ]":
            return 0
        l += 1
        r -= 1
    return 1

def find_char(st, idx, ch):
    for i in range(idx, len(st)):
        if "[  c  ]":
          return i
    return -1

設問

プログラム中の[     ]に入れる正しい答えを、解答群の中から選べ。

a に関する解答群

ア i			
イ ith			
ウ ith + 1
エ hit - ith		
オ hit - ith + 1

b に関する解答群

ア l == r
イ 1 != r
ウ chars[l] == chars[r]
エ chars[l] != chars[r]
オ chars[l].lower() == chars[r].lower()
カ chars[l].lower() != chars[r].lower()

c に関する解答群

ア ch == st[i]
イ ch != st[i]
ウ ch.lower() == st[i].lower()
エ ch.lower() != st[i].lower()
オ (ch == st[i].lower()) or (ch.lower() == st[i])
カ (ch == st[i].lower()) and (ch.lower() == st[i])

解答と解説

空欄 a の解説

表 1 に示された「 abc0cbe 」という文字列から「 bc0cb 」という回文が表示される例を想定して、関数 find_palindrome の処理の流れを追いかけてみましょう。

  1. 6 行目で、「 abc0cbe 」の先頭の「 a 」の添え字が変数 ith に格納されます。
  2. 8 行目で、「 abc0cbe 」の先頭から 1 つ先を起点とした「 bc0cbe 」という文字列から先頭の「 a 」と、同じ文字があるかどうかが関数 find_char で検索されます。
    この場合は、見つからないので、関数 find_char の戻り値は -1 になり、それ以降にある while 文の処理は行われず、次の文字の処理に進みます。
  3. 6 行目で、「 abc0cbe 」の 2 文字目の「 b 」の添え字が変数 ith に格納されます。
  4. 8 行目で、「 abc0cbe 」の 2 文字目から 1 つ先を起点とした「 c0cbe 」という文字列から 2 文字目の「 b 」と、同じ文字があるかどうかが関数 find_char で検索されます。
    この場合は、「 b 」が見つかり、関数 find_char の戻り値は見つかった「 b 」の位置の添え字になり、それ以降の while 文の処理に入ります。
  5. 11 行目で変数 psize に空欄 a の値を代入します。
  6. 12 行目で変数 psize を関数 is_palindrome の第 3 引数に指定しています。関数の仕様を見ると、第 3 引数は、チェックする文字数です。
    ここでは、「 abc0cbe 」の「 bc0cb 」という文字の並びが回文かどうかをチェックします。

この文字の並びの長さは、「 bc0cb 」の先頭の「 b 」を指す添え字 ith と、末尾の「 b 」を指す添え字 hit の差、プラス 1 で求められます。したがって、空欄 a は、hit - ith + 1(選択肢オ)です。

空欄 b の解説

関数 is_palindrome では、文字列 chars を左端からたどる l と右端からたどる r を 1 つずつ変化させる while 文で、文字列 chars が回文かどうかをチェックしています。

左端からたどった文字はchars[l]であり、右端からたどった文字はchars[r]です。

 

空欄 b には、関数 is_palindrome が戻り値として 0 を返す条件が入ります。関数 is_palindrome の仕様を見ると、戻り値として 0 を返すのは、文字列 chars が回文でない場合です。

大文字と小文字が違っても同じとみなすので、空欄 b の条件は、小文字に統一して等しくないことをチェックするchars[l].lower() != chars[r].lower()(選択肢カ)です。

空欄 c の解説

関数 find_char は、引数で指定された文字列 st から文字 ch を見つけて、最初に見つかった位置の添え字を返します。

空欄 c は、st[i]の添え字を返す処理の条件です。大文字と小文字が違っても同じとみなすので、ch.lower() == st[i].lower()(選択肢ウ)です。

 

解答

空欄 a ― オ
空欄 b ― カ
空欄 c ― ウ

いかがでしたか。 Python のプログラムを読み取って、問題を解けましたか?

もしも、プログラミングの学習を始めたばかりなら、スラスラできなくても当然です。同じ問題を、何度も繰り返し練習してください。時間はかかるかもしれませんが、必ずできるようになります。

この連載は、今回で最終回になります。これまで連載をお読みいただいた皆様に、この場をお借りして、厚く御礼申し上げます。

またどこかでお会いしましょう!

 

label 関連タグ
科目A試験は、
免除できます。
独習ゼミで科目A試験を1年間免除して、科目B試験だけに集中しましょう。
免除試験を受けた 74.9% の方が、
科目A免除資格を得ています。
科目A免除試験 最大 2 回の
受験チャンス !
info_outline
科目A免除試験 最大 2 回の
受験チャンス !
詳しく見てみるplay_circle_filled
label これまでの『基本情報ではじめるPython』の連載一覧 label 著者