2021/11/18

ヒューマン・リソース・マシーン 入社25年目−ゼロまで足して

目次

1)課題

左の各数値に対して、0までのカウントダウンを行い、自身を含めたすべての数値を加算した結果を出力せよ。

例えば左の数値が3である場合、右に運ぶ数値は6(=3+2+1)になります。

2)考え方

ここまでの課題をクリアーすれば, 次のような考えが浮かんでくると思います.

  1. 左のコンベアから取ったパネルを1つずつ減らし, その都度, 答えを書いてあるカーペットに足し込んでいけばよい.
  2. 左のコンベアから取ったパネルと答えのパネルをカーペットに保存する場所を用意しておく.
  3. 当然, 答えのパネルは0に初期化しておく.

これぐらい思いつけば, コマンドを並べて試行錯誤することで課題をクリアーできるでしょう. ここでは, もう少し落ち着いて考えていきます.

ここで, 総和を求める関数Sを考えます. 例を挙げます. 

S(3) = 3 + 2 + 1
S(5) = 5 + 4 + 3 + 2 + 1

「関数S」などと書いてあると苦い経験を思い出されるかもしれませんが, 1からSに続く数字までの和を計算するすることを表す, 程度に考えてください.

さて, S(3)を例にしてもう少し考えます. S(3)は3+2+1ですが, 2+1はS(2)に相当します. ですから, S(3)は次のようにも書けます.

S(3) = 3 + S(2)

同じようにして, S(2)=2+1ですが, S(2)=2+S(1)と書けます. また, S(1)=1です. これらをまとめると次のようになります.

S(3) = 3 + S(2)
S(3) = 3 + 2 + S(1)
S(3) = 3 + 2 + 1

式を変形する途中で, できる足し算は片付けてしまいます.

S(3) = 3 + S(2)
S(3) = 5 + S(1)
S(3) = 6

ヒューマン・リソース・マシーンのプログラムにするため, もう少し式に手を加えます. 

S(3) = 0 + S(3)
S(3) = 3 + S(2)
S(3) = 5 + S(1)
S(3) = 6 + S(0)

右辺の1つ目の項をカーペットの「こたえ」に, 2つ目の項をカーペットの「S」に割り当てれば, プログラムをつくれます. 

3)プログラムを作る

プログラムを作っていきます.

計算するための準備をします. 所謂, 初期化です. 「こたえ」に0を配置し, 「S」に左のコンベアから取り出したパネルを配置します.

左のコンベアから取り出し, 「S」に配置したパネルを「こたえ」に足し込みつつ, 「S」を1つずつ減らしています. 左のコンベアから取り出したパネルが3でしたので, 「S」が0になった時に「こたえ」が6になっており, 期待通りの結果が得られました. 「S」が0になった時, 「こたえ」を右のコンベアに運べば上司の要求に応えられます.

9行目にJUMP if zeroコマンドを追加して, 「S」が0になった時に「こたえ」を右のコンベアに運ぶようにしました. うまく計算できているようですが, 図では「S」が-1となっています. 0ではありませんので, 無限ループに入ってしまいます.

9行目をJUMP if zeroコマンドからJUMP if negativeコマンドに変更し, 無限ループを回避します. また, この変更により, 「こたえ」に0を加えることになりますが, 結果に変わりはありませんのでこのままとします. 

課題をクリアーできました. スピード目標を達成するためには, 左のコンベアから取り出したパネルが0の時, そのまま右のコンベアに運ぶ, といった工夫が必要です.

目次

2021/11/16

ヒューマン・リソース・マシーン 入社24年目−あまりはいくつ?

1)課題

左側の数値2つ(A, B)ごとに割り算(A÷B)を行い、その剰余(あまり)を右側へ運んで下さい。実際に割り算をする必要はありません。割り算の意味を改めて考えてみましょう。

この課題ではマイナス値は出ません。また、2つ目の数字に0が来る事はありません。

2)解説

入社20年目で掛け算をしました. A×Bを計算するために, 0から始めて, AをB回加えました. この課題ではA÷Bを行い, 余りを求めます. 考え方としては, 掛け算と逆にAからBを引き続ければ答えに近づけそうです. まず, 例として8÷3を考えてみます. 

「A」に8, 「B」に3を配置し, 「A」から「B」を引いた結果を「A」に配置していきます.

  A  B
  8 3
  5 3
  2 3
 ―1 3

