ヒューマン・リソース・マシーン 攻略 入社38年目 数字をバラせ
ここで解説している内容なりヒントなりはあくまで筆者の解法に基づいたものなので、別の考え方ももちろんあるよ。ってのは念頭に置いてください。
課題
左側のパネルの数値を桁ごとに分解して右側へ運んで下さい。
たとえば数字が123だったら、答えは「1,2,3」になります。
使用可能な命令
- inbox
- outbox
- copyfrom
- copyto
- add
- sub
- bump+
- bump-
- jump
- jump_if_zero
- jump_if_neg
効率目標
- サイズ:30行
- スピード:165ステップ
ヒント
その1
各桁の値を出すためには割り算をすれば良い。
割り算は[23年目]で実施済み
その2
101など、10の位が0のケースをカバーするためにはどうすればよい?
その3(スピード目標)
大きい数値はまとめて処理してしまえばよい。
回答例 + 解説
サイズ
回答例 + 解説
1. jump:ラベル1へ ラベル2:10の位を運ぶ 2. copyfrom 10の位 3. outbox ラベル3:1の位を運ぶ 4. copyfrom 0 5. outbox ラベル1:// 1セットの開始位置 6. inbox 7. copyto 0 8. sub 10 9. jump_if_neg:ラベル3へ // 10以上だった場合の処理 10. copyfrom 9 11. copyto 10の位 12. copyto 100の位 ラベル4:// 100の位の算出 13. copyfrom 0 14. sub 11 15. jump_if_neg:ラベル5へ 16. copyto 0 17. bump+ 100の位 18. jump:ラベル4へ ラベル5:// 100の位を運ぶ 19. copyfrom 100の位 20. jump_if_zero:ラベル6へ 21. outbox ラベル6:// 10の位の算出 22. copyfrom 0 23. sub 10 24. jump_if_neg:ラベル2へ 25. copyto 0 26. bump+ 10の位 27. jump:ラベル6へ
各桁の値を出すためには割り算をすれば良い。割り算は[23年目]で実施済み。
101などに対応するため、最初に10以上かを判定するのがポイント
パネルを拾って(inbox)、一旦保持(copyto 0)
10以上か判定(sub 10)し、10より小さかった場合(jump_if_neg)は、保持したパネル(copyfrom 0)をそのまま運ぶ(outbox)
10以上の場合は各桁を計算してから運ぶ
各桁の初期化用に0を取得(copyfrom 9)し、10の位,100の位をそれぞれ初期化する(copyto)
保持している値を取得(copyfrom)し、100で割り算(sub 11 ~ bump+ 100の位)
割り切れなくなったら(jump_if_neg)、100の位(copyfrom 100の位)を運ぶ(outbox)
この時、100未満の場合は100の位が0になるため、その場合は運ばない(jump_if_zero)ようにする。※先に100以上か?の判定を入れても良いがの場合はサイズが膨れる
同様に10で割り算(sub 10 ~ bump+ 10の位)を行い、割り切れなかったら10の位を運ぶ。
例によって無駄なジャンプが発生しないようにoutboxとinboxがつながるように配置して、初回の無駄処理(inboxより前)は実行しないように飛ばす(jump)。
スピード
回答例 + 解説
1. copyfrom 11 2. add 11 3. add 11 4. copyto "300" 5. copyfrom 10 6. add 10 7. add 10 8. copyto "30" 9. jump:ラベル1へ ラベル2:10の位を運ぶ 10. copyfrom 10の位 11. outbox ラベル3:1の位を運ぶ 12. copyfrom 0 13. outbox ラベル1:// 1セットの開始位置 14. inbox 15. copyto 0 16. sub 10 17. jump_if_neg:ラベル3へ // 10以上だった場合の処理 18. copyfrom 9 19. copyto 10の位 20. copyto 100の位 ラベル4:// 100の位の算出 // 300でまとめて計算 21. copyfrom 0 22. sub "300" 23. jump_if_neg:ラベル7へ 24. copyto 0 25. bump+ 100の位 26. bump+ 100の位 27. bump+ 100の位 28. jump:ラベル4へ ラベル7:// 100で計算 29. copyfrom 0 30. sub 11 31. jump_if_neg:ラベル5へ 32. copyto 0 33. bump+ 100の位 34. jump:ラベル7へ ラベル5:// 100の位を運ぶ 35. copyfrom 100の位 36. jump_if_zero:ラベル6へ 37. outbox ラベル6:// 10の位の算出 // 30でまとめて計算 38. copyfrom 0 39. sub "30" 40. jump_if_neg:ラベル8へ 41. copyto 0 42. bump+ 10の位 43. bump+ 10の位 44. bump+ 10の位 45. jump:ラベル6へ ラベル8:// 10で計算 46. copyfrom 0 47. sub 10 48. jump_if_neg:ラベル2へ 49. copyto 0 50 bump+ 10の位 51. jump:ラベル8へ
前述の内容でサイズ目標をクリアしている前提。
大きい数値用300/30を作って、3つ分を一気に計算して処理を短縮する
最初に300(copyfrom 11 ~ copyto "300")と30(copyfrom 10 ~ copyto "30")を作って、 あとは100/10で割っていたタイミングにそれぞれ差し込むだけ