まずは基本中の基本の「s,r,l」についていろいろと。
「s」は多分"straight"の略で「一歩前進」です。
「r」は"right"の略で「90°右に回る」です。
「l」は"left"の略で「90°左に回る」です。
では、Editを開いて下さい。
Editは自由なmap・初期位置を自分で設定できるので、コードがどのように動くのかを試すのに便利です。
Editでいろいろなコードを試してみるのも上達への近道だったりします。
そこに
sslsls
と書いて実行してみて下さい。「7」の字を描いて進んだと思います。
このコードを日本語にするならば、
「前に2つ進んで左を向き、前に1つ進んでさらに左を向き、前に1つ進む」
となりますね。
では次に
sslslsls
を実行してみて下さい。「9」の字を描いたと思います。
しかし通ったマスは、「7」の字のコードの通ったマスと同じですね。
凸(自キャラ)の通った軌道にtarget(白丸)を置いてそれぞれのコードを実行してみるとはっきりと分かります。
(ただし「Cleared!」になると実行が止まるような仕様になっているので、「9」は最後まで描けません。)
また
slsrsrs
と書いても、通るマスは同じはずです。
つまり、「同じ形でもそれを辿る方法は1つではない」ということです。
その複数あるパス(辿り方)の中から一番短いコードで書けそうなものを選ぶのです。
場合によっては、同じ場所を何回もぐるぐる回るようなパスが良い場合もあったりします。
あと、気をつけておくと良い事は、
「一歩進む」は「s」と書くしかありませんが、
方向転換、すなわち「右に回る」などは何通りもの書き方があるということです。
例えば「r」は「rlr」や「lll」「rrrrr」などと書けたり、
「後ろを向く」=「180°回る」は「rr」とも「ll」とも書けたりします。
特に「後ろを向く」は正しい方を選ぶとうまく縮められることがよくあるので覚えておいて下さい。
+練習問題+
今回は、一番基本的な「置換」による短縮です。
では早速このコードを見て下さい。
sssssrssssslsssss
稲妻のような形を描いたはずです。
このコードは17B(Byte)ですね。
しかし、よく見ると「sssss」が3回出てきています。
これを置換してみましょう。
x:sssss
xrxlx
このように「x:sssss」と書いておくことによって、「x」を「sssss」として使えるようになります。
「:」(コロン)は1Bとして数えないので、全部で11Bですね。
6Bも短縮できました。
次はこのコードを「置換」してみましょう。
sssrsss
7Bですね。
「sss」が2回出てきているので、先ほどと同じように置換してみましょう。
x:sss
xrx
7Bですね。
置換前のコードも7Bだったので、短縮できていませんね。
なぜ短縮できなかったのかを考えてみましょう。
1つ目の例と2つ目の例の違いを挙げてみます。
- 1つ目の方が置換される部分のByte数が多い。
- 1つ目の方が置換される部分の数が多い
つまり、置換される部分の長さと個数が多い方が、置換の効果が大きくなるのです。
というわけで、それらと 短縮できるByte数の関係を表にしてみました。
横は長さ、縦は個数です。
マイナスの数字は、逆に長くなってしまうことを表しています。
\ |
2B |
3B |
4B |
5B |
2個 |
-1B |
0B |
1B |
2B |
3個 |
0B |
2B |
4B |
6B |
4個 |
1B |
4B |
7B |
10B |
5個 |
2B |
6B |
10B |
14B |
ガッツリ覚える必要はありませんが、なんとなく感覚を掴んでおくとと良いと思います。
特に、2Bなら4個、3Bなら3個、4Bなら2個以上なら短縮が出来るという感覚は身につけておきましょう。
最後に下の2つのコードを置換によって短縮してみましょう。
llssssrssss
11Bです。
「ssss」という4Bの部分が2回出てきているので1B縮まりますね。
x:ssss
llxrx
10Bです。
しかし、実はもう1B縮みます。
前回の講座の内容を思い出してみましょう。
「ll」は「rr」とも書けるんでしたね。
それを踏まえて書き直すと、
x:ssss
rrxrx
となり、これは
x:rssss
rxx
と短めることができ、9Bになりました。
では最後のコードです。
sssrssslsssrsssrssslsss
23Bと長めです。
「sss」が6つも出てきているので明らかに短縮できますね。
x:sss
xrxlxrxrxlx
15Bと一気に8Bも縮みました。
しかしこれで油断してはいけません。まだ縮みます。
よく見てみると「xrxlx」が2回出てきています。
5Bが2回出てきているので短縮できますね。
x:sss
y:xrxlx
yry
13Bです。
最初に比べ10Bも縮みました。
「置換」による短縮は一番の基本なので是非習得しましょう。
+練習問題+
best解は「置換」だけでは難しいのですが、Clearを目指して下さい^^
Herbertをやっていると、ほとんどの問題で、
「同じものを繰り返す」
という状況が出てきます。
これを実現する方法はいくつかありますが、
今回はそのうちのひとつである「関数」について書きたいと思います。
では、このコードを短縮してみましょう。
srslsrslsrslslsrslsrslsr
24Bです。
見にくいですね^^
構造を説明すると、
srslとslsrが3回ずつ繰り返されてる形です。
まず、前回の講座の「置換」を使ってみましょう。
x:srsl
y:slsr
xxxyyy
16Bです。
4文字が3回出てくるのを2個置換したので8B縮みました。
次に「関数」を使って短縮してみましょう。
f(X):XXX
f(srsl)f(slsr)
15Bになりました。
このように、
「関数」を使えば 同じものが繰り返される部分を短縮することが出来ます。
H言語の「関数」は数学の「関数」と似ていて、
例えば数学で
f(x) = x^2 + x - 6
※「x^2」は「xの二乗」という意味です。
とした時に
f(7) = 7^2 + 7 - 6 (= 50)
となるのと同じで、H言語で
f(X):XXX
としたときには
f(s) = sss
f(rs) = rsrsrs
f(srsl) = srslsrslsrsl
f(slsr) = slsrslsrslsr
となります。
「引数」(この例の場合"X")は大文字でなければいけない点に注意しましょう。
「f(X):XXX」は同じものを3回繰り返す「関数」なので、「3倍関数」と呼んでいます。
では次にこのコードを縮めてみましょう。
lsrssrssrssrslsssslssrssssrssssrssssrss
39Bです。
今度は4倍関数を定義すれば良いですね。
f(X):XXXX
lf(srs)lf(s)lf(ssrss)
21Bです。かなり縮みました。
しかし、実はまだ2B縮みます。
f(X):lXXXX
f(srs)f(s)f(ssrss)
19Bです。
このように、":"の後ろには"X"以外の文字も入れて良いので、
定義の仕方によってはコードを短くできることがよくあります。
でも少しややこしいので、慣れるまでは「○倍関数」だけでも使えると良いでしょう。
+練習問題+
前回やった「関数」ですが、入れ子にすることでさらに便利になります。
ssssssssrssssssssrssssssssrssssssssr
36Bです。
一辺8歩の正方形を描きます。
まずは前回と同じように短縮してみましょう。
f(X):XXXX
f(ssssssssr)
16Bです。
よく見ると「ssssssss」は「ss」を4回繰り返したものですね。
これを「f(ss)」に書き直してみると、こうなります。
f(X):XXXX
f(f(ss)r)
11Bです。
このように関数の中に関数を書くことも出来ます。
とりあえずもう1つ例を出してみます。
ssssrssssrssssrssssrrssssrssssrssssrssssrrssssrssssrssssrssssrrssssrssssrssssrssssrr
「田」の字を描きます。
84Bと、めちゃくちゃムダにあふれていますね。
f(X):XXXX
f(f(f(s)r)r)
12Bになりました。ちょっとややこしくなってきましたね。
分からなくなったら、メモ帳とかを使って展開してみると良いと思います。
ちなみに、このコードはあと1B縮みます。
f(X):XXXXr
f(f(f(s)))
関数は便利なので是非マスターしちゃって下さい!
+練習問題+