4行目で「A」が負の数となりました. 8÷3の余りは2ですから, 4行目の一つ上にある3行目の「A」の値2が求める答えです. プログラムでは, 「Aがマイナスになる一つ手前」とは言えません. 代わりに, 「AがマイナスになったらBを加え, その結果が求める余り」とします. 

問題文にあるように, 負の数や「B」が0となることはありませんので, これ以上, 考える必要は無さそうです. この考えに従いプログラムを作ります.

1行目から4行目で, 左のコンベアから取ったパネルをカーペットに配置しています. 5行目と6行目で「A-B」を計算し, 結果がマイナスになったか判定しています. マイナスの場合, 10行目にジャンプし, 「B」の値を加えて右のコンベアに運びます. マイナスでない場合, 8行目で引き算した結果を「A」にコピーして, 6行目に戻ります. このプログラムを実行すると課題をクリアーできます.

サイズ目標, スピード目標共に達成できました. プログラムを最適化すると, これらの目標を下回ることができます.

目次

2021/11/13

ヒューマン・リソース・マシーン 入社23年目−一番小さいのは?

目次

1)課題

複数の「0区切り文字列」が置かれています。

各文字列の内から一番小さい数字を右側に運んで下さい。ただし、各文字列は少なくとも1つの数値を含むものとする。

2)大小の比較

この課題を解くためには, 2枚のパネルの大小を比較する方法が必要です. SUBコマンドとJUMP if negativeコマンドを組み合わせれば, パネルの大小を比較できます.

SUBコマンドを使うと, 持っているパネルからカーペットのパネルを引いた結果が得られます. 引いた結果がマイナス値であれば, 持っていたパネルがカーペットのパネルより小さいと言えます. 

3)一番小さいのは?

上司の要求は, 「一番小さい数字」です. 一番小さい数字を求めるために, 「チャンピオン」と「チャレンジャー」を用意します. 「チャレンジャー」を「チャンピオン」に挑ませ, 「チャレンジャー」が勝てば次の「チャンピオン」になり, 最後に「チャンピオン」であった者が真の「チャンピオン」です. この考え方を整理します.

  1. 「チャンピオン」と書いたカーペットには, 左のコンベアの先頭のパネルを置きます.「チャンピオン」と書いてありますが, あくまでも暫定王者です.
  2. 左のコンベアからパネルを取り出し, 「チャレンジャー」と書いたカーペットに置きます. 
  3. 「チャンピオン」と「チャレンジャー」のどちらが小さいかを比較します. 
  4. 「チャンピオン」の方が小さければ, そのまま左のコンベアから次の「チャレンジャー」を取り出し,比較します.
  5. 「チャレンジャー」の方が小さければ, 「チャレンジャー」が新しい「チャンピオン」になります.
  6. 0と書いたパネルを取り出せば, そこで終了です. 「チャンピオン」を右のコンベアに運びます.

少しずつ作っていきます. まずは, 大小を比較するところまでコードを書いてみました. 図のコードは, 「チャレンジャー」-「チャンピオン」を計算します. 

SUBコマンドに続けて, JUMP if negativeコマンドを入れました. SUBコマンドの結果がマイナス値であれば, 「チャンピオン」を交代させます. マイナス値でなければ, JUMPコマンドを使って次の「チャレンジャー」を呼び出します. 

図は, 左のコンベアから0と書いたパネルを取り出したところです. 0は「区切り文字」ですから「チャレンジャー」ではありません. 

4行目のJUMP if zeroコマンドにより, 0の場合は12行目にジャンプさせ, 「チャンピオン」を右のコンベアに運びます. 14行目のJUMPコマンドの先が画面に入っていませんが, 先頭に戻っています. 

サイズ目標とスピード目標まで, もう少しのようです. これらの目標を達成するためには, プログラムの読みやすさを犠牲にしなくてはなりません. 記事を改めて解説します.

目次

2021/11/12

ヒューマン・リソース・マシーン 入社22年目−フィボナッチ数列

1)課題

左側の数値に対し、それ自身を超える直前までのフィボナッチ数列を右側に運んで下さい。

例えば、入力が10である場合、出力は1 1 2 3 5 8となります。

フィボナッチ数列に関する詳しい話は、そこで見ている上司にきいてみましょう。

2)アルゴリズム

