クソ診断紹介2「あなたに必要な3つのもの」

この記事は、クソ診断 Advent Calendar 2019 の9日目の記事です。

1. はじめに

診断作成の経緯

twitterのタイムラインで、格子上に並んだ文字の中から言葉を探す心理テストを時折見かけることがあります。見つけた言葉が表すものは、手に入れたいものであったり、人生で重要なものであったりとツイートにより異なるものの、「最初に見つけた3つの言葉」という条件はほぼ共通しているようです。
さて、本診断を作成したのは2019年の元日のことでした。日本人の運気に対する関心が特に高まるこの年末年始の時期、多数の占いや心理テストに関するツイートが投稿されました。「最初に見つけた3つの言葉」についてもいくつかの投稿があり、特に以下のツイートは多数のRTを集めました。

一方、作成に手間がかかるなどの理由からか、「最初に見つけた3つの言葉」についてはあまり多くのバリエーションが作成されていないように見えました。これを毎日遊べるコンテンツにする事が、診断作成の動機でした。

診断の概要

カタカナ80文字の中に、縦または横に3~4文字のキーワードが隠れています。
その中で最初に見つけた3つが、あなたに今必要なものを表しています。 shindanmaker.com

この診断の抽選の仕組みを図1に示します。どの位置に何文字の単語を入れるかを決めるパズルと、パズルに入れる文字を決めるキーワードの2種類のリストで構成されています。これらの抽選結果を組み合わせることで、診断結果が生成されます。

f:id:yryrrrrryryr:20191209040548p:plain:w400
図1 診断の抽選の仕組み

この記事では、パズルおよびキーワードの各リストの作成方法を示した後、実装方法について診断メーカーの制約条件を踏まえながら解説していきます。

2. リストの中身を作る

パズルを作成する

どの位置に何文字の単語を入れるか決定するアルゴリズムは、診断メーカーの機能だけで作成するには少々複雑です。
そのため、パズル部分は診断メーカー外であらかじめ候補を作成しておき、診断メーカーでは候補の中から抽選を行うような仕組みとしました。
パズルの作成方法を図2に示します。行数と列数が決められた格子を、ピースで隙間なく埋めていくことを考えます。

f:id:yryrrrrryryr:20191209051654p:plain:w400
図2 パズルの作成方法

なお、ピースはキーワードの文字数読む方向に応じて、以下の6種類があります。

  • 1文字
  • 横2文字
  • 横3文字
  • 横4文字
  • 縦3文字
  • 縦4文字

2文字以上のピース(5種類)からランダムに1種類を選択し、既存のピースと重ならないように配置する動作を、格子の80%以上が埋まるまで繰り返します。最後に残った格子には、1文字のピースを配置します。

疑似コードは以下のとおりとなります。

ピースが配置された文字数 = 0
基準文字数 = 格子の総文字数 × 80%
while( ピースが配置された文字数 < 基準文字数 ):
    ピースの種類をランダムに選択
    ピースの位置をランダムに選択
    if(新しいピースが既存のピースと重ならない):
       新しいピースを格子に配置する
       ピースが配置された文字数 += 新しいピースの文字数
残った格子に1文字のピースを配置する

キーワードを選ぶ

キーワードの選定については、『現代日本語書き言葉均衡コーパス』短単位語彙表 ver.1.0を参考にしました。 pj.ninjal.ac.jp

  • 3文字、4文字のリスト 「名詞-普通名詞」の中から、各200単語ずつを選定しました。

  • 2文字のリスト 任意の1文字を2つ並べた場合、偶然に意味のある単語となる可能性が高く、ゲームとしての難易度を大きく下げる要因になり得ます。
    (例えば、アから始まる2文字の名詞だけでも、「愛(アイ)」「青(アオ)」「赤(アカ)」「秋(アキ)」等多数存在)
    そこで、難易度調整を目的として、2文字のリストには語彙表に掲載されていない、すなわち単語として意味を成さない文字列を選定しました。

3. 実装してみる

リストの構成

リストの構成は以下のとおりとなります。

リスト番号 リストの説明
[LIST1] キーワード(1文字)
[LIST2] キーワード(縦2文字,不使用)
[LIST3] キーワード(縦3文字)
[LIST4] キーワード(縦4文字)
[LIST5] キーワード(横2文字)
[LIST6] キーワード(横3文字)
[LIST7] キーワード(横4文字)
[LIST8] パズル(左半分)
[LIST9] パズル(右半分)

制約条件を考慮して実装する

ツイート文字数の制約

