Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rubyの配列クイズで最大の難問はどれか(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

参考: class Array (Ruby 3.2 リファレンスマニュアル)

Rubyの配列クイズで最大の難問はどれか(翻訳)

RubyのArrayクラスには、Rubyエコシステムで最も多用されるメソッドがいろいろ含まれています。数か月前に、Rubyの配列や配列に関連するメソッドの知識を問うクイズを公開しました。この短い記事では、クイズの平均的な成績を確認して、どのクイズが最も難しかったかを明らかにします。

はじめに

数か月前に、以下のRubyの配列操作クイズを公開しました。

クイズは10問で、Ruby言語におけるこの基本コンポーネントに関する知識をセルフテストできます。

本記事では、寄せられた解答を元に平均的な成績をチェックして、どの問題が最も難しかったかを明らかにします。

成績別の内訳

本記事執筆時点では324件の回答が登録されており、平均値はわずか29%でした。得点分布を以下の棒グラフにまとめました。

点数を登録した回答者数を0~10点、10~20点、90~100点のバケットごとに振り分けた度数分布図

Ruby配列クイズ受験者の得点分布

全回答の平均値は29%で、最頻値は30〜39です。高得点を獲得した解答は非常にまれでした。実際、本記事執筆時点では、得点が70%を超えればトップ5%入りで、得点が80%を超えたのはわずか3件でした!

問題別の内訳

次に、個別の問題についてユーザーがどう回答したかを見てみましょう。以下の棒グラフのバーをクリックすると、その問題のスクリーンショットが表示されます(訳注: 動的な操作は元記事で行ってください)。

問題別の内訳

最も難易度の高かった問題

グラフを見ると、問6が正答率わずか2.07%で最も難問だったことがすぐ見て取れます。この問6は、配列(および文字列)に対してsplitjoinreversemapsumといった一般的な操作を組み合わせた操作について考えるものです。個別のメソッドについて詳しくは公式ドキュメントのArrayおよびStringで学べます。以下は問6の実際の出題内容です。

問6: 結果が文字列123456になるのは以下のどれか

Ruby配列クイズの最難問
次の中から"12345"という文字列になるものを1つ以上選べ

この問題では、文字列"12345"を生成する方法がいくつか提示されています。期待通りの結果を返すものもあれば、そうでないものもあります。この問題は複数回答ありです。ここで重要なのは、String#splitメソッドに関する知識です。

"once,twice,three times a lady".split(",")
=> ["once", "twice", "three times a lady"]

このメソッドは、指定された区切り文字に基づいて文字列を分割し、配列にします。ここでは区切り文字としてカンマ,を渡しています。このメソッドのドキュメントを読んでみると、分割するパターンを指定しない場合は事実上ホワイトスペース1で分割することがわかります。

パターンがnilの場合は、特殊変数$;の値が使われます。$;nil(デフォルト)の場合、を指定したかのようにホワイトスペースによって文字列が分割されます。
split -- Class: String (Ruby 3.1.1)より

'12345'のようにホワイトスペースが含まれていない文字列を分割すると、['12345']のように要素を1個のみ含む配列を返します。この点を理解しておくことが、以下で提案する2つの解決方法を理解するうえで重要になってきます。それぞれのオプションを順に見ていきましょう。

(1...5).map(&:to_s).join('')
range (1...5) には3つのドット...が含まれており、これは末尾の5を含まないという意味になるので、この式の結果は"1234"という文字列になります。
なお、(1..5)のようにドットを2つ..にすれば、期待通りの結果を得られます。
"54321".split.reverse.join
文字列"54321"splitを適用すると、要素1個の配列になります(デフォルトではホワイトスペースで区切られます)。Array#reverseは要素1個の配列に対しては効かないので、joinしても"54321"になるだけです。つまりこれは期待通りの結果ではありません。
なお、この例でsplit('')を使えば、期待通りの出力を得られます。
"54321".reverse
文字列にreverseを適用すると、期待通りの結果が得られます。つまりこれは有効な回答です。
12345.to_s.split.sum('')
数値12345を文字列に変換してからsplitsumを実行するのは論理的に正しそうに思えますが、既に説明したように、ここでsplitが生成するのは要素1個の配列になります。つまりsplit.sum('')という操作は文字列に何の効果も及ぼさず、結果は"12345"のままです。しかしこれは期待通りの結果なので、有効な回答です。

まとめ

本記事では、以前公開したRuby配列クイズに登録された結果を簡単に分析してみました。最も難易度が高かったのは問6で、この問題ではArrayStringのメソッドに関する理解を問います。この問題に対する正答を調べながら、学習のポイントを確認しました。特にString#splitメソッドは、引数なしで呼び出すと区切り文字にホワイトスペースを使うのがデフォルトの振る舞いです。

短い記事ですが、お役に立てられれば幸いです。ご質問やお気づきの点がありましたら元記事末尾のコメント欄までどうぞ。本記事をお楽しみいただけましたら、新着記事をすぐ読めるようぜひ購読をご検討ください。お読みいただきありがとうございました。

参考情報

  1. 元のRuby配列クイズ: Test Yourself on Ruby Array Operations
  2. Rubyの配列でSetの操作を行う: Using Set Operations on Ruby Arrays
  3. Rubyの公式ドキュメント: Array
  4. Rubyの公式ドキュメント String

関連記事

Rubyオブジェクトモデルのクイズで最大の難問はどれか(翻訳)


  1. 訳注: 一般にホワイトスペース(whitespace)と呼ぶ場合、半角スペース文字()の他に、改行文字(\n)やTab文字(\t)も加えたものを指します。なお全角スペース( )はホワイトスペースに含まれないのが普通です。参考: スペース - Wikipedia 

CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。