問題文と上司に教えてもらったことから, フィボナッチ数は次のように計算できます.

1+1=2
  1+2=3
    2+3=5
      3+5=8
        5+8=13


字下げを取り除いて表の形式にし, 各列にラベルを付けます.

A B C
1+1=2
1+2=3
2+3=5
3+5=8
5+8=13

この結果から, カーペットに置いたパネルの動かし方が分かります.

次に, 上司に解答例を示してもらいます.

解答例では, 始めに「1, 1, 」と出力しています. これも考慮に入れて計算手順を見直します. 

A B C
0+1=1
1+1=2
1+2=3
2+3=5
3+5=8
5+8=13

0と1を加えることから始めると, 「1」を出力する見通しが立ちました. 

更にカーペットの初期状態も含めて考えます. 「+」や「=」の記号を取り除き, カーペットの数値の変化に注目できるようにします.

A B C
0 0 1
0 1 1
1 1 2
1 2 3
2 3 5
3 5 8

1行目から2行目, 2行目から3行目へと移る時, 次の操作をします.

  1. 「C」を右のコンベアに運ぶ.
  2. 「B」から「A」にコピーする.
  3. 「C」から「B」にコピーする.
  4. 「A」と「B」を加えた結果を「C」にコピーする.

Cの値が左のコンベアから取り出したパネルの値を超えたところで終了です. 

3)実装

上で考えたアルゴリズムを使ってプログラムを作ります.

始めに, カーペットを初期化します. カーペットに名前を付け, パネルを配置します. 

プログラムの本体に取り掛かります. プログラムの流れは次のようになります.

  1. 「上限」と「C」を比較します.
  2. 「C」の方が大きければ先頭に戻ります.
  3. 「上限」の方が大きければ, 「C」を出力します. 続けて「B」を「A」に, 「C」を「B」にコピーし, コピー後の「A」と「B」を加えた結果を「C」にコピーします. 
  4. 先頭に戻ります.

この流れに沿って, プログラムを作ります.

10行目のJUMP if negativeコマンドは, 「上限」から「C」を引いた値が負であれば先頭に戻っています. 11行目以降で, 「C」を右のコンベアに運び, 次のフィボナッチ数を求めるための処理を記述しています. これを実行すると課題をクリアーできます.

サイズ目標を達成できていました. スピード目標を達成するためにはまだまだ工夫が必要です.

2021/11/06

ヒューマン・リソース・マシーン 入社21年目−ゼロが区切り

目次

1)課題

左側にいくつかの「0で終わる数値グループ」が置いてあります。

各グループ内の数値の合計値を算出し、右側に運んで下さい。

2)解説

左のコンベアからパネルを取り出し, 0と書いたパネルを取るまでパネルの値を足し込んでいけば, 上司の要求に応えられます. 手順を考えてみます.

  1. 入社20 年目の「掛け算のしかた」と同じように, パネルの値を足し込むためのカーペットが必要です. カーペットのラベルに「こたえ」と書いておきます.
  2. 「こたえ」は, 0から始める必要があります. カーペットの5番に0があるので, これをコピーします.
  3. 左のコンベアからパネルとカーペットの「こたえ」に置いてあるパネルを足します. 足した結果を「こたえ」にコピーします.

ここまで考えた内容でプログラムを作ってみました. これを実行すると, 左のコンベアからパネルを取り出し, 「こたえ」に足し続ける様子を観察できます. 

このプログラムでは, 左のコンベアのパネルがなくなるまで繰り返し, 右のコンベアにパネルを運びませんので, 上司の要求に応えられていません. 左のコンベアから取ったパネルが0の場合の対応を考えます. 左のコンベアから取ったパネルが0であれば, 問題文にある「数値グループ」が終わったということです. カーペットの「こたえ」には, 「数値グループ」のパネルを足した結果となっています. これを右のコンベアに運べば, 上司の要求に応えられます.

INBOXコマンドを使って左のコンベアからパネルを取った直後に, 0であるか判定します. 0であれば, カーペットの「こたえ」においてあるパネルを取り, 右のコンベアに運びます. 運び終われば, 最初に戻って次の「数値グループ」の合計を求めます. 

プログラムを実行するとクリアーできます. スピード目標については, 記事を改めて解説します.

目次

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+コマンドを使い分けます. このコードを実行すると課題をクリアーできます.

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

目次

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

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