三流プログラマの戯言

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

CPSCO2019 Session1 B問題をbrainf*ckで解く(後編)

前編では、配列の作成まで書きましたが、 後編では、それらの値がすべて等しいかどうかを判別していきます。

前編を読んでない人は先にそちらを読んでください。

一般の言語だと、配列の先頭から見て、0でなければ記録されている数と一緒かどうかを見ていって、 異なる数値があらわれた場合は no そうでないならyes とすればいいわけです。
C++で書くとこんな感じでしょうか

int num = 0;
bool isAllEqal = true;
for(int i = 0; i< 26; i++){
  if(data[i] != 0){
    if(num == 0) 
      num = data[i];
    else if( data[i] != num){
      isAllEqal = false;
      break;
    }
  }
}

brainf*ckでの実装もこれでもよかったのですが、多少面倒そうだったので、以下の方式で行いました。

int first = 0;
for(int i = 0; i < 26; i++){
  if(data[i].Count == 0) 
    data[i].IsEmpty == true;
}
for(int i = 0; i < 26; i++){
  if(data[i].Count != 0) {
    first = i;
    break;
  }
}
while(data[first].Count !=0){
  data[first].Count--;
  for(int i= first +1; i < 26; i++){
    if(data[i].IsEmpty == true) continue;
    data[i].Count--;
  }
}

ここで for(int i = 0; i < 26; i++) が複数回登場するため、前編で書いたようなindexアクセスを毎回行うのは無駄なので、

for(int i = 0; i < 26; i++){
  data[pos].PtrMarker = 1;
}

として配列であることを示すマークを入れて、

int i = 0 ; 
while(data[pos].PtrMarker == 1){
  //ここに処理を記述
  pos++;
}

といったコードで処理を簡略化します。

そしてほかにも細かいところを、Brainf*ckで書きやすいように変更して、出来上がったbrainf*ckコードがこれです。

++++++++++ ++++++++++ ++++++
[- > >>>[>>>]+[<<<]<]       //for(int i = 0;i<26;i++) data[pos].PtrMarker =1;
    
> >>> [<<[>>>]>>[<+<]>>>>>] //for(int i = 0;i<26;i++)
                            //  if(data[i].Count == 0) 
                            //  data[i].IsEmpty == true;
<<<[>>>>>]<<<<<             //} 

[
  <[<<<]                    // 一番末尾にある有効な要素に移動
  <[[-<[<[<<<]>[<<->]<<]]>>>[<<<<+>]<[->] >>>[>>>]]
                            // 有効要素のCountを1減らす
  >>[>>>] <<< [>>>]<<       // 配列の末尾に移動
]

<
[<[<<<] // 配列の末尾から有効要素を探索
  <[    //見つかった有効要素のcntが0かどうかを判別
    [-]   // cnt != 0 の場合 "No"を出力
    ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++ 
    ++++++++++ ++++++++++ ++++++++.
    ++++++++++  ++++++++++  ++++++++++ ++ +.[-]  
    >[-]>[-]+<  //ループを繰り返さないための処理
  ]< 
]

>> <+>[[-]<->] < //Noが出力されていないことを検知
[ //Noが出力されていない場合はYesを出力
  [-] //Output Yes
  ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++ 
  ++++++++++ ++++++++++ ++++++++++ +++++++++.
  + ++++++++++ +.
  ++++++++++ ++++.
  [-]
]

うわぁ、説明が雑。 (どうせ細かいところを見てる人なんていないでしょう)
ちなみに、C++のコードでは先頭から見て行っていますが、コードの関係上、末尾から見て行っています。
特に深い意味はなく、直前の動作で、ポインタが末尾に近いかったからです。

また、普通の言語ですと、ループ内ですべて等しいかの確認を行い、それをbool型の変数に入れるのが普通だと思いますが、 めんどくさかったので、Noの場合はその場で出力しました。(else句を書くのは意外と面倒なんですよね。)

ここまで読んでくださった方が何人いるかはわかりませんし、上記のプログラムを(こんな雑な説明で)理解できた人はまずいないでしょう。
でも、brainf*ckという言語がどういう言語なのかを少しは感じることができたのではないでしょうか。
brainf*ckについて少しでも興味を持ってもらえると嬉しいです。

それではこれで。