JavaScriptによる総当たり検索

#JavaScriptによる総当たり検索
##打倒！覆面算
いきなりですが、自分は脱出ゲームや謎解きに、はまっています。
その中でたまに出てくる「覆面算」ってのが苦手です。

<img width="165" alt="fukumen001.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/153636/7069d3f0-220e-87a8-79a4-b20382fff593.jpeg">

ルール
・同じ文字には同じ数字が入り、違う文字には違う数字が入る。
・最上位の文字には0は入らない。

この場合は、M=1ではないかってとこから解きだすのでしょうが・・・

ここはプログラマー的に考えます。
とりうるパターンは10の階乗通り・・・・

10! = 3,628,800
総当たりでやっても全然いけそうです。

やってみよう！

##Cでやってみた	
0~9までの総当たりをループするプログラム

```c
X=1;
for(j[X]=1;j[X]<=Max-X;j[X]++){
	p[j[X]] = 1;

	X=2;
	for(j[X]=1;j[X]<=Max-X;j[X]++){
		for(k=1,m=1;k<=j[X];m++) if(p[m]==0) k++;
		p[m-1] = X;
		
		X=3;
		for(j[X]=1;j[X]<=Max-X;j[X]++){
			for(k=1,m=1;k<=j[X];m++) if(p[m]==0) k++;
			p[m-1] = X;

			X=4;
			for(j[X]=1;j[X]<=Max-X;j[X]++){
				for(k=1,m=1;k<=j[X];m++) if(p[m]==0) k++;
				p[m-1] = X;
			・・・・

```

ちょっと待てよ。このまま10層まで書くのはエレガントではない・・・
Google先生にお知恵を拝借。

```c
typedef int ITEM;
typedef ITEM* Iterator;

//*x と *y を交換する
void iter_swap(Iterator x, Iterator y){
	ITEM t = *x;
	*x = *y;
	*y = t;
}

//first以上 last未満の範囲を反転する
void reverse(Iterator first, Iterator last){
	while( first != last && first != --last){
		iter_swap(first, last);
		++first;
	}
}

//次の組み合わせに入れ替える
bool next_permutation(Iterator first, Iterator last){
	Iterator i = last;
	if(first == last) return false;
	if(first == --i)  return false;
	
	while(1){
		Iterator i1, i2;
		
		i1 = i;
		if(*--i < *i1){
			i2 = last;
			
			while(!(*i < *--i2));
			
			iter_swap(i, i2);
			reverse(i1, last);
			return true;
		}
		
		if(i== first){
			reverse(first, last);
			return false;
		}
	}
}
```

こんな感じで、関数宣言

```c
int main(){
	const int N = 4;
	
	ITEM data[] = { 1, 2, 3, 4 };
	
	do{
		printf("%d,%d,%d,%d\n",data[0],data[1],data[2],data[3]);
	
	}while(next_permutation(data, data+N));

	return 0;
}
```

原理は1,2,3,4で表せる次に大きな数に入れ替える関数です。
このアルゴリズム作った人、天才です。

```c
void main(){
	const int N = 10;	
	ITEM d[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	
	do{
		/* ここに計算が成り立つかの判定分を入れる ≪上記サンプルとは別の問題≫ */
		if(                  d[0]*1000 + d[1]*100 + d[2]*10 + d[3]
			               + d[4]*1000 + d[3]*100 + d[5]*10 + d[6]
			 == d[0]*10000 + d[1]*1000 + d[5]*100 + d[3]*10 + d[7]
			 && d[0] != 0)
		{
			printf("D=%d E=%d B=%d T=%d S=%d A=%d R=%d H=%d\n",d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);
		}

	}while(next_permutation(d, d+N));
}
```

結果、1秒以内で十分総当たりいけました。

##JavaScriptでやってみた

総当たりという重い処理を、JavaScriptでやるという矛盾はおいて置くと、
何より手軽のが良いです。ブラウザがあれば、それだけで実行できます。

```c
var item = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

//*x と *y を交換する
function iter_swap(x, y){
	var t = item[x];
	item[x] = item[y];
	item[y] = t;
}

//first以上 last未満の範囲を反転する
function reverse(first, last){
	while(first != last && first != --last){
		iter_swap(first, last);
		++first;
	}
}

function next_permutation(first, last){
	var i = last;
	if(first == last) return false;
	if(first == --i) return false;

	while(1){
		var i1, i2;

		i1 = i;
		if(item[--i] < item[i1]){
			i2 = last;

			while(!(item[i] < item[--i2]));

			iter_swap(i, i2);
			reverse(i1, last);
			return true;
		}

		if(i==first){
			reverse(first, last);
			return false;
		}
	}
}
```
後はmain関数で

```c
do{
	//判定文
}while(next_permutation(0, 10));

```
さすがに重い。10秒以上かかりますね。


##外出先でやる為
後は、パソコンなくてもできるように、Webページ作ります。

[Mack Calculation](http://shizentai.jp/habapi/test003.html)

<img width="460" alt="fukumen002.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/153636/ea6b101e-98ba-b054-1cad-f7fb976b2517.jpeg">
↓
<img width="469" alt="fukumen003.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/153636/ff689317-31f5-38a1-5f02-bb3e06090b21.jpeg">

できました！！


##終わりに
これで脱出ゲームで、覆面算が出てきても大丈夫です。
これまで戦術だけであった脱出ゲームに戦略的に勝利する日はくるのか・・


さて、最後に企画倒れな求人広告案。総当たり検索ロジック組まないと解けないですが、
解くととあるドメインがでてきます。そこには求人広告を置いておく。
って案は、Googleの企画のまるパクリといわれて却下されました。
（ドメインをとってないので、解いてもなにもありません。）
<img width="243" alt="fukumen004.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/153636/c728d61a-e1f6-292c-610f-60aa1aa11ac3.jpeg">