ヒューマン・リソース・マシーン 攻略 入社19年目 カウントダウン
ここで解説している内容なりヒントなりはあくまで筆者の解法に基づいたものなので、別の考え方ももちろんあるよ。ってのは念頭に置いてください。
課題
左側の数値を0までカウントダウン、もしくはカウントアップした結果を右側に運んでください。
使用可能な命令
- inbox
- outbox
- copyfrom
- copyto
- add
- sub
- bump+
- bump-
- jump
- jump_if_zero
- jump_if_neg
初出命令
- bump+/bump-
指定したカーペットの上に乗っている数値を+/- 1してその数値のコピーを手元に用意する。上に何も乗っていないカーペットを指定すると?
上司に怒られてお仕事中断(終了)。既に手にパネルがある状態で実施すると?
手に持っているパネルを捨てて、コピーを手元に用意する。
効率目標
- サイズ:10行
- スピード:82ステップ
ヒント
その1
考え方は実は17年目と変わらない。
難しく感じるときはあれこれ考えずに愚直にやるのが実は一番の近道だったりする。
最初のパネルがマイナスの時と、マイナスじゃない時(プラス)の時で、処理を分けて考えよう
その2(サイズ目標)
0までカウントダウン = 0を運んだら1セット終了。
運んだパネルを判断するにはどうすれば良いだろう?
その3(スピード目標)
もし今の値に対して都度+/-の判断をしているのであれば、17年目の時のように完全に処理を分けた方が早くなる。
その3(スピード目標)
※ここで紹介している解法でサイズ目標を満たしている前提
copyfromはステップで考えると完全に無駄。どうにかしてcopyfromを使わないで処理終了を判断しよう。
その4(スピード目標)
※ここで紹介している解法でサイズ目標を満たしている前提
0を超えてカウントダウンするとどうなる?
回答例 + 解説
サイズ
回答例 + 解説
ラベル1:// 1セットの開始位置 1. inbox 2. copyto 0 ラベル3:// 右へ運ぶ 3. outbox 4. copyfrom 0 5. jump_if_zero:ラベル1へ 6. jump_if_neg:ラベル2へ // プラス用処理(カウントダウン) 7. bump- 8. jump:ラベル3へ ラベル2:// マイナス用処理(カウントアップ) 9. bump+ 10. jump:ラベル3へ
運んだパネルが0であったら次へ、運んだパネルは保持してあるから運んだ後でも判断できる。
左のパネルをとって(inbox)、計算用に一旦保持(copyto)
手元のパネルを運んで(outbox)、判断用に再度運んだものと同じパネルを手元に用意(copyform)して、
運んだパネルが0であったなら次のパネルへ(jump)。
0じゃないなら、マイナスなら(jump_if_neg)カウントアップ(bump+)、マイナスじゃないならカウントダウン(bump-)する。
これを0を運ぶまで繰り返す(jump)
スピード
回答例 + 解説
ラベル1:// 1セットの開始位置 1. inbox 2. copyto 0 3. jump_if_neg:ラベル2へ ラベル3:// プラス用処理(カウントダウン) 4. outbox 5. bump- 6. jump_if_neg:ラベル1へ 7. jump:ラベル3へ ラベル2:// マイナス用処理(カウントアップ) 8. outbox 9. bump+ 10. jump_if_neg:ラベル2へ 11. outbox 12. jump:ラベル3へ
最初のパネルがマイナスの場合は、マイナス用の処理。マイナスじゃない場合は、プラス用の処理。
プラス用の処理は0判断しようとすると少し面倒(※)なので気にせずカウントダウンするとマイナスに突入することを利用。
※分岐を組むのが面倒なだけで、0判断でもスピード目標は達成できる。
左のパネルをとって(inbox)、計算用に一旦保持(copyto)
マイナスならマイナス用の処理へジャンプ(jump_if_neg)、マイナスじゃないならプラス用の処理を実行。
* マイナス用処理
手元のパネルを運んで(outbox)、カウントアップ(bump+)
マイナスのままならマイナス用の処理を繰り返す(jump_if_neg)、マイナスじゃない(=0)なら0を運んで(outbox)次のパネルへ(jump)
* プラス用処理
手元のパネルを運んで(outbox)、カウントダウン(bump-)
マイナスなら次のパネルへ(jump_if_neg)、マイナスじゃないならプラス用の処理を繰り返す(jump)