2022/01/15

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

目次

1)課題

0を終端とした文字列がいくつか流れてきます。各文字列に対してソート(並べ替え)を行い、小さい順(昇順)に右側へ運んでください。

2)状況の確認

この問題では, 予めコードが入っています. このコードを実行して, 何をするコードなのか確かめます. 

左のコンベアからパネルを取り出し, カーペットに配置しています. 終端を表す0を配置したところで終了しています. また, 使用したカーペットの最大値がカーペットの20番に記録してあります. 

3)考え方

カーペットに配置したパネルを小さい順に並べ替える方法を考えます. ここでは, 終端を表す0に近いカーペットから順に大きい数字のパネルを置くように考えていきます. アドレスの判定を簡単にするためです. 

ここで, 入社23年目の「一番小さいのは?」を振り返ります. この課題では, 一番小さいパネルを選びました. この課題を応用します. 

上の図では, カーペットの3番が0となっています. カーペットの2番に, 最大の数字を配置する方法を考えます. 

  1. カーペットの2番をチャンピオンとします.
  2. カーペットの1番をチャンピオンに挑ませます. 1番の方が大きければ, チャンピオンを交代します.
  3. 同じようにしてカーペットの0番をチャンピオンに挑ませ, 大きければ交代します.

最大の数字が決まれば, カーペットの2番をチャンピオンとして同様に処理します. この操作を繰り返すことで, パネルを並び替えられます.

4)カーペットの名前

カーペットには, 並べ替えるパネル以外にも, 管理用のカーペットが必要です. 

次のように名前を付けました.

  1. アドレス:処理中のカーペットを表します. チャンピオンを決定する時は, チャレンジャーの位置を表します.
  2. チャンピオン:チャンピオンのいるカーペットの位置を表します.
  3. SWAP:チャレンジャーが勝った場合, チャンピオンとチャレンジャーを入れ替えるために使います. 
  4. ZERO:初期化用の0を置いておきます.

5)全体的な枠組み

カーペットの位置を示す「アドレス」と「チャンピオン」を書き換える処理を中心にコードを書いていきます.

8行目の時点で, 「アドレス」には終端を表す「0」を配置したカーペットの番号が入っています. 8行目から10行目で「チャンピオン」に反映します. 

11行目で, 「チャンピオン」が0になっているか判定しています. 「チャンピオン」が0なら, 並び替えが終わっているので, 運び出すだけです. 

12行目から「チャンピオン」の値を使って「アドレス」の値を「チャンピオン」の値-1としています. ここでの「アドレス」は「チャレンジャー」の意味です. 「アドレス(チャレンジャー)」がマイナスなら, 「チャンピオン」の防衛が決まったので, 10行目に戻り, 次の「チャンピオン」を決めます. 

15行目で「アドレス(チャレンジャー)」を取り出し, 「チャンピオン」に挑ませます. 

結果がマイナス, つまりチャンピオンの方が大きければ13行目に戻り, 次のチャレンジャーに挑ませます. 

結果がプラス, つまりチャレンジャーの方が大きければ, チャレンジャーとチャンピオンを入れ替えます. ここでは, 「SWAP」と書いたラベルを配置してあるだけで, コードの中身はこれから書きます.

「アドレス(チャレンジャー)」が「チャンピオン」より大きい場合, 「SWAP」を使って「アドレス(チャレンジャー)」を「チャンピオン」を入れ替えます. 入れ替え後に「アドレス(チャレンジャー)」を1減らし, 次のチャレンジャーに挑ませます.

11行目で「チャンピオン」がマイナスかを判定しています. マイナスの場合, すべてのパネルの順序が決まり, ソートが完了しました. パネルを小さい方から順に右のコンベアに運びます. 最初に左のコンベアから取り出したパネルをカーペットに配置しましたが, その逆のことをしています. 

クリアーできました. サイズ目標は3行も少なく達成できました. スピード目標を達成するには,もう少し工夫が必要です.

目次

2022/01/13

ヒューマン・リソース・マシーン 入社40年目−素因数に分解せよ

目次


1)課題

右側のパネルの数値に対し、素因数分解を行い、答えを右側に運んで下さい。

答えは昇順、すなわち小さい順に運んで下さい。

2)考え方

カーペットが25枚とかなり広いので, 素数表を作る方法も考えましたが, 地道に割り算していくことにします. 

