はぎあの裏のラクガキ

自身の制作物に関することや、自分の考えなどを置いておきます

JOI2020 1次予選(1回目) A - 3つの整数(Three Integers) Brainfuck解答

はじめに

この記事では、JOI2020 1次予選(1回目)A問題のBrainfuck解答の解説をします。普通の解説が必要な方は他の記事を見たほうが有益かと思います。

問題概要

整数 A, B, Cが与えられる。この3つの整数はいずれも1か2である。1と2のうち多い方の数を求めよ。

解説

解答コードはページの一番下に載せてあります。

配列

解答において、brainfuckの配列には以下のように変数を当てています。

index 0 1 2 3 4 5 6 7 8 9 10 11 12
A (空白) B (空白) C A2 A3 B2 B3 C2 C3 F1 F2
  • A2, A3: Aのコピー(B, Cについても同様)
  • F1, F2: 分岐処理に使うフラグ(後述)

Brainfuckの基本テクニック

本コードの解説の前に、解答で使うテクニックをいくつか紹介します。以下、brainfuckの配列のn番目の値をv[n]と表します。

値のコピー

brainfuckでは値を破壊することが多くあるため、値のコピーが必要になります。
下記のコードはv[0]の値をv[1]とv[2]にコピーするコードです。

[>+>+<<-]
値の比較

下記のコードはv[0]とv[1]を比較します。v[0]=v[1]のとき、v[1]=0、そうでない時v[1]≠0となります。(v[0]の値はいかなる場合も0です。)

[->-<]
条件分岐

[]を使用することで、ポインタの指す場所の値が0でないかどうかで条件分岐ができます。他言語でいうelse句は、else句を実行するかを記録するフラグを用意し、then句の中でelse句を実行しないようにします。
下記のコードは、v[0]≠0のとき処理1を、そうでない時処理2を実行するコードです。else句実行フラグはv[1]とします。

[[-]>[-]<(処理1)]>[[-](処理2)]

以上のテクニック()を使うことで、この問題は比較的簡単に解くことができます。

解答コード(Brainfuck)

わかりやすさのためにコメントやインデントを入れています。

,>,>,>,>,<<<<[>>>>>+>+<<<<<<-]>>[>>>>>+>+<<<<<<-]>>[>>>>>+>+<<<<<<-]>>>>>>>+>+<<<<<<< 変数の初期化(詳細は解説の配列の項を参照のこと)
[->>-<<]>> もしA2≠B2ならば
    [<[->>>-<<<]>>> もしA3≠C2ならば
        [<.>>>[-]>[-]<<<[-]] B3を表示し、以下のコードを実行しないようにする(C2, F1, F2を0にする)
    >>>[<<.>[-]>[-]]<<<<<[-]] A3=C2ならば、C3を表示し、以下のコードを実行しないようにする(B2, F1, F2を0にする)
>>>>[<<<<<.[-]] A2=B2ならばA3を表示する