ITパスポートのプログラミング問題を解いてみよう(続き)

この記事からの続きです。読まれていない方は先に読まれることをオススメします。

令和4年度公開の問78に挑戦

問題文

関数checkDigitは,10進9桁の整数の各桁の数字が上位の桁から順に格納された整数型の配列originalDigitを引数として,次の手順で計算したチェックデジットを戻り値とする。プログラム中のaに入れる字句として,適切なものはどれか。ここで,配列の要素番号は1から始まる。

〔手順〕
(1)配列originalDigitの要素番号1~9の要素の値を合計する。
(2)合計した値が9より大きい場合は,合計した値を10進の整数で表現したときの各桁の数字を合計する。この操作を,合計した値が9以下になるまで繰り返す。
(3)(2)で得られた値をチェックデジットとする。

〔プログラム〕
○整数型:checkDigit(整数型の配列:originalDigit)
 整数型:i,J,k
 j ← 0
 for(iを1からoriginalDigitの要素数まで1ずつ増やす)
  j ← j+originalDigit[i]
 endfor
 while(jが9より大きい)
  k ← j÷10の商 /* 10進9桁の数の場合,jが2桁を超えることはない */
   空欄a 
 endwhile
 return j

ア j ← j-10×k
イ j ← k+(j-10×k)
ウ j ← k+(j-10)×k
エ j ← k+j

前置き

前回の解説でプログラムを眺めることに多少の耐性はついたでしょうか!?

問78はプログラムが長くて一見手強そうに見えますが、〔プログラム〕の中でやりたいことをすべて〔手順〕で説明してくれている、実は親切設計な問題です。「10進9桁」とか「配列を引数として」とか「チェックデジット」といった耳慣れない用語で混乱させようとしてきますが、落ち着いて問題文を読み下していきましょう。

イメージしやすいように、最初に実際の数字に置き換えて流れを見ていきましょう。10進9桁というのは物々しい言い方ですが、要するに私たちが日常的に使っている数字で9桁の数字を考えるだけです。適当に「567892345」とでもしておきましょう。チェックデジットの計算は、以下のように進みます。

手順(1):各桁の数字を足した合計を求める
 567892345 → 5+6+7+8+9+2+3+4+5=49
・手順(2):各桁を合計した数字が9より大きい場合、今度はその数字の各桁を足す。これを、足した値が9以下になるまで繰り返す
 4913
 134 (9以下になったので計算終了)
・手順(3):手順(2)で計算した数字をチェックデジットとして返す
 チェックデジット=4

なお、チェックデジットというのは、エラー(誤り)の検出や訂正に利用するために、元のデータに付加する数字のことです。身近なところでは、バーコードの読み取りエラーの検出や、ネットワーク通信での訂正符号として広く利用されています。チェックデジット自体もよく出題されるので、この機会に覚えておきましょう。

配列について

配列はプログラミング特有かもしれません。配列というのは、同じ名前で大量に量産できるデータの入れ物です。ただし、量産しただけだと区別がつかないので番号を振ります。プログラム中に「originalDigit[i]」という記述がありますが、この「[i]」の部分がまさにそれです。

1つ1つの入れ物自体は、変数と同じような役割です。言い換えると、変数をまとめて扱えるのが配列のうれしいポイントです。

配列originalDigitは「10進9桁の整数の各桁の数字が上位の桁から順に格納された整数型の配列」ということなので、10進9桁の「567892345」は次のような形で配列originalDigitに格納されています。

  • originalDigit[1]=5
  • originalDigit[2]=6
  • originalDigit[3]=7
  • originalDigit[4]=8
  • originalDigit[5]=9
  • originalDigit[6]=2
  • originalDigit[7]=3
  • originalDigit[8]=4
  • originalDigit[9]=5

解説

それではプログラムを見ていきましょう。

まず「j ← 0」で変数jに0を代入しています。なぜこんなことをするのかというと、この関数を使い回す場合に、前の計算の残骸が残っていたら計算が狂ってしまうからです(プログラムのバグでありがちなパターンです)。ここで確実に0にリセットしています。「変数を初期化する」という言い方もします。

続くfor~endfor文だけで、手順(1)が完了します。配列を使うと、このような形で引数をカウントアップすることで、配列の中身を順番に取り出して処理することができます。配列を使う場合の定番の形なので、これはぜひ慣れてください。

最後の「return j」が手順(3)っぽいですね。つまり、while~endwhile文の中で手順(2)を実現しているわけです。while文と手順(2)の内容に集中しましょう。

いま、手順(1)でoriginalDigitの各桁を合計した値が変数jに入っている状態です。「567892345」であればj=49ですね。while文の条件は「jが9より大きい」間は処理を繰り返すという意味です。いま、j=49なのでwhile文の処理を実行する必要があります。

※ちなみに、「111110000」のように最初からjが9以下となる場合はwhile文を実行しません。その数字がそのままチェックデジットとなります。

・while文の1巡目(j=49)
 k ← j÷10の商=4 
(jの10の桁の数字をkに代入しています)

・空欄aの選択肢ごとの計算(j=49,k=4
 ア j-10×k=9
 イ k+(j-10×k)=13
 ウ k+(j-10)×k=160
 エ k+j=53

while文の1巡目で計算しているのは、j=49のときの各桁の合計ですから、計算結果が「13」となるイが正解です。

この問題は「チェックデジット」で惑わしてきますが、実際にチェックデジットを求める必要はないので、この時点で解答終了です。

裏ワザ

慣れてくると、プログラム全体の流れがぼんやり読み取れるようになります。「この問題は手順(2)のことだけ考えればいいんだな」と判断できれば、適当なjの値を想定してさきほどの「while文の1巡目」の確認を行うだけです。例えばj=68と想定したなら「14」、j=25と想定したなら「7」になる選択肢が正解です。

※なお、ここで想定した数字がk=1となる場合、つまりj=10~19の数字を想定した場合は、選択肢イとウが同じ計算式「1+j-10」となるため、この裏ワザが使えません。ご指摘をいただきありがとうございます。

擬似言語に囚われることなかれ

プログラムやアルゴリズムの処理の書き方は、問題の作成者によっても千差万別です。そもそもが試験のための“擬似”言語ですから、そこにこだわる必要はありません。大事なのは、なにをやろうとしているかを読み取れることです。

ITパスポートのプログラミング問題は、習うより慣れろ! 考えるな感じろ!」の精神で、目を背けずに向き合ってみてください。きっと心強い得点源にできますよ!

\おすすめ/技術評論社ITパスポート本はこちら

苦手ジャンルなど、テーマ別に過去問を解きたい

ITパスポート試験によくでる問題集

新刊

試験形式で問題を一通り解きたい、数をこなしたい

ITパスポートパーフェクトラーニング過去問題集

よかったらシェアしてね!
  • URLをコピーしました!