基本的な考え方として, 割るべき素数を2から始め, 割り切れれば割り算に使った素数を右のコンベアに運び, 割り算の結果の商を次の割られる数にします. 割り切れない場合は, 素数を1増やして割り切れるか試します. 

素数に入る数字は4など合成数になる時がありますが, 4で割り切れるなら2でも割り切れているので, 結果には影響しません. 効率は悪いですけれども. 

3)初期化

カーペットに名前を付けます.

  1. ZERO:カーペットに配置してある0をコードでも識別しやすいように名前を付けます.
  2. 入力:左のコンベアから取り出したパネルを保存しておきます. 素数で割り切れなかった時, 割り算をやり直すために使います.
  3. 余り:引き算を繰り返して割り算をしますが, 引いた残りの値を記録します. 余りが0になれば, 割り切れたと判断できます.
  4. 商:割り算の結果を記録します.
  5. 素数:素因数分解するための素数の候補を記録します.

カーペットに名前を付け, 値を配置します. 「素数」には2を設定します.

4)割り算

「素数」で「余り」を割っていきます.

「余り」から「素数」を引き, 結果が0になれば「素数」で割り切れたたことになりますので, 「われた」に進みます. 

「余り」から「素数」を引いた結果がマイナスになった場合, 「素数」では割り切れなかったので, 次の素数で割ることを考えます.

5)割り切れなかった

割り切れなかった場合, 「素数」を1増やして割り算をやり直します.

「入力」に退避していた割られる数を「余」にコピーし, 8行目に戻ります. 8行目に戻る理由は, 「商」を0で初期化するためです.

6)割り切れた

割り切れた場合, 「素数」を右のコンベアに運び, 次の割り算に備えます.

割り切れた場合, 「素数」を右のコンベアに運びます. 忘れずに「商」を1増やしておきます. 

24行目で「商」と「素数」の大小を比較しています. 

「素数」の方が大きい場合は, 素因数分解が完了したと判断できるので, 先頭に戻ります. この時, 「商」は1になっているので, 1との比較をした方が良いのでしょうが, この実装で進めます. 

「商」の方が大きければ, 5行目に戻り, 「商」の値を「余」と「入力」にコピーして, 「商」の素因数分解を試みます.

ここまでの内容を実行すると課題をクリアーできました. サイズ目標を達成できています. スピード目標はこの次に考えます.

目次

2022/01/08

ヒューマン・リソース・マシーン 入社39年目−座標をもとめよ

目次

1)課題

右側の数字は、カーペット上の番号を表しています。各入力データに対し、その座標(X, Y)を右側に運んで下さい。

例えば左側の数字が6の場合、右に運び出してほしいのは2と1になります。

2)考え方

問題文では, 数字が6の場合, 座標はX=2, Y=1と書いてあります. XとYの求め方は次のようになります.

  1. Xは数字6を4で割った余り
  2. Yは数字6を4で割った商

入社26年目で割り算をしました. その結果を使えば良さそうです.

3)実装

入社26年目で作成したプログラムをコピーし貼り付けます.

ここからコードを修正していきます. 割る数Bは, カーペット15番の4となります. また, カーペット9番の「ZERO」はカーペット14番になります.

修正しました. カーペット1番にあったBをカーペット15番に付け替えました. またカーペット9番の「ZERO」をカーペット14番に移動しています. 当然, COPYFROMコマンドなどのアドレスも変更しています. 

また, コピー元のコードでは, 左のコンベアから2枚目のパネルを取り出し, カーペットに配置していましたが, これに関するコードは取り除いています.

左のコンベアから12を取り出し, 割り算をしました. 上司に怒られていますが, 割り算はできており, 「Q」と「A」のパネルを右のコンベアに運べば課題をクリアーできます. 

カーペットのラベルを問題の位置を反映し, 「A」を「X」に, 「Q」を「Y」に付け替えました. 割り算終了後に, 「X」と「Y」のパネルを右のコンベアに運んでいます. 

課題をクリアーできました. 

目次

2022/01/03

ヒューマン・リソース・マシーン 入社38年目−数字をバラせ

目次


1)課題

左側のパネルの数字を桁ごとに分解して右側へ運んで下さい。

例えば数字が123だったら、答えは「1, 2, 3」となります。

2)考え方

一般的なプログラミング言語であれば, 10で割った商と余りを使って一の位から順に処理していきますが, ヒューマン・リソース・マシーンには割り算がありませんので工夫が必要です. 