Twitter上でツイート可能な文字数の制約から、診断結果本文に使える文字数は全角換算で120文字以下となります。制約条件の詳細については前回のクソ診断紹介記事をご覧ください。

クソ診断紹介1「ちんぽ揃えゲーム」 - にゃーん

(なお、この節における「文字」および「文字数」は、全角換算のものを示すこととします)

格子の行数をR、列数をCとすると、消費される文字数は以下の通りとなります。

  • 文字に R×C 文字
  • 改行に 0.5(R-1) 文字

今回は、格子サイズを行数 R=8 、列数 C=10 と設定したため、格子部分で83.5文字が消費されることになります。

残りの36.5文字で、文字の羅列が何を意味するかツイート冒頭に説明を加えます。

最初に見つけた3つの言葉が、[USER]に今必要なものです。(改行2回)

ここで、[USER]には診断トップ画面で入力された名前が入ります。
[USER]を除いた文字数は24.5文字のため、[USER]が12文字以内であれば、診断結果が途切れることなくツイートされます。

リストの値の文字数の制約

診断メーカーのシステムの都合上、リストの各値の文字数は、300文字以内に制限されております。
(なお、この節における「文字」および「文字数」は、全角半角を問わず1文字としてカウントしたものを示すものとします)
パズルのリストでは、用いたピースのリストを順番に参照していきます。その際、[LIST]表記も全て文字数としてカウントされます。また、パズルのリストは行ごとにカンマで区切られるため、縦のピースのリストは分断され、文字数と同じ回数だけ参照する必要があります(図3)。

f:id:yryrrrrryryr:20191209071230p:plain:w400
図3 ピースの方向によるリスト参照回数の違い

ピースの文字数を n としたとき、リスト参照時に消費される文字数は以下のとおりとなります。

ピースの方向 リストの枝番が1桁の場合 リストの枝番が2桁の場合
11n 12n
9 10

なお、同一のピースのリスト(文字数と方向が等しい)から10種類以上のキーワードを参照する事は少ないため、以降リストの枝番は常に1桁と仮定して話を進めます。
1文字のピースの占める割合が20%で、残りの5種類のピースが等確率で選ばれると仮定したとき、 RC 列の格子のパズルにおけるピースごとの期待出現数および期待リスト消費文字数は以下のとおりとなります。

ピースの種類 消費文字数/ピース 期待出現数 期待リスト消費文字数
1文字 9 0.20RC 1.80RC
縦3文字 33 0.05RC 1.65RC
縦4文字 44 0.05RC 2.20RC
横2文字 9 0.05RC 0.45RC
横3文字 9 0.05RC 0.45RC
横4文字 9 0.05RC 0.45RC

よって、RC 列の格子のパズルのリストを記述するのに必要な文字数は、期待リスト消費文字数の総和 7RC 文字に、行ごとのカンマ区切り 0.5(R-1) 文字を加えたものとなります。

リストの各値の文字数の制約より、

7RC + 0.5(R-1) ≦ 300

が満たされる必要がありますが、作成予定の8行10列の格子では期待リスト消費文字数が563.5文字となり、制約条件を大幅に超過してしまいます。
そのため、格子を左右で2分割する方針を取りました。具体的には、左半分と右半分でそれぞれ8行5列のパズルを抽選し、最終的な結果表示時に結合するようにしました。この場合、期待リスト消費文字数は283.5文字で制約条件を満たすようになります。なお、ランダムに選択されたピースが縦方向のものに偏り、制約条件を満たさなくなるパズルは用いない事としました。

格子を左右で2分割した事により、横方向のピースが5列目~6列目を跨ぐことができないのは大きなデメリットですが、パズルの組み合わせ総数の増加につながっている側面もあります。
(今回は左用のパズルを50個、右用のパズルを50個作成したため、パズルの組み合わせ総数は2,500個)

4. おわりに

ほぼ1年前に作成したクソ診断を思い出したらブログを執筆していたら、夜を明かしてしまいました。何という贅沢な時間の使い方でしょう。 今週の診断はクソ要素薄めの診断紹介になってしまい申し訳ありません。とはいえ、キーワードに用いる単語のユーモア次第では、クソ診断に化けるポテンシャルは秘めているかもしれません。 来週は、グー、チョキ、パーの他に下半身が出せる「下半身ジャンケン」を紹介したいと思います。それではまたお会いしましょう。

(参考) ソースコード

診断に使用した基本診断テキストおよび[LIST8]、[LIST9] (パズル部分)をgithubに公開しています。 github.com