2021/10/29

ヒューマン・リソース・マシーン 入社17年目−同じならゼロ

目次

1)課題

左側の数値を2つごとに、判断を行い、2つの数字のプラスorマイナスが同じ場合は「0」を違う場合は「1」を右側に運んでください。

2)考え方

2つの数値で掛け算をして, 結果がプラスなら同じ, マイナスなら異なると判断できますが, ヒューマン・リソース・マシーンでは掛け算を使えません. 一つずつ解決していきます. 

まず, 左のコンベアから1枚目のパネルを取り出し, プラスかマイナスかを判定します.

  1. プラスの場合, 2枚目のパネルを取り出し, プラスかマイナスかを判定します.
     プラスなら「0」,
     マイナスなら「1」
    を右のコンベアに運びます.
  2. マイナスの場合, 同じように2枚目のパネルを判定します.
     プラスなら「1」,
     マイナスなら「0」
    を右のコンベアに運びます.

この考え方に従い, 課題を解決していきます.

3)実装

左のコンベアからパネルを取り出し, 数値がプラスかマイナスかを判定します. JUMP if negativeコマンドを使えばマイナスであるかを判定できます. JUMP if negativeコマンドを使って条件分岐を作っていきますが, 構造が複雑になるためラベルを使います. また, ゴールを明確にするために, 出力するコードを作ります. 

数値の正負が同じなら「0」, 違うなら「1」を右のコンベアに運びます.

続けて, 左のコンベアからパネルを取り出し, その正負を判定します. 1枚目のパネルの名前を「A」とします.

「A」がプラスの場合, 左のコンベアからパネルを取り出し, その正負を判定します. 2枚目のパネルの名前を「B」とします. 「B」がプラスなら「同じ」へ, マイナスなら「ちがう」へジャンプさせています.

同様にして, 「A」がマイナスの場合, 左のコンベアから2枚目のパネル「B」を取り出し, その正負を判定します.「B」がプラスなら「ちがう」へ, マイナスなら「同じ」へジャンプさせています. 「B」がマイナスの場合のJUMPコマンドは要りませんが, 対称性を尊重しています.

ここまでできれば課題をクリアーできます. 分かりやすさを優先してプログラムを作成したので, サイズ目標, スピード目標共に達成できていません. 

目次

2021/10/26

ヒューマン・リソース・マシーン 入社16年目−必ずポジティブに

目次

課題

左側のコンベアの数値を右側に運んで下さい。
ただし、その数値がマイナス値である場合は、マイナスマークを外してから右側に運んで下さい。

解説

この課題から, JUMP if negativeコマンドを使えるようになりました. JUMP if zeroコマンドは, 持っているパネルが0の時, 矢印の先に進みました. JUMP if negativeコマンドは, 持っているパネルがマイナス値の時, つまり0よりも小さい時, 矢印の先に進みます. つまり, JUMP if negativeコマンドを使えば, パネルの値がマイナス値であるか判定できます. 

パネルからマイナスマークを外す方法, つまり, 絶対値を求める方法を考えます. もし, 掛け算が使えるのであれば, -1を掛ければマイナスマークを外せます. しかし, ヒューマン・リソース・マシーンの世界には掛け算はありません. 別の方法が必要です.

少し考えると, 引き算を2回使えば, マイナスマークを外せることに気づきました. パネルの値が-8の時, 次のように計算をすれば, -8から8を得られます. 

―8―(―8)―(―8)=―8+8+8=8

マイナスマークを外す手順を考えてみます.

  1. 左のコンベアからパネルを取り, カーペット0番に置きます. 
  2. パネルがマイナス値であれば, 持っているパネルからカーペット0番のパネルを2回引きます. 結果を右のコンベアに運び, 最初に戻ります.
  3. パネルがマイナス値ではない, つまり, プラス値であれば, そのまま右のコンベアに運び, 最初に戻ります.

手順を素直にコードに置き換えました. このコードを実行すると課題をクリアーできます.

サイズ目標もスピード目標も達成できませんでした. これらの目標を達成するためのコードの最適化については, 記事を改めて解説します. 

目次

2021/10/23

ヒューマン・リソース・マシーン 入社14年目−大は小を兼ねる

目次

課題

左側の数値2つごとに数字の大小を比較し大きい方の数値を右側に運んで下さい。もし数値が同じである場合、いずれかを運んで下さい。
[JUMP if negative]が使えるようになりました。手元の値がマイナスの時だけ指定ジャンプ先に移動します。

解説

入社13年目では, 2枚のパネルが同じ値かを判定しました. この問題では, 値が大きい方のパネルを選びます. この問題でも同じようにSUBコマンドを使います.

SUBコマンドは, 持っているパネルの値から, カーペットに置いてあるパネルの値を引きます. つまり, SUBコマンドの結果がマイナスになれば, カーペットに置いてあるパネルの方が大きいと言えます.