カーペットには, 0, 10, 100と書いたパネルが置いてありますので, これらを使っていきます. アルゴリズムは次のようになります.

  1. 100で割った結果を右のコンベアに運び, 余りをカーペットに置いておく. 
  2. 余りを10で割った結果を右のコンベアに運び, 余りも右のコンベアに運ぶ.

この問題を解くときにもう一つ注意点があります. 上司に解答例を尋ねると, 3などの一桁の数は3のみを右のコンベアに運んでおり, 百の位の数が0の場合はコンベアに運びません. この条件が無ければ, もっと簡単なのですが.

3)初期化

初期化のためのコードを書きます.

カーペットの0番に「一の位」, 1番に「十の位」, 2番の「百の位」と名前を付けます. 元々, パネルを置いてあるカーペットにもパネルの値をカーペットの名前とします. 

続けて, 「百の位」と「十の位」に0を置きます. 「一の位」には左のコンベアから運んだパネルを置きます.

4)百の位

初期化が終わりましたので, 百の位を求めます.

「一の位」のパネルから「100」を引きます. 結果がマイナスでない時, 「百の位」を1増やし, 結果がマイナスになるまで繰り返します. 結果がマイナスになれば, 「百の位」には百の位の値が入っています. その値が0でなければ右のコンベアに運びます. 

5)十の位

百の位と同様に十の位を求めます.

15行目から20行目までが十の位を求めるコードです. 百の位と処理内容は同等です.

6)十の位と一の位の出力

十の位の計算が終わると, 「十の位」と「一の位」に右のコンベアに運ぶべき値が入っています. 問題は, 「百の位」が0の時, 「十の位」の値も0であれば, 「一の位」だけを右のコンベアに運びます. それ以外の時は, 「十の位」に続けて「一の位」を出力します. 

21行目から「十の位」と「一の位」を出力するためのコードです.

21行目から, 「百の位」が0であるか判定しています. 0でなければ, 26行目にジャンプして, 「十の位」と「一の位」を出力します. 

「百の位」が0の場合, 「十の位」が0であるか判定しています. 0でなければ「十の位」を出力し, そのまま「一の位」を出力します. 「十の位」が0の場合, 28行目にジャンプして, 「一の位」を出力します. 最後に, 30行目で先頭に戻ります.

課題をクリアーできました. サイズ目標を達成できました. スピード目標は, どうしたものでしょう?

目次

2021/12/24

ヒューマン・リソース・マシーン 入社37年目−次へつなげよ

1)課題

6つのデータペアが配置されています。右側の数字は次のペアの位置番号です。

左側の各数値に対し、数珠つなぎにペアをたどり、その際に通過したペアの左側の文字を右側に運んで下さい。

右側の数字がマイナスの場合、数珠つなぎは終了です。


2)考え方

カーペットのパネルの配置から, 次のような手順で処理をすればクリアーできそうです.

  1. 「アドレス」にパネルを配置する.
  2. 「アドレス」が示すパネルを右のコンベアに運ぶ. この時, パネルには文字が書いてある.
  3. 「アドレス」を1増やす.
  4. 「アドレス」が示すパネルを「アドレス」に配置する. この時, パネルには数字が書いてある.
  5. 「アドレス」の数字がマイナスなら終了

3)実装

上で考えた方針に従い, プログラムを作ります.

ほぼ, そのまま実装できました. 「アドレス」がマイナスかどうかの判定を前の方に持ってきています. 

あっさりとクリアーできてしまいました. サイズ目標, スピード目標共に達成です. 

目次

2021/12/14

ヒューマン・リソース・マシーン 入社36年目−辞書順に並べよ

1)課題

左側のコンベアに2つの単語が運ばれてきます。辞書順で並べたときに、先に来る単語を右側に運んで下さい。

2)考え方

単語を辞書順に並べるのですから, 1文字ずつ比較していきます. 異なる文字が現れれば, 並び順の小さい文字を含む単語を右のコンベアに運びます. 注意点として, 2つの単語の文字数が異なる場合, 短い方の単語を運びます. 

プログラムは大きく3つの部分から構成します.

  1. 左のコンベアからパネルを取り出し, カーペットに配置する.
  2. カーペットに配置した2つの単語を構成する文字を1文字ずつ比較し, 先に来る単語を特定する.
  3. 先に来る単語を右のコンベアに運ぶ.

プログラムを作るために, いくつか名前を決めていきます. 

  1. 左のコンベアから取り出した1つ目の単語をAとします. 
  2. 2つ目の単語をBとします. 
  3. 単語Aのアドレスを記録するカーペットをADR-Aとします.
  4. 同様に単語BのアドレスをADR-Bとします.
  5. 最後に右のコンベアに単語を運ぶためのアドレスをOUTとします.

