見出し画像

【趣味プログラミング】Brainfuckはじめました #2 ABC329-A

こんにちは。すっかりBrainfuckのとりこになっているほっぴーです。

今回もBrainfuckでAtCoderの問題を解いていこうと思います。

BrainfuckについてやAtCoderについてはこちらの記事を参照ください。


問題

今回解いていく問題はこちら!

英大文字からなる文字列 S が与えられます。S の各文字を空白で区切り、その順で 11 文字ずつ出力してください。

入力:abc
出力:a b c

解いていく

方針1 素朴な実装(55byte)

0番地に空白をセットしておいて、
「1番地に値を入力して表示し、0番地の空白を表示」
を改行コードが入力されるまで繰り返す。

という方針でとりあえず解けそうです。
コードはこんな感じ。

//1番地に空白をセット
++++++++[->++++<]
//0番地に入力して、改行じゃなくなるまで繰り返す
,----------[++++++++++.>.<,----------]

一行ver

++++++++[->++++<],----------[++++++++++.>.<,----------]


方針2 入力がNULLだったら-1がセットされることを利用(28byte)

これは今回初めて知った仕様で、例えば入力「abc」として、「,,,,」というコードを実行すると、0番地には-1がセットされます。

コンパイラによって挙動が異なるところですが、AtCoderの環境では-1が入るようです。

この知識を使うと、終わりの判定がかなり短くなります。

//1番地に空白をセット
++++++++[->++++<]
//0番地に入力して、NULLじゃなくなるまで繰り返す
,+[-.>.<,+]

一行ver

++++++++[->++++<],+[-.>.<,+]


方針3 空白を作る部分でオーバーフローを使用(23byte)

前回使ったテクで、2^Nの繰り返しはオーバーフローをうまく使うと短くなるケースがあります。このテク考えた人本当に頭良すぎる。

さっそく今回も使っていきましょう!
具体的には、「空白」の文字コードは32なので、256 / 32 = 8より、0から8ずつ引いていけばいいことがわかります。

//1番地に空白をセット
-------->+<]
//0番地に入力して、NULLじゃなくなるまで繰り返す
,+[-.>.<,+]

一行ver

-------->+<],+[-.>.<,+]

かなり上手くいっていると思いますが、この問題のshortestは20byte。
あと3byteをどうしても縮められそうになかったので、shortestコードを見てみることにしました。


方針4(?) 改行区切りでも良いことを利用する(20byte)shortest

20byteのコードを見てみたところ、この問題は空白区切りではなく、改行区切りで表示してもACするようです(なんじゃそりゃ)

試しにc++で改行区切りするコードで出してみましたが、無事(?)ACしました。

しゃくぜんとはしませんが、コードにするとこんな感じ。

// 入力して、NULLじゃなければ表示して改行を繰り返す
,+[-.>++++++++++.,+]



まとめ

shortestまではいけませんでしたが、空白区切りで表示しているコードの中では一番短かったので、及第点といったところでしょうか。

空白じゃなくて改行でも良かったり、答えの前後に空白や改行が挿入されていてもいいという柔軟さは、短いコードを書く上で利用できることがあるようです。

それにしても、やはりBrainfuckでのAtCoderは他では接種できない楽しさを提供してくれます。

この記事が、みなさんの良きBrainfuckライフの手助けになっていれば幸いです。

この記事が気に入ったらサポートをしてみませんか?