AtCoder Brainfuck Contest 参加記
概要
有志の方がAtCoderのバーチャルコントテストで brainfuck
向けの問題でバチャコンを開いてくれたのでそれに参加しました。
全部まとめて提出用としたところ、ペナを出しました。恥ずかしいです。
というわけで、問題の解説を行っていきたいと思います。
コンテストリンク
目次
- 概要
- 目次
- A. 1問目
- B. ABCxxx
- C.Diagonal String
- D.12/22
- E.お茶
- F.
- G. September 9
- H.Restricted
- I.Ringo's Favorite Numbers
- J.Welcome to AtCoder
- 総評
- あとがき
A. 1問目
問題概要
入力文字列の 1
文字目を出力するだけです。
コード
.,
解説
言語仕様を理解していれば解くことができます。
B. ABCxxx
問題概要
ABC
を出力して、そのあとにエコープログラムを
書くだけです。
コード
++++++++[->++++++++<]>+.+.+. ,----------[++++++++++.,----------]
解説
A
の文字コードは 65
なので、8*8+1
で数値を生成できます。そのあとは、インクリメントしながら出力すれば、ABC
と出力することができます。
エコープログラムは、改行コード (=10)
まで読み込んで出力すればいいです。
C.Diagonal String
問題概要
対角線上の文字を順に出力するだけです。
コード
,.,,,,,.,,,,,.
解説
1
文字目、6
文字目、11
文字目を順に出力すればいいです。(改行も文字に含まれることに注意してください。)
,
は現在の値を上書きするので、値の初期化の必要はありません。
D.12/22
問題概要
4
桁の数字の 2
の数を数える問題です。
コード
,---------- [ >+++++[-<-------->]< >>+<< [ [-] >>-<< ] ,---------- ] >++++++[->++++++++<]>.
解説
読み込みを 4
回してもいいのですが、ループで回すとコード量を削減できます。2
の数を数えるだけです。
2
以外を数えて 4
から引くのでも構いません。
E.お茶
問題概要
文字列の最後が T
かどうかを判断するだけです。
コード
,---------- [ > ,---------- ] ++++++++[-<--------->]< -- >+< [ [-]>[-]< No ++++++++++[->+++++++++++>++++++++<<]>>--.[-]<+.[-]< ] > [ [-] Yes ++++++++++[->+++++++++<]>-.++++++++++++.++++++++++++++.[-]< ]
解説
改行コードが来るまで、現在の値をどこかのメモリに格納ということもしてもいいですが、すべての値をメモリに順に入れて、最後の要素を確認する方が楽です。(入力文字列はメモリに充分乗るので。
あとは、T
かどうかの判断を行い if-else
を書けば良いです。
F.
問題概要
入力文字列が並び替えると abc
になるかどうかを判断します。
コード
,---------- [ >++++++++++[-<--------->]<+++ >+< [-[-[- ]>[- >>>+<<<]< ]>[- >>+<<]< ]>[- >+<]< ,---------- ] >> [[-]<+>]> [[-]<+>]> [[-]<+>]> <<[-<+>]<[-<+>] +< --- [ [-]>[-]< Yes ++++++++++[->+++++++++++>++++++++<<]>>--.[-]<+.[-]< ] > [ [-] No ++++++++++[->+++++++++<]>-.++++++++++++.++++++++++++++.[-]< ]
解説
入力は例によってループで処理してます。
3
つの入力が異なるかどうかの判別によって解く方法と
a,b,c
がそれぞれ存在するかを確認する方法があります。
上記コードは後者の解放になってます。
めんどくさいので解説はしません
G. September 9
問題概要
二桁の数字に 9
が含まれるかどうかを判別するだけです。
コード
, +++>++++++[-<---------->]< >+< [ >-< , +++>++++++[-<---------->]< >+< [ [-]>-< ++++++++++[->+++++++++++>++++++++<<]>>--.<+.[>]> ] ] > [ > ++++++++++[->+++++++++<]>-.++++++++++++.++++++++++++++.[>] ]
解説
今回は入力が 2
文字なので、if-else
を 2
回書けばいいです。
上記コードでは、Yes
の出力はひとつのコードで行えるように工夫をしています。
H.Restricted
問題概要
A+B
を出力するだけです。ただし、10
を超える場合はerror
を出力します。
コード
>>,<,> [--<---<--->>] <[-<+>]< [->+>>+<<<] >>> >+++++++++< [[->]<[<]>]<< //比較 [ > ++++++++++[->++++++++++<]>+.+++++++++++++..---.+++.[>]>>>> ] << [>++++++[-<++++++++>]<.>] ,.
解説
文字コードを数字に変換する際に、空白を利用することでコード長を削減しています。
比較は、[[->]<[<]>]<<
で行っています。
これの解説をすると長くなるので、そういうものだと思ってください。
比較ができたら、あとは if-else
を書くだけです。
I.Ringo's Favorite Numbers
問題概要
概要は問題を見てください。一言で説明するのは面倒ですので。
コード
>,+>>,[--<+++<--->>]> ,----------[++++++++++>,----------] <<<[>>+<<<] 100 の場合は1の位をインクリメント >>>[<]>[.>] 数値の出力 <[<]<<[<] 位置修正 >-[->..<] 0 を出力
解説
数字は改行まで読み込んで、'3' 桁あれば、 1
の位をインクリメントすればいいです。 100
の時のみなので、繰り上がりは考慮しなくていいです。
ただし、入力長に応じて、位置が変わるのでそれを修正するコードが必要になります。
J.Welcome to AtCoder
問題概要
3
つの数の和を出力しエコープログラムを書けば良いです。
256
を超えるので brainfuck
には難しいです。
コード
>>> #region Multi_ReadNum +>+>+>+>+> +>+> //桁数 >+[-< ,+[-----------[---------------------- [--------------<-[+<-]>[[-<+>]>]+<] ]]> ] <<-[+<-]+>[->]< #endregion > >>> #region Multi_ReadNum +>+>+>+>+> +>+> //桁数 >+[-< ,+[-----------[---------------------- [--------------<-[+<-]>[[-<+>]>]+<] ]]> ] <<-[+<-]+>[->]< #endregion #region Multi_AddToPrev 0 //start ___{ a }___{ b*}___ //resilt ___{res}___{ b*}___ [ [<]<[<]<<[->>+<<]>>[>]>[>]>+<<- [ [<]<[<]>+[>]>[>] >+<<- ] < ] <[<]<<[<]> [[-<+>]>]>>[[-<<<+>>>]>]<<<< [ [->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[ [->+<]>----------< <[+>]>[<] ]]]]]]]]]]]< ] >>[>]>>>>>[[-<<+>>]>]<<< #endregion [[-]<]> #region Multi_ReadNum +>+>+>+>+> +>+> //桁数 >+[-< ,+[-----------[---------------------- [--------------<-[+<-]>[[-<+>]>]+<] ]]> ] <<-[+<-]+>[->]< #endregion #region Multi_AddToPrev 0 //start ___{ a }___{ b*}___ //resilt ___{res}___{ b*}___ [ [<]<[<]<<[->>+<<]>>[>]>[>]>+<<- [ [<]<[<]>+[>]>[>] >+<<- ] < ] <[<]<<[<]> [[-<+>]>]>>[[-<<<+>>>]>]<<<< [ [->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[->+<[ [->+<]>----------< <[+>]>[<] ]]]]]]]]]]]< ] >>[>]>>>>>[[-<<+>>]>]<<< #endregion [<]<<< #region Multi_WriteNum +[<]>[-[+[>]]<+>>] ++++++[-<-------->]<+<--> [[<]>[+>]<]<[<]>[.>] >++++++[-<++++++++>]<- [[<]>[->]<]<[<]<[[->+<]<]>>[>]< //数値復帰部 #endregion [-]>[-]< ++++++++++[->+++<]>++.[>] ,+[-.,+]
解説
マルチバイト変数を利用しているので、解説は省略します。
総評
全体的に brainfuck
向けの良い問題ばかりが集められていると思います。
あとがき
コンテスト中に記事を書いたのでだいぶ雑です。すみません。
皆さん、これを期に、ぜひ brianfuck
を初めて見てはどうでしょうか。