アルゴリズムを考えると次のようになります.

  1. 1枚目のパネルを取りだし, カーペットの0番に置く.
  2. 2枚目のパネルを取りだし, カーペットの1番に置く.
  3. 持っているパネルとカーペット0番のパネルで減算をする. この時, 持っているパネルはカーペット1番の同じ値であることに注意.
  4. 減算の結果がマイナスであれば, カーペット0番のパネルの方が大きいので, カーペット0番のパネルを右のコンベアに運び, 最初に戻る.
  5. 減算の結果がマイナスでなければ, カーペット1番のパネルを右のコンベアに運び, 最初に戻る.

このアルゴリズムからコードを組み立てました. このコードを実行すると課題をクリアーできます.

クリアーはできましたが, サイズ目標もスピード目標も達成できませんでした. 2回使っているOUTBOXコマンドを1回にまとめられれば, サイズ目標を達成できそうです. コードの最適化については記事を改めます.

目次

2021/10/19

ヒューマン・リソース・マシーン 入社13年目−同じかどうか

目次

1)課題

左側の数値2つごとに、同値か否か判断をして下さい。同値である場合、その値を1つ右側に運んで下さい。同値でない場合は、捨てちゃってください。
コメント機能が使えるようになりました。コマンドの合間にコメント機能でメモをつけて考えを整理しましょう。

2)解説

2枚のパネルの値が同じであるかどうかを判定する方法を考えます. 11年目でSUBコマンドの使い方を学びました. 2枚のパネルで引き算をして結果が0であれば, 持っているパネルとカーペットのパネルが同じ, と言えます. 

SUBコマンドを使うためには, パネルをカーペットに置く必要がありますので, 2枚のパネルが同値かどうかを判定する手順は次のようになります. 

  1. 1枚目のパネルを取りだし, カーペットに置く.
  2. 2枚目のパネルを取りだし, カーペットに置いたパネルと減算をする. 
  3. 減算の結果が0であれば, カーペットのパネルを取り, 右のコンベアに運ぶ.
  4. 減算の結果が0でなければ, 最初に戻る.

図は, この手順をコードにした結果です. このコードを実行すると, 課題をクリアーできます.

このコードでサイズ目標は達成できましたが, スピード目標には届きませんでした. コードの最適化については, 記事を改めて解説します.

目次

2021/10/16

ヒューマン・リソース・マシーン 入社12年目−40の作り方

1)課題

左側の数値を40倍にして右側に運んで下さい。

2)解説

上司の言葉にもあるように, 入社8年目と10年目の成果を活用します. 

  1. 入社8年目では, 左側の数値を3倍にしました.
  2. 入社10 年目では, 左側の数値を8倍にしました. 

これらを活用して40倍にする方法を考えます. 8に5を掛ければ40になりますから, パネルの数値を8倍にし, その結果を5倍にすれば40倍となります. 

3行目から9行目までは, 入社10年目と同じようにして数値を8倍にしています. 10行目から13行目までは, 入社8年目と同じようにして数値を5倍にしています. 2行目で, カーペットの1番に左側のコンベアから取り出したパネルのコピーを置いています. これにより, 実行結果を検証できるようにしています. 

プログラムを実行した結果, 5の40倍となる200を作れました.

これまでの課題と同じようにして, OUTBOXコマンドとJUMPコマンドを追加してプログラムを完成させます. 

実行した結果, サイズ目標とスピード目標の両方を達成できました.

目次

2021/10/14

ヒューマン・リソース・マシーン 入社11年目−引き算の結果

課題

左側のパネル2つごと(A, B)に、2つのパネルを右側に運んで下さい。その際、1つめは(B-A)、2つめが(A-B)になるように運んで下さい。
[SUB]コマンドが使用可能になりました。手元のデータから、カーペット上の指定した番号に置かれたデータを減算します。

解説

ADDコマンドの対となるSUBコマンドの使い方を学ぶ問題です. 

ADDコマンドの場合, コマンドの解釈として次の2つのどちらを取ってもコマンドの実行結果は同じです.

  1. 持っているパネルにカーペットのパネルを加える.
  2. カーペットのパネルに持っているパネルを加える.

一方, SUBコマンドの場合, コマンドの解釈によって結果は異なります.

  1. 持っているパネルからカーペットのパネルを引く.
  2. カーペットのパネルから持っているパネルを引く.

SUBコマンドの動作を確認するために, コマンドを並べました. コードを実行すると, 次のようになります.

  1. カーペットの0番に3を置きます.
  2. カーペットの1番に8を置きます. この時, 8と書いたパネルを持っています.
  3. SUBコマンドを実行します. カーペット0番の3と持っている8とで引き算をします.

SUBコマンドを実行しました. 持っているパネルが8から5に変わりましたので, SUBコマンドは, 持っているパネル8からカーペットのパネル3を引いています. この結果は, 問題文のB-Aに対応します. この結果を右のコンベアに運べば, 上司からの要求の半分に応えられます. 

同様にして, A-Bも計算できます. 考え方は次の通りです.

  1. カーペットの0番はAに相当し, カーペットの1番はBに相当します.
  2. A-Bの結果が必要ですから, Aに相当するカーペット0番のパネルを持ち, SUBコマンドでカーペット1番を指定すれば, A-Bを計算します.
  3. OUTBOXコマンドで, 引き算した結果を右のコンベアに運びます.
このコードを実行すれば, 課題をクリアーできます.

