三流プログラマの戯言

プログラミング初心者が気になったことを書き綴るだけ。主にc#

AtCoder Brainfuck Contest 参加記

概要

有志の方がAtCoderのバーチャルコントテストで brainfuck 向けの問題でバチャコンを開いてくれたのでそれに参加しました。 全部まとめて提出用としたところ、ペナを出しました。恥ずかしいです。
というわけで、問題の解説を行っていきたいと思います。
コンテストリンク


目次


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-else2 回書けばいいです。
上記コードでは、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 を初めて見てはどうでしょうか。