2021/11/04

ヒューマン・リソース・マシーン 入社20年目−掛け算のしかた

 


1)課題

左側の数値2つごとに、掛け算を行った結果を右側へ運んでください。この課題では0以上の数値だけが運ばれてきます。

「ラベル」が使えるようになりました。うまく活用し、各場所の用途を忘れない様にメモしておきましょう。

2)掛け算のしかた

この課題では, 2枚のパネルの掛け算をします. パネルには1桁の数字しか書いていないようなので, 九九を習っていれば暗算で答えてしまえます.しかし, ヒューマン・リソース・マシーンの世界で使えるのは足し算と引き算だけなので, これらを使って掛け算をする方法を考えます.

ここで, 例として5×4を考えてみます.足し算を使って5×4を表現すると次のようになります.

5×4=5+5+5+5

つまり, 5を4回足し合わせるということです.

「5を4回足す」に相当するコマンドがありませんので, この計算をもう少し分解します. 5に掛けてある4を1つ減らし, 代わりに5を加えるようにします. 次のように式を変形できます.

5×4=5×3+5
5×4=5×2+5+5
5×4=5×1+5+5+5
5×4=5×0+5+5+5+5
5×4=5+5+5+5

「5+5+5+5」を計算できれば掛け算の答えが得られるのですが, ヒューマン・リソース・マシーンで「5+5+5+5」を扱う方法が見つからないので, 別の方法を考えます. 「5+5+5+5」と足し算を並べる代わりに, その都度, 5を足しこめば良さそうです.

5×4=5×3+5
5×4=5×2+10
5×4=5×1+15
5×4=5×0+20
5×4=20

このようにすれば,ヒューマン・リソース・マシーンで使えるコマンドだけで「5×4」を計算できそうです. しかし, プログラムにするためには,上の式の1行目をもう少し丁寧に書く必要があります. 

5×4=5×4+0
5×4=5×3+5
5×4=5×2+10
5×4=5×1+15
5×4=5×0+20

等号の右側には3つの数字が現れています. それぞれの数字にラベルを付けます.

  • 5のまま変化しない数字を「A」とします.
  • 4, 3, 2, 1, 0と減っていく数字を「B」とします.
  • 0から始まって5ずつ増え, 最終的に掛け算の答えとなる数字を「こたえ」とします.

ここまで書ければ, プログラムを作る準備が整いました. 

3)プログラムをつくる

上で考えたアルゴリズムからプログラムを作っていきます. この問題から, ラベルを使えるようになりました. カーペットにラベルを付けて, 数字の意味を思い出せるようになります. 

カーペットにラベルを付けました. 

  • カーペットの0番を「A」とします.
  • カーペットの1番を「B」とします.
  • カーペットの2番を「こたえ」とします.

元々あったラベルの使い方を説明するコードを取り除きます. 左のコンベアからパネルを取り出し, 掛け算をする準備をします. 左のコンベアから取り出したパネルをそれぞれ, 「A」と「B」とラベルを付けたカーペットに置きます. また, 「こたえ」には0を置き, 初期化します.

7行目以降に, 「B」が0になるまで「A」を「こたえ」に足し込むコードを書きました. 図は, 確認のためにプログラムを実行した結果です. プログラムを開始した時, 「B」は4だったので, 「こたえ」が期待通りの20になっています. 


続けて, 「B」が0となった時, 「こたえ」を右のコンベアに運ぶコードを追加しました. JUMP if zeroコマンドを実行する前に, COPYFROMコマンドを使って「B」のパネルを持ちます. また, 16行目のJUMPコマンドですが, 図では途切れていますが先頭に戻っています. このプログラムを実行すると, 課題をクリアーできます.

コードを1行減らせばサイズ目標を達成できますが, スピード目標はかなり頑張らないと達成できそうにありません. プログラムを実行している様子を見ていると, 「A」が0の時にも「B」回, 「こたえ」に0を足し込んでいます. 「A」が0なら掛け算の結果も0ですから, もっと工夫できそうです.

2021/11/01

ヒューマン・リソース・マシーン 入社19年目−カウントダウン

目次

1)課題

左側の各数値を0までカウントダウン、もしくはカウントアップした結果を右側に運んでください。

[bump+][bump-]コマンドが使えるようになりました。カーペット上の指定の場所に置いてある数字を+1もしくは-1して、その数値をコピーして手元に保持します。

2)BUMPコマンドの使い方

まず, BUMPコマンドの使い方を確認します.

BUMPコマンドの動作を調べるために, 簡単なコードを作成しました. 左のコンベアからパネルを取り, カーペットの0番に配置し, そのまま右のコンベアに運びます. パネルを持たずにBUMPコマンドを実行して, 動作を確認します. 

ステップ実行により, OUTBOXコマンドまで実行しました. これからBUMP+コマンドを実行します.

BUMP+コマンドを1回, 実行しました. カーペット0番のパネルが2から3に変わり, カーペットのパネルのコピーを持っています.

2つ目のBUMP+コマンドを実行しました. パネルの値が4になっています.

BUMP-コマンドを2回実行しました. パネルの値が2になっています.

BUMP+コマンドは, カーペットに置いてあるパネルを1増やし, 値を増やしたパネルのコピーを持ちます. BUMP-コマンドは, カーペットのパネルを1減らします. 

3)課題を解く

BUMPコマンドの使い方を理解できましたが, 問題文だけでは上司が何を求めているのか分かりませんでした. 上司に解答例を尋ねてみました.

解答例から, パネルが3なら, 3, 2, 1, 0を右のコンベアに運び, パネルが-2なら, ―2, ―1, 0を右のコンベアに運べば良さそうです. つまり, BUMPコマンドを使ってパネルの値を1ずつ0に近づけ, その都度, 右のコンベアに運べば, 上司の要求に応えられます.

まず, パネルの値がプラスの場合に限定して, コードを書くために必要な事柄を挙げていきます. 

  1. パネルの値が0でなければ, BUMP-コマンドを使ってパネルの値を1つ減らします. 
  2. パネルの値が0であれば, 右のコンベアに運びます. 処理しているパネルについては, これで終了です.
  3. パネルの値が0でなければ, 最初に戻ります. 
  4. BUMP-コマンドを使ってパネルの値を1つ減らすごとに, 右のコンベアに運ばなくてはなりません.
  5. OUTBOXコマンドを使うと持っているパネルが無くなりますので, COPYTOコマンドを使って持っているパネルをカーペットに退避しておきます. 
  6. 解答例を見ると, 左のコンベアから取った時のパネルと0を右のコンベアに運ばなくてはなりません. このような境界値を忘れがちなので注意が必要です.

考えた結果をコードに変換しました.

そのまま実行しました. 左のコンベアの1枚目のパネルが2でしたので, 2, 1, 0を右のコンベアに運んでいますので, 期待した結果が得られました. 2枚目のパネル,―2については何も対策をしていませんので, 誤ったパネルを右のコンベアに運んでしまい, 上司に怒られてしまいました.

左のコンベアから取ったパネルがマイナス値の場合とプラス値の場合とで処理を分けていきます. コードを眺めると, JUMP if zeroコマンドの後でマイナス値かプラス値かで処理を分けるのが良さそうです. JUMP if negativeコマンドを使ってBUMP-コマンドとBUMP+コマンドを使い分けます. このコードを実行すると課題をクリアーできます.

サイズ目標を達成できました. スピード目標を達成するには, かなり工夫が必要です.

目次

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コマンドを追加してプログラムを完成させます. 

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

目次

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

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