Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Ruby "enbugging" quiz の別解を求めて(@j5c8k6m8)
Search
coincheck
June 05, 2024
0
79
Ruby "enbugging" quiz の別解を求めて(@j5c8k6m8)
Ruby Kaigi 2024 のリキャップイベントで使用したスライド
coincheck
June 05, 2024
Tweet
Share
More Decks by coincheck
See All by coincheck
スクラム成熟度セルフチェックツールを作って得た学びとその活用法
coincheck_recruit
1
140
サイロ化した金融システムを、packwerk を利用して無事故でリファクタリングした話
coincheck_recruit
4
4k
CTOレター
coincheck_recruit
0
150
暗号資産取引所のアーキテクチャとセキュリティ
coincheck_recruit
0
2.5k
ブロックチェーン領域に異業種転職したエンジニアたちの近況報告会
coincheck_recruit
1
850
コインチェック会社紹介資料/Coincheck Company description
coincheck_recruit
0
67k
コインチェック バーチャルオフィスツアー
coincheck_recruit
0
7.1k
Featured
See All Featured
Designing the Hi-DPI Web
ddemaree
280
34k
[RailsConf 2023] Rails as a piece of cake
palkan
52
4.9k
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.2k
A Philosophy of Restraint
colly
203
16k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
Testing 201, or: Great Expectations
jmmastey
38
7.1k
Building Your Own Lightsaber
phodgson
103
6.1k
Designing for Performance
lara
604
68k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Art, The Web, and Tiny UX
lynnandtonic
297
20k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
329
21k
Transcript
Ruby "enbugging" quiz の別解を求めて 2024.06.04 kusaka (@j5c8k6m8)
©2024 Coincheck Inc. 自己紹介
©2024 Coincheck Inc. • アプリケーション基盤G に所属 ◦ Rails update ◦
モジュラモノリス推進 ◦ 認可 / 認証 ◦ 開発規約の整備 自己紹介 • 元 SIer 出身 • たまに Qiita とか Zenn とか • kusaka と読み替えて下さい
©2024 Coincheck Inc. Ruby "enbugging" quiz とは
©2024 Coincheck Inc. Ruby "enbugging" quiz https://ruby-quiz-2024.storesinc.tech/ RubyKaigi2024 の STORES
さんの企画 Rubyコミッタである、遠藤(mame) さんが作成 mame さんの quiz は毎年の RubyKaigi の楽しみの一つ (画像はmame さんのセッションより引用) https://speakerdeck.com/mame/good-first-issues-of-typeprof?slide=3
©2024 Coincheck Inc. Ruby "enbugging" quiz • 全部で 12 Stage
(3Stage/日. 全問解いた後の extra で追加 3stage) • クリア条件: Expected error に記載のエラーを発生させること • 手順: ◦ 最初から表示されている コードの一部を書き換える ▪ 書き換えた量 (diff) に応じて Score が変わる ◦ 実行ボタン を押す ▪ Expected error のエラーが発生したらクリア n → nil クリア! (例年より簡単?..)
©2024 Coincheck Inc. Ruby "enbugging" quiz Day 1 できた! 3問で18
なるほど。。 自力で解けると気持ちいいので、まずはチャレンジを ただ解くだけではなく、低スコアチャレンジもできるという2段構えの quiz (すべて、Score 1での解が用意されている?) 間違い探しのように、 答えを知っちゃうと、 探す楽しみがなくなるタイプ
©2024 Coincheck Inc. Ruby "enbugging" quiz 5/27 に STORES さんの
テックブログから mame さんの公式解説記事 も出していただいてます! (予想通り、全ての問題が Score 1で解けます) https://product.st.inc/entry/2024/05/27/113038 (※ ネタバレ防止のため、マスク) 私はここでいう 別の回答 で解いたな、、 他にも解説記事で紹介されてない、 Score 1 の別解があるのでは? Solver プログラム を作って、別解を確認してみよう! 必読!
©2024 Coincheck Inc. Solver を作る
©2024 Coincheck Inc. Solver を作る https://github.com/cc-kusaka/rubykaigi2024_after_enbugging_quiz_solver 作成した Solver(リポジトリ) の URL
と QRコード この後の話の ネタバレ含む Ruby "enbugging" quiz のエラー形式は、 markdown friendly に改善された 3.4.0 形式なことに注意 (引用) mame さんのセッション ("Good first issues of TypeProf") より https://speakerdeck.com/mame/good-first-issues-of-typeprof?slide=2 コードは ruby 3.4.0 の環境で 実行してください
©2024 Coincheck Inc. Solver を作る まずは、問題を json 形式で保存 (stage 毎の
expected_error と source を保持した hash)
©2024 Coincheck Inc. Solver を作る 用意したJSON読み込み 結果JSON出力 各文字位置 に対して、 文字削除
or ASCII の各文字挿入 のケース で 解答となる source を作成 eval で実行 SyntaxError は StandardError ではない点に注意 正解かの判定
©2024 Coincheck Inc. Solver を作る 警告を抑止 (RUBYOPT=”W0”) し、 評価コード中の puts
の標準出力を無視 ( 1> /dev/null) して、 実行! 想定外のエラーが発生!
©2024 Coincheck Inc. eval で実行 eval での評価コードが外側の変数を、 参照して書き換えてしまっていた Solver を作る
©2024 Coincheck Inc. Solver を作る (instance_eval で)
©2024 Coincheck Inc. Solver を作る(instance_eval) TOPレベルの変数を削除し、 instance_eval を利用した、 実行環境用のクラスを用意 毎回
instance を生成
©2024 Coincheck Inc. Solver を作る(instance_eval) 正常終了!したが.. 結果ファイルにStage 7 の回答が出力されていない
©2024 Coincheck Inc. Solver を作る(instance_eval) 発生したエラーに特異クラスの module名が入ってしまい、 Expected error が一致しなくなってしまっていた。
Actual error: private method 'main' called for an instance of #<Class:0x000000010091e9d8>::C (NoMethodError) Stage 7 のケース(Class名の問題) 以外にも、 グローバル変数やクラス変数がリセットされない問題もありそう。 問題中にclass 定義
©2024 Coincheck Inc. Solver を作る (コマンド実行 で) Take3
©2024 Coincheck Inc. • バッククォートでコマンド実行して結果を受け取る • 標準エラー出力を、標準出力に流して受け取る • エラー出力には、行数なども含まれるためinclude? で判定する
Solver を作る(コマンド実行) コードをファイル出力
©2024 Coincheck Inc. ※ esa_io さんのブログ (https://docs.esa.io/posts/509) で、 solver (https://github.com/fukayatsu/ruby-quiz-2024/blob/main/solve.rb)
が紹介されていました。 こちらは、Thread を利用した多重処理で重さを回避しているようでした。 (エラー取得も Open3 モジュールを利用) 実行が終わらない (全体だと数時間かかる) Solver を作る(コマンド実行) Stage 1 に限定して 15分21秒 instance_eval 版は 0.3秒
©2024 Coincheck Inc. Solver を作る (forkを使って) Take4
©2024 Coincheck Inc. Solver を作る(fork) Stage7 を考慮し、Object の class_eval で実行。
別プロセスで実行するので、 グローバル変数を含む各種変数が、 前の施行の影響を受けない。 fork でプロセスを複製し、結果を IO.pipe でやりとり (pipe 周りでコードがちょっと長くなる) 都度 wait をするので実質 1並行
©2024 Coincheck Inc. Solver を作る(fork) 全体でも 3分22秒 で終了 並列処理版にす る
並列処理にする 全体で 1分5秒 に短縮
©2024 Coincheck Inc. Solver を作る(fork) 実際にやってみても、 undefined local variable or
method になり、クリアにならない ‘j’ を入れる誤解答が提示 ‘j’ を入れる誤解答が提示
©2024 Coincheck Inc. Solver を作る(fork) require ‘json’ で ‘j’ メソッドが生えていた!
https://github.com/ruby/ruby/blob/d50404d6fe9dcd991dbad4f8757d23d38d1b5b80/ext/json/lib/json/common.rb#L658-L663
©2024 Coincheck Inc. Solver を作る (まとめ)
©2024 Coincheck Inc. Solver を作る(まとめ) • 隔離された Clean な実行環境を用意するのには、一定コストが必要 •
現状では fork でプロセスコピーが、(性能を含めた)一定解か。(require 問題はあるが) # Solver の内容 実行時間 (Stage 1のみ) 出力結果 1 (グローバルスコープで) eval を利用 - • クロージャを参照して失敗 2 (スコープを意識して) instance_eval を利用 0.3秒 • 実行環境のモジュール名の差異が発生 • クラス変数やグローバル変数を実行都度リセットできない 3 (ファイル出力と) コマンド実行を利用 (single) 15分 21秒 • 基本的には問題なし • Error の一致判定は標準エラー出力の部分一致を利用 4 fork を利用 (single) 19.3秒 • 評価前の `require` などで 環境に差異が発生 5 fork を利用 (multi) 6.6秒 • 同上
©2024 Coincheck Inc. # Solver の内容 実行時間 (Stage 1のみ) 出力結果
1 (グローバルスコープで) eval を利用 - • クロージャを参照して失敗 2 (スコープを意識して) instance_eval を利用 0.3秒 • 実行環境のモジュール名の差異が発生 • クラス変数やグローバル変数を実行都度リセットできない 3 (ファイル出力と) コマンド実行を利用 (single) 15分 21秒 • 基本的には問題なし • Error の一致判定は標準エラー出力の部分一致を利用 4 fork を利用 (single) 19.3秒 • 評価前の `require` などで 環境に差異が発生 5 fork を利用 (multi) 6.6秒 • 同上 Solver を作る(まとめ) • 隔離された Clean な実行環境を用意するのには、一定コストが必要 • 現状では fork でプロセスコピーが、(性能を含めた)一定解か。(require 問題はあるが) ◦ Ruby に Namespace が導入されるのに期待 ▪ 少なくとも、require ‘json’ 問題は解決可能なはず ▪ instance_eval のような方法でも実現可能になるかも
©2024 Coincheck Inc. 別解を見る 別解あったよ
©2024 Coincheck Inc. 別解を見る # Expected error 解数(※1) 別解 Stage
1 undefined method '+' for nil (NoMethodError) 11 有 Stage 2 undefined method 'downcase' for nil (NoMethodError) 16 無 Stage 3 wrong number of arguments (given 2, expected 3) (ArgumentError) 1 無 Stage 4 nil can't be coerced into Integer (TypeError) 9 有 Stage 5 index -4 too small for array; minimum: -3 (IndexError) 1 無 Stage 6 negative argument (ArgumentError) 7 有 Stage 7 private method 'main' called for an instance of C (NoMethodError) 5 無 Stage 8 cyclic include detected (ArgumentError) 7 有 Stage 9 wrong number of arguments (given 1, expected 0) (ArgumentError) 11 有 Stage A cannot clamp with an exclusive range (ArgumentError) 10 無 Stage B 0: 1 === 0 does not return true (NoMatchingPatternError) 1 無 Stage C invalid radix 52 (ArgumentError) 2 無 (※1) 空白文字の違いは1でカウント 面白いと思った 3つの別解を紹介します(ネタバレ含む)
©2024 Coincheck Inc. 別解を見る (Stage1)
©2024 Coincheck Inc. 別解を見る (Stage 1) 解は11個 9パターン 解説でも4パターンが紹介されている
©2024 Coincheck Inc. += を使うことでnil 初期化 .追加で、メソッドチェーンにして 右辺から評価させる (1_000.p は
no method だけど) 1文字メソッドの p を追加 別解を見る (Stage 1) 削除, ‘#’, ‘@’, ‘$’ が公式解説でも言及されていた ‘+’, ‘.’, ‘p’ を追加する方法(上記以外の箇所も含めて) が別解
©2024 Coincheck Inc. 別解を見る (Stage6)
©2024 Coincheck Inc. 解は7個 6パターン 「どこかに、改行を入れる」 という解がある 別解を見る (Stage 6)
©2024 Coincheck Inc. 配列として代入できる記法 (知らなかった) 解説では、n = *10 が紹介。 別解を見る
(Stage 6) 公式の解説もとにかく面白いので すが(コメントがひっかけ) そのコメントを利用する別解
©2024 Coincheck Inc. 別解を見る (Stage4)
©2024 Coincheck Inc. 別解を見る (Stage 4) 解は9個 7パターン 「どこかに、’%’ を入れる」
という解がある
©2024 Coincheck Inc. 別解を見る (Stage 4)
©2024 Coincheck Inc. 別解を見る (Stage 4) 文字列リテラルの % 記法の区切 り文字がスペース
と理解して読むと以下になる
©2024 Coincheck Inc. Score1 での解の数 紹介していない別解もあるので、興味ある人は 以下の回答(と公式の解説)を見てみてください。 https://github.com/cc-kusaka/rubykaigi2024_after_enbugging_quiz_solver/blob/main/answers3.json # Expected
error 解数(※1) 別解 Stage 1 undefined method '+' for nil (NoMethodError) 11 有 Stage 2 undefined method 'downcase' for nil (NoMethodError) 16 無 Stage 3 wrong number of arguments (given 2, expected 3) (ArgumentError) 1 無 Stage 4 nil can't be coerced into Integer (TypeError) 9 有 Stage 5 index -4 too small for array; minimum: -3 (IndexError) 1 無 Stage 6 negative argument (ArgumentError) 7 有 Stage 7 private method 'main' called for an instance of C (NoMethodError) 5 無 Stage 8 cyclic include detected (ArgumentError) 7 有 Stage 9 wrong number of arguments (given 1, expected 0) (ArgumentError) 11 有 Stage A cannot clamp with an exclusive range (ArgumentError) 10 無 Stage B 0: 1 === 0 does not return true (NoMatchingPatternError) 1 無 Stage C invalid radix 52 (ArgumentError) 2 無 (※1) 空白文字の違いは1でカウント
©2024 Coincheck Inc. さいごに
©2024 Coincheck Inc. • まずは、何よりも、本 LT の前提となる 「Ruby "enbugging" quiz」を
作成/提供していただいた、Stores さん、 mame さん、関係者の方々に感謝します。 • mame さんが提供している quiz は、ものすごく楽しいので、ぜひ参加してください。 • 変わったプログラムを書いたり読んだりすると、言語の背景が薄く見えるような感覚があっ て楽しいですね。 • 来年は TRICK2025 の開催も決定しているので、チャレンジしたいです(宣言) さいごに
©2024 Coincheck Inc. 業務に関係ないけどこういうことをやる利点的なやつ書く? rubykaigi2024 と mame さんへの感謝 coincheck の採用とかについて?
さいごに https://hrmos.co/pages/coincheck/jobs/0000551
©2024 Coincheck Inc. さいごに ご清聴ありがとうございました!