3)実装

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

カーペットに名前を付け, 左のコンベアから運び出したパネルをカーペットに配置します. カーペットの23番に0, 24番に10と書いたパネルがあります. 単語Aを配置し始めるカーペットの番号に0を割り当て, 単語Bは10を割り当てます.

15行目から, ADR-AとADR-Bを再初期化し, 1文字ずつの比較に備えます. 

続けて, 単語Aと単語Bが終端を表す0に到達しているか調べ, 0になっている単語を運び出します. 運び出す単語のアドレスをOUTに設定しています. OUTを使って単語を運び出せますので, 運び出す処理を1つにまとめられます. 

23行目から1文字ずつ比較するコードを書いていきます. 23行目に到達した時点で単語Bの文字を持っていますので, 単語Aの文字とSUBコマンドを使って比較します. 

結果が0なら同じ文字ですので, 次の文字を比較するためにADR-AとADR-Bを1増やし, 19行目に戻ります. 

結果が0でなくマイナスの場合, 単語Aの文字の方が大きいということですから, 単語Bを運ぶためにカーペット24番の10運ぶ準備をします. 

結果がプラスの場合, 単語Aを運ぶためにカーペット23番の0をOUTに運ぶ準備をします. 

OUTを使ってカーペットに置いてあるパネルを運び出します. OUTが示すカーペットのパネルが0になるまで, 右のコンベアに運び, OUTを1増やす操作を繰り返します.

クリアーできました. サイズ目標を達成できています. スピード目標はもう少しで達成できます. 

目次

2021/12/10

ヒューマン・リソース・マシーン 入社35年目−ダブりを省け

目次

1)課題

入力側のデータを出力側に運んで下さい。ただし、重複したデータは破棄してください。

2)考え方

方針は次のようになります.

  1. 左のコンベアからパネルを取り出し, カーペットに配置していないかを調べます. 
  2. カーペットになければ, 左のコンベアから取り出したパネルをカーペットに追加し, 右のコンベアに運びます.

どのカーペットまでを使ったかを記録するため, カーペット14番にある0を使います. このカーペットに「上限」と名前を付けます. 

また, 右のコンベアから取り出したパネルを一時的にカーペットに配置するための場所も必要になります. カーペットの13番に「文字」と名前を付けます. 

更に, カーペットに配置してあるパネルの内, どこまで調べたかを記録する場所も必要です. カーペットの12番に「アドレス」と名前を付けます. 「アドレス」は「上限」から始めて, 0に向けて減らしていきます. こうすることで, 使用するコマンドを減らせます.

この問題でよく考えなくてはいけないことは, 最初の1枚をどうするか, です. カーペットに何も無い状態から始めて一般的にプログラムを作れると良いのですが, 「アドレス」の扱いが難しくなります. プログラムを簡単にするために, 1枚目のパネルは特別扱いし, カーペットの0番に配置し, 無条件で右のコンベアに運びます.

3)実装

初期化から始めます.

左のコンベアから1枚目のパネルを取り出し, カーペットの0番に配置します. そのまま右のコンベアに運びます. 続けて, 「上限」の値を「アドレス」にコピーします. 4行目以降のコードを2枚目以降のパネルで使いますので「2文字目」とラベルを付けています.

6行目でINBOXコマンドを使って左のコンベアからパネルを取り出し, 「文字」に配置します. 続けて, 「アドレス」が示す文字と比較し, 同じならそのパネルを捨ててしまうためにそのまま4行目に戻ります. 文字が異なるなら, 「アドレス」を1減らし, 次の文字との比較に備えます. 

11行目で「アドレス」がマイナスになっているか判定しています. マイナスであれば, 「文字」は初めて現れた文字ですから, 右のコンベアに運びます. この時, 「上限」を1増やして, カーペットに追加します. OUTBOXコマンドを使うと持っているパネルが無くなりますので, コマンドの順序に注意してください.

「アドレス」がマイナスでない場合, カーペットの次の文字との比較をするため, 改めて「文字」からパネルを取り出し, 8行目に戻ります. 

プログラムを実行するとクリアーできます. サイズ目標達成まであと1行です. スピード目標は, 目標値を下回って達成できていました. 1文字目を特別扱いしないコードにすれば, もっと良くなるかもしれません. 

目次

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

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