問5 注文データから関連度の高い商品を選ぶ

基本情報​技術者試験 令和6年度 公開問題 科目B、全6問のうちの問5。

出典:令和6年度 基本情報技術者試験 公開問題 科目B 問5(表とプログラムは原本の画像を文字に書き起こし、字下げは 1 段を空白 2 つで表した。折り返した行は、原本どおり続きの位置にそろえた。関連度の分数の式は 1 行に書き直し、分数の横線を / で表した。Lxy、Mxy、Kx などの添字は並べて書いた。空欄は[ a ]~[ c ]で、解答群の表は 1 行の文に組み直した)

次のプログラム中の[ a ]~[ c ]に入れる正しい答えの組合せを,解答群の中から選べ。ここで,配列の要素番号は 1 から始まる。

一度の注文で購入された商品のリストを,注文ごとに記録した注文データがある。表に,注文データの例を示す。

表 注文データの例
注文番号購入された商品のリスト
1A, B, D
2A, D
3A
4A, B, E
5B
6C, E

注文データから,商品 x と商品 y とが同一の注文で購入されやすい傾向を示す関連度 Lxy を,次の式で計算する。

Lxy = (Mxy × 全注文数) / (Kx × Ky)

ここで,Mxy は商品 x と商品 y とが同一の注文で購入された注文数,Kx は商品 x が購入された注文数,Ky は商品 y が購入された注文数を表す。表の例では,MAB が 2,全注文数が 6,KA が 4,KB が 3 であるので,商品 A と商品 B の関連度 LAB は,(2 × 6) / (4 × 3) = 1.0 である。

手続 putRelatedItem は,大域変数 orders に格納された注文データを基に,引数で与えられた商品との関連度が最も大きい商品のうちの一つと,その関連度を出力する。プログラムでは,商品は文字列で表し,注文は購入された商品の配列,注文データは注文の配列で表している。注文データには 2 種類以上の商品が含まれるものとする。また,注文データにある商品以外の商品が,引数として与えられることはないものとする。

〔プログラム〕
// 注文データ(ここでは表の例を与えている)
大域: 文字列型配列の配列: orders ← {{"A", "B", "D"}, {"A", "D"}, {"A"},
{"A", "B", "E"}, {"B"}, {"C", "E"}}
 
○putRelatedItem(文字列型: item)
文字列型の配列: allItems ← ordersに含まれる文字列を
重複なく辞書順に格納した配列
// 表の例では {"A", "B", "C", "D", "E"}
 
文字列型の配列: otherItems ← allItemsの複製から値がitemである
要素を除いた配列
 
整数型: i, itemCount ← 0
整数型の配列: arrayK ← {otherItemsの要素数個の0}
整数型の配列: arrayM ← {otherItemsの要素数個の0}
実数型: valueL, maxL ← -∞
文字列型の配列: order
文字列型: relatedItem
 
for (orderにordersの要素を順に代入する)
if (orderのいずれかの要素の値がitemの値と等しい)
itemCountの値を1増やす
endif
for (iを1からotherItemsの要素数まで1ずつ増やす)
if (orderのいずれかの要素の値がotherItems[i]の値と等しい)
if (orderのいずれかの要素の値がitemの値と等しい)
[ a ]の値を1増やす
endif
[ b ]の値を1増やす
endif
endfor
endfor
for (iを1からotherItemsの要素数まで1ずつ増やす)
valueL ← (arrayM[i] × [ c ]) ÷ (itemCount × arrayK[i])
/* 実数として計算する */
if (valueLがmaxLより大きい)
maxL ← valueL
relatedItem ← otherItems[i]
endif
endfor
relatedItemの値とmaxLの値をこの順にコンマ区切りで出力する
  1. アa arrayK[i],b arrayM[i],c allItemsの要素数
  2. イa arrayK[i],b arrayM[i],c ordersの要素数
  3. ウa arrayK[i],b arrayM[i],c otherItemsの要素数
  4. エa arrayM[i],b arrayK[i],c allItemsの要素数
  5. オa arrayM[i],b arrayK[i],c ordersの要素数
  6. カa arrayM[i],b arrayK[i],c otherItemsの要素数
答えと解説を開く

正解はオです。

arrayK[i] は otherItems[i] が買われた注文数 (Ky)、arrayM[i] は item と otherItems[i] が同じ注文で買われた注文数 (Mxy) を数える配列です。注文 order に otherItems[i] があるとき、そこに item もあれば両方が同じ注文にあるので、a は arrayM[i] です。item の有無にかかわらず otherItems[i] は買われているので、b は arrayK[i] です。式の全注文数は注文の数で、注文データは注文の配列なので、c は ordersの要素数 です。item = "A" で追います。otherItems は {"B", "C", "D", "E"} です。注文 1 {A, B, D} で itemCount = 1、B と D の K と M が 1 になります。注文 2 {A, D} で itemCount = 2、D の K と M が 2 になります。注文 3 {A} で itemCount = 3 です。注文 4 {A, B, E} で itemCount = 4、B の K と M が 2、E の K と M が 1 になります。注文 5 {B} で B の K が 3 になります。注文 6 {C, E} で C の K が 1、E の K が 2 になります。最後は arrayK = {3, 1, 2, 2}、arrayM = {2, 0, 2, 1}、itemCount = 4 です。関連度は B が (2 × 6) ÷ (4 × 3) = 1.0、C が (0 × 6) ÷ (4 × 1) = 0、D が (2 × 6) ÷ (4 × 2) = 1.5、E が (1 × 6) ÷ (4 × 2) = 0.7⁠5 です。maxL は -∞ から B で 1.0、D で 1.5 に更新され、D,1.5 を出力します。正解はオです。

ほかの選択肢が違う理由

  • アa と b が逆です。arrayK[i] が item と同じ注文の数になり、arrayM[i] が otherItems[i] の注文数になります。さらに c の allItemsの要素数 は商品の種類の数 (例では 5) で、全注文数の 6 ではありません。
  • イc は合っていますが、a と b が逆です。例の B では arrayM[i] が 3、arrayK[i] が 2 になり、関連度が (3 × 6) ÷ (4 × 2) = 2.2⁠5 と式と違う値になります。
  • ウa と b が逆で、c の otherItemsの要素数 は item 以外の商品の種類の数 (例では 4) です。全注文数ではありません。
  • エa と b は合っていますが、c の allItemsの要素数 は商品の種類の数 (例では 5) です。B の関連度が (2 × 5) ÷ (4 × 3) で約 0.8⁠3 になり、1.0 になりません。
  • カa と b は合っていますが、c の otherItemsの要素数 は item 以外の商品の種類の数 (例では 4) です。全注文数の 6 ではありません。

仕組み

この関連度は、2 つの商品が一緒に買われる割合が、偶然そろう場合と比べて何倍かを表す値で、リフト値とも呼ばれます。1 より大きければ一緒に買われやすい組です。

数える配列が複数あるときは、それぞれ「何を数えているか」を式の記号 (ここでは Mxy と Ky) に結び付けてから、増やす条件を読みます。

この問に出る言葉