サイズ目標もスピード目標も達成できました.

まとめ

  1. この課題では, SUBコマンドを使って持っているパネルからカーペットのパネルを引く方法を確認しました. (持っているパネル-カーペットのパネル)であり, 逆ではないことに注意が必要です.
  2. 減算した結果は持っているパネルに反映されます.
  3. パネルを持たずにSUBコマンドを実行するとエラーとなります. 逆にカーペットにパネルを置かずにSUBコマンドを実行してもエラーとなります. エラーとなると, 上司に怒られます.

目次

2021/10/12

ヒューマン・リソース・マシーン 入社10年目−3回で8を

1)課題

左側の数値を8倍にして右側に運んでください。

[ADD]をたくさん使えば、課題自体は簡単ですが、効率が悪いです。[ADD]の使用回数は3回でいけるハズです。考えてみましょう。

2)解説

ADDコマンドを7回使えば数値を8倍にできますが, 問題文にある通り効率が良くありません. 問題文には, ADDコマンドの使用回数は3回で良い, と書いてあります. 勘の良い人であれば, 2の3乗は8になることに気づくと思います. ヒューマン・リソース・マシーンのコマンドを組み合わせて, 8倍にする方法を探してみます.

左側のコンベアからパネルを取り, カーペットの0番と1番に置きます. 続けて, カーペットの1番に対してADDコマンドを実行し, その結果をカーペットの1番に置きます. カーペットの0番にパネルを置いた理由は, パネルの初期値を保存しておけば, 動作の確認がしやすくなるからです. このコードを実行することで, 左側のコンベアから取り出したパネルを2倍にできました. これを続けます.

ADDコマンドとCOPYTOコマンドを追加しました. これにより, 7を4倍した28になりました. 

この組み合わせをもう一つ追加すれば, 8倍にできます. ここまでできれば, もう少しでプログラムが仕上がります.

課題をクリアーするために, OUTBOXコマンドで持っているパネルを右側のコンベアに運び, JUMPコマンドで先頭に戻るようにしました. 

サイズ目標とスピード目標を達成できていません. 無駄なコマンドを取り除き, プログラムを最適化します. 2行目と9行目のCOPYTOコマンドは, 説明のために入れたコマンドですので, 取り除いてもプログラムの実行結果に影響を与えません.

サイズ目標である9行に収まりました. 

サイズ目標とスピード目標の両方を達成できました.

目次

2021/10/07

ヒューマン・リソース・マシーン 入社9年目−ゼロだけを残せ

 目次

1)課題

「0だけ」を右側に運んでください。

2)解説

入社7年目では0以外のパネルを右のコンベアに運びましたが, この問題では0だけを運ばなくてはなりません. 入社7年目で作成したコードをコピーして貼り付け, JUMP if zeroコマンドのジャンプ先を変更すれば課題をクリアーできそうです.

入社7年目からコードをコピーして貼り付けました. 

JUMP if zeroコマンドの分岐先を変更しました. パネルが0の時はOUTBOXコマンドを実行し, それ以外ではINBOXコマンドに戻るようにJUMPコマンドを入れました. OUTBOXコマンドにより0と書いたパネルを右のコンベアに運んだあとで, 次のパネルを処理するために, JUMPコマンドを追加しました.

このコードを実行すれば課題をクリアーできます. サイズ目標は達成できましたが, スピード目標は達成できていません. スピード目標を達成するためには, 少し工夫が必要です. スピード目標を達成する方法については, 記事を改めて解説します.

目次

2021/10/05

ヒューマン・リソース・マシーン 入社8年目−当社比300%

 目次

1)課題

左側のコンベアの数値を3倍にして右側に運んでください。
TIPS:

課題自体はそれほど難しくありません。効率的なやり方が無いか、考えてみましょう。 

2)解説

始めに, ADDコマンドの効果を確認してみます. 

左のコンベアからパネルを取り, COPYTOコマンドでカーペットの0番に取ったパネルを置きます. そのまま, 持っているパネルとカーペットの0番のパネルを足しました. 左のコンベアから1と書いたパネルを取りましたので, 2と書いたパネルを持っています. つまり, このプログラムは左のコンベアから取ったパネルを2倍にしています. もう1回, ADDコマンドを使えば3倍になるはずです.

ADDコマンドをもう一つ増やしてみました. 予想通り3倍になりました. 残りは, 右のコンベアに運ぶだけです.

OUTBOXコマンドを使って右のコンベアに運び, JUMPコマンドで先頭に戻ります. このプログラムを実行すれば, 課題をクリアーできます.

サイズ目標, スピード目標共に達成できました. 問題文に「効率的なやり方が無いか、・・・・」と書いてあるのでドキドキしましたが, あっけなく達成できました. 

目次

ヒューマン・リソース・マシーン 入社41年目−並べ替えよ

目次 1)課題 0を終端とした文字列がいくつか流れてきます。各文字列に対してソート(並べ替え)を行い、小さい順(昇順)に右側へ運んでください。 2)状況の確認 この問題では, 予めコードが入っています. このコードを実行して, 何をするコードなのか確かめます.  左のコンベアから...