#pragma warning(disable: 4996)

#include<iostream>

#include<stdlib.h> /*callocrand,srandを使うのに必要*/

#include<ctime>

#include<process.h>

#include<conio.h> //while (!_kbhit()); を使うためのお呪い。

#include <math.h>

#include <cmath>

#include<process.h>

#include <iomanip>

#include <stdio.h>

#include <stdlib.h>

using namespace std;

const size_t th = 12;

void 問題生成関数(size_t g, size_t a);

void 非対称配列関数(size_t a);

void 左右対称配列関数(size_t a);

void 上下対称配列関数(size_t a);

void 点対称配列関数(size_t a);

void 左右上下対称配列関数(size_t a);//対称対称かつ点対称配列でもある。

void ハート型配列関数(size_t a);

void 局所解析関数(size_t s, size_t t, size_t a);

void 代入関数(size_t a);

char 継続 = 1;

size_t* どのスレッドが発見したか示す変数 = (size_t*)calloc(th, sizeof(size_t));

unsigned シード値 = (unsigned)time(NULL);

void 変身の術関数(void* a);

void 初期化0(size_t a);

void 初期化1(size_t a);

void 入力順決定関数(size_t g, size_t a);

size_t 検証関数(size_t a);

size_t 全体リスト構造解析関数(size_t a);

void 解答作成関数(size_t a);

void 問題作成関数(size_t a);

void ライン排除関数(size_t a);

void 相補確定関数(size_t a);

void 三対三確定および排除関数(size_t a);

void リスト法関数(size_t a);

void ライン行排除関数(size_t a);

void ライン列排除関数(size_t a);

void ラインブロック排除関数(size_t a);

void 相補確定とそれによる行排除関数(size_t a);

void 相補確定とそれによる列排除関数(size_t a);

void 相補確定とそれによるブロック排除関数(size_t a);

void 三対三確定および排除行関数(size_t a);

void 三対三確定および排除列関数(size_t a);

void 三対三確定および排除ブロック関数(size_t a);

void #排除関数(size_t a);

const size_t RN = 5;

const size_t N = RN * RN;

const size_t N2 = N * N;

void 表示関数3(size_t a);

void 表示関数4(size_t a);

void 表示関数5(size_t a);

size_t m[th][N][N];//問題

size_t mx[th][N][N];//座標(N,N)候補リスト数

size_t wb[th][N][N][N];

//スレッドNにおける座標(N,N)の色塗り 色は入力文字に対応9×9数独なら1から9

size_t rlst[th][N][N][N];

//スレッドNにおける座標(N,N)の候補数字リスト

size_t y[th][N2], x[th][N2];//各スレッドにおいて入力順決定関数を使うときの座標

size_t yy[th][N2], xx[th][N2];

//9×9を例にとると01,・・・,80各セル番号を等間隔に飛ぶ座標

//スタート地点も飛ぶ間隔も疑似乱数によってスレッド毎にランダムに与えられる。

size_t cm[th][N][N];//解答

size_t ヒント数, 空欄数[th], cn[th];//各スレッドで解答が発見されると1になる。

size_t S;//左右対称型などのタイプを示す変数

clock_t hj1[th], ow1[th];

//各スレッドの数独を解き始める時間と解き終わったときの時間

clock_t 初期配置数 = 20;

int  main() {

           size_t ii[th];

           ヒント数 = 400;

           clock_t hj, ow;//数独

           cout << "数独のタイプ:" << N << "×" << N << endl;

           cout << "初期配置数 = " << 初期配置数 << endl;

           cout << "ヒント数 = " << ヒント数 << endl;

           cout << "スレッド数 = " << th << endl;

           hj = clock();

           シード値 = (unsigned)time(NULL);

           継続 = 1;

           for (size_t i = 1; i < th; i += 1) {

                      ii[i] = i;

                      _beginthread(変身の術関数, 0, &ii[i]); //新しいスレッドを起動して、そのスレッド上で関数問題生成関数を働かせなさいの命令

           }

           srand(シード値);

           while (1) {

                      初期化0(0);

                      size_t 選択変数 = 4;

                      非対称配列関数(0);

                      /*size_t 選択変数;

                      if (ヒント数 == 20)選択変数 = rand() % 5; else 選択変数 = rand() % 6;

                      if (選択変数 == 0) 左右対称配列関数(0);

                      if (選択変数 == 1) 上下対称配列関数(0);

                      if (選択変数 == 2) 点対称配列関数(0);

                      if (選択変数 == 3) 左右上下対称配列関数(0);

                      if (選択変数 == 4) 非対称配列関数(0);

                      if (選択変数 == 5) ハート型配列関数(0);*/

                      if (継続 == 0)break;

                      cn[0] = 0;

                      問題生成関数(0, 0);

                      if (継続 == 0)break;

                      問題作成関数(0);

                      if (継続 == 0)break;              

                      解答作成関数(0);

                      if (cn[0] == 1) {

                                  ow1[0] = clock();

                                  どのスレッドが発見したか示す変数[0] = 1;

                                  継続 = 0;

                                  goto tobi0;

                      }

           }

tobi0:;

           while (継続);

           size_t ik;

           for (size_t i = 0; i < th; i++)if (どのスレッドが発見したか示す変数[i] == 1) { ik = i; break; }

           //数独を見つけたスレッドを特定した。

           for (size_t i = ヒント数; i < N2; i++) {

                      m[ik][yy[ik][i]][xx[ik][i]] = 0;

           }

           表示関数5(ik);

           /*if (検証関数(ik) == 1)cout << ""; else cout << "×";

           cout << endl;*/

           FILE* fp;

           /*ファイル(save.csv)に書き込む*/

           if ((fp = fopen("a.csv", "w")) != NULL) {

                      for (size_t i = 0; i < N; i++) {

                                  for (size_t j = 0; j < N; j++) {

                                             fprintf(fp, "%d,\n", cm[ik][i][j]);//問題

                                  }

                      }

                      for (size_t i = 0; i < N; i++) {

                                  for (size_t j = 0; j < N; j++) {

                                             /*カンマで区切ることでCSVファイルとする*/

                                             fprintf(fp, "%d,\n", m[ik][i][j]);//解答

                                  }

                      }

           }

           /*忘れずに閉じる*/

           fclose(fp);

           ow = clock();

           cout << "数独解法時間は" << (double)(ow1[ik] - hj1[ik]) / CLOCKS_PER_SEC << "秒です。" << endl;

           cout << "数独生成時間は" << (double)(ow - hj) / CLOCKS_PER_SEC << "秒です。" << endl;

           while (!_kbhit()); //待機させるための命令

           return 0;

}

void 変身の術関数(void* aa) {

           size_t a = *(size_t*)aa;

           srand(シード値 - 19 * (a + 1));

           while (1) {

                      初期化0(a);

                      size_t 選択変数 = 4;

                      非対称配列関数(a);

                      /*size_t 選択変数;

                      if (ヒント数 == 20)選択変数 = rand() % 5; else 選択変数 = rand() % 6;

                      if (選択変数 == 0) 左右対称配列関数(a);

                      if (選択変数 == 1) 上下対称配列関数(a);

                      if (選択変数 == 2) 点対称配列関数(a);

                      if (選択変数 == 3) 左右上下対称配列関数(a);

                      if (選択変数 == 4) 非対称配列関数(a);

                      if (選択変数 == 5) ハート型配列関数(a);*/

                      cn[a] = 0;

                      問題生成関数(0, a);

                      if (継続 == 0)return;

                      問題作成関数(a);

                      if (継続 == 0)return;

                      空欄数[a] = N2 - ヒント数;

                      hj1[a] = clock();

                      解答作成関数(a);

                      if (cn[a] == 1) {

                                  ow1[a] = clock();

                                  どのスレッドが発見したか示す変数[a] = 1;

                                  継続 = 0;

                                  return;

                      }

           }

}

void 表示関数3(size_t a) {

           for (int i = 0; i < N + 1; i++) {

                      if (i % RN == 0) {

                                  cout << " ";

                                  for (int j = 0; j < N + 3; j++) {

                                             cout << "- ";

                                  }

                                  cout << " ";

                                  cout << endl;

                      }

                      if (i == N)break;

                      for (int j = 0; j < N + 1; j++) {

                                  if (j % RN == 0) {

                                             cout << "| ";

                                  }

                                  if (j < N) {

                                             if (cm[a][i][j] == 0)cout << "* "; else cout << cm[a][i][j] << " ";

                                             //問題

                                  }

                      }

                      cout << endl;

           }

           for (int i = 0; i < N + 1; i++) {

                      if (i % RN == 0) {

                                  cout << " ";

                                  for (int j = 0; j < N + 3; j++) {

                                             cout << "- ";

                                  }

                                  cout << " ";

                                  cout << endl;

                      }

                      if (i == N)break;

                      for (int j = 0; j < N + 1; j++) {

                                  if (j % RN == 0) {

                                             cout << "| ";

                                  }

                                  if (j < N) {

                                             if (m[a][i][j] == 0)cout << "* "; else cout << m[a][i][j] << " ";//問題

                                  }

                      }

                      cout << endl;

           }

}

void 表示関数4(size_t a) {

           for (int i = 0; i < N + 1; i++) {

                      if (i % RN == 0) {

                                  cout << " ";

                                  for (int j = 0; j < N + 18; j++) {

                                             cout << "- ";

                                  }

                                  cout << " ";

                                  cout << endl;

                      }

                      if (i == N)break;

                      for (int j = 0; j < N + 1; j++) {

                                  if (j % RN == 0) {

                                             cout << "|";

                                  }

                                  if (j < N) {

                                             if (m[a][i][j] == 0) {

                                                        cout << " ** ";//問題

                                             }

                                             if (m[a][i][j] > 0 && m[a][i][j] < 10) {

                                                        cout << "  " << m[a][i][j] << " ";//問題

                                             }

                                             if (m[a][i][j] >= 10) {

                                                        cout << " " << m[a][i][j] << " ";//解答

                                             }

                                  }

                      }

                      cout << endl;

           }

           for (int i = 0; i < N + 1; i++) {

                      if (i % RN == 0) {

                                  cout << " ";

                                  for (int j = 0; j < N + 18; j++) {

                                             cout << "- ";

                                  }

                                  cout << " ";

                                  cout << endl;

                      }

                      if (i == N)break;

                      for (int j = 0; j < N + 1; j++) {

                                  if (j % RN == 0) {

                                             cout << "|";

                                  }

                                  if (j < N) {

                                             if (cm[a][i][j] == 0) {

                                                        cout << " ** ";//解答

                                             }

                                             if (cm[a][i][j] > 0 && cm[a][i][j] < 10) {

                                                        cout << "  " << cm[a][i][j] << " ";//解答

                                             }

                                             if (cm[a][i][j] >= 10) {

                                                        cout << " " << cm[a][i][j] << " ";//解答

                                             }

                                  }

                      }

                      cout << endl;

           }

}

void 表示関数5(size_t a) {

           for (int i = 0; i < N + 1; i++) {

                      if (i % RN == 0) {

                                  cout << " ";

                                  for (int j = 0; j < N + 27; j++) {

                                             cout << "- ";

                                  }

                                  cout << " ";

                                  cout << endl;

                      }

                      if (i == N)break;

                      for (int j = 0; j < N + 1; j++) {

                                  if (j % RN == 0) {

                                             cout << "|";

                                  }

                                  if (j < N) {

                                             if (m[a][i][j] == 0) {

                                                        cout << " ** ";//問題

                                             }

                                             if (m[a][i][j] > 0 && m[a][i][j] < 10) {

                                                        cout << "  " << m[a][i][j] << " ";//問題

                                             }

                                             if (m[a][i][j] >= 10) {

                                                        cout << " " << m[a][i][j] << " ";//解答

                                             }

                                  }

                      }

                      cout << endl;

           }

           for (int i = 0; i < N + 1; i++) {

                      if (i % RN == 0) {

                                  cout << " ";

                                  for (int j = 0; j < N + 27; j++) {

                                             cout << "- ";

                                  }

                                  cout << " ";

                                  cout << endl;

                      }

                      if (i == N)break;

                      for (int j = 0; j < N + 1; j++) {

                                  if (j % RN == 0) {

                                             cout << "|";

                                  }

                                  if (j < N) {

                                             if (cm[a][i][j] == 0) {

                                                        cout << " ** ";//解答

                                             }

                                             if (cm[a][i][j] > 0 && cm[a][i][j] < 10) {

                                                        cout << "  " << cm[a][i][j] << " ";//解答

                                             }

                                             if (cm[a][i][j] >= 10) {

                                                        cout << " " << cm[a][i][j] << " ";//解答

                                             }

                                  }

                      }

                      cout << endl;

           }

}

void 解答作成関数(size_t a) {

           size_t i, k空欄数;

           if (全体リスト構造解析関数(a) == 1) {

                      cn[a] = 2;

                      return;

           }

           for (i = 0; i < N; i++) {

                      k空欄数 = 空欄数[a];

                      ライン排除関数(a);

                      if (cn[a] > 0) return;

                      if (空欄数[a] == 0) {

                                  cn[a] = 1;

                                  return;

                      }

                      相補確定関数(a);

                      三対三確定および排除関数(a);

                      #排除関数(a);

                      if (空欄数[a] == 0) {

                                  cn[a] = 1;

                                  return;

                      }

                      リスト法関数(a);

                      if (cn[a] > 0)return;

                      if (空欄数[a] == 0) {

                                  cn[a] = 1;

                                  return;

                      }

                      if (k空欄数 == 空欄数[a]) {

                                  cn[a] = 0;

                                  return;

                      }

           }

}

size_t 全体リスト構造解析関数(size_t a) {

           size_t i, j;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  if (m[a][i][j] == 0) {

                                             局所解析関数(i, j, a);

                                             if (mx[a][i][j] == 0) {

                                                        return(1);

                                             }

                                  }

                      }

           }

           return(0);

}

void ライン行排除関数(size_t a) {

           size_t i, j, k, w, jk, kk, s, t;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  w = 0;

                                  for (k = 0; k < N; k++) {

                                             if (m[a][j][k] == 0) {

                                                        if (wb[a][j][k][i] == 0) {

                                                                   jk = j;

                                                                   kk = k;

                                                                   w = w + 1;

                                                        }

                                             }

                                  }

                                  if (w == 1) {

                                             if (空欄数[a] == 0) {

                                                        cn[a] = 2;

                                                        return;

                                             }

                                             m[a][jk][kk] = i + 1;

                                             空欄数[a] = 空欄数[a] - 1;

                                             if (空欄数[a] == 0) return;

                                             for (k = 0; k < N; k++) {

                                                        if (m[a][jk][k] == 0) {

                                                                   wb[a][jk][k][m[a][jk][kk] - 1] = 1;

                                                        }

                                                        if (m[a][k][kk] == 0) {

                                                                   wb[a][k][kk][m[a][jk][kk] - 1] = 1;

                                                        }

                                                        s = RN * (jk / RN) + (k / RN);

                                                        t = RN * (kk / RN) + (k % RN);

                                                        if (m[a][s][t] == 0) {

                                                                   wb[a][s][t][m[a][jk][kk] - 1] = 1;

                                                        }

                                             }

                                             for (k = 0; k < N; k++) {

                                                        if (m[a][jk][k] == 0)局所解析関数(jk, k, a);

                                                        if (m[a][k][kk] == 0) 局所解析関数(k, kk, a);

                                                        s = RN * (jk / RN) + (k / RN);

                                                        t = RN * (kk / RN) + (k % RN);

                                                        if (m[a][s][t] == 0)局所解析関数(s, t, a);

                                             }

                                  }

                      }

           }

}

void ライン列排除関数(size_t a) {

           size_t i, j, k, w, jk, kk, s, t;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  w = 0;

                                  for (k = 0; k < N; k++) {

                                             if (m[a][k][j] == 0) {

                                                        if (wb[a][k][j][i] == 0) {

                                                                   jk = j;

                                                                   kk = k;

                                                                   w = w + 1;

                                                        }

                                             }

                                  }

                                  if (w == 1) {

                                             if (空欄数[a] == 0) {

                                                        cn[a] = 2;

                                                        return;

                                             }

                                             m[a][kk][jk] = i + 1;

                                             空欄数[a] = 空欄数[a] - 1;

                                             if (空欄数[a] == 0) return;

                                             for (k = 0; k < N; k++) {

                                                        if (m[a][kk][k] == 0) {

                                                                   wb[a][kk][k][m[a][kk][jk] - 1] = 1;

                                                        }

                                                        if (m[a][k][jk] == 0) {

                                                                   wb[a][k][jk][m[a][kk][jk] - 1] = 1;

                                                        }

                                                        s = RN * (kk / RN) + (k / RN);

                                                        t = RN * (jk / RN) + (k % RN);

                                                        if (m[a][s][t] == 0) {

                                                                   wb[a][s][t][m[a][kk][jk] - 1] = 1;

                                                        }

                                             }

                                             for (k = 0; k < N; k++) {

                                                        if (m[a][kk][k] == 0)局所解析関数(kk, k, a);

                                                        if (m[a][k][jk] == 0)局所解析関数(k, jk, a);

                                                        s = RN * (kk / RN) + (k / RN);//ブロック部分を動く y座標

                                                        t = RN * (jk / RN) + (k % RN);//ブロック部分を動く x座標

                                                        if (m[a][s][t] == 0)局所解析関数(s, t, a);

                                             }

                                  }

                      }

           }

}

void ラインブロック排除関数(size_t a) {

           size_t i, j, k, w, sk, tk, s, t, s1, t1;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  w = 0;

                                  for (k = 0; k < N; k++) {

                                             s = RN * (j / RN) + (k / RN);

                                             t = RN * (j % RN) + (k % RN);

                                             if (m[a][s][t] == 0) {

                                                        if (wb[a][s][t][i] == 0) {

                                                                   sk = s;

                                                                   tk = t;

                                                                   w = w + 1;

                                                        }

                                             }

                                  }

                                  if (w == 1) {

                                             if (空欄数[a] == 0) {

                                                        cn[a] = 2;

                                                        return;

                                             }

                                             m[a][sk][tk] = i + 1;

                                             空欄数[a] = 空欄数[a] - 1;

                                             if (空欄数[a] == 0) return;

                                             for (k = 0; k < N; k++) {

                                                        if (m[a][sk][k] == 0) {

                                                                   wb[a][sk][k][m[a][sk][tk] - 1] = 1;

                                                        }

                                                        if (m[a][k][tk] == 0) {

                                                                   wb[a][k][tk][m[a][sk][tk] - 1] = 1;

                                                        }

                                                        s1 = RN * (sk / RN) + (k / RN);

                                                        t1 = RN * (tk / RN) + (k % RN);

                                                        if (m[a][s1][t1] == 0) {

                                                                   wb[a][s1][t1][m[a][sk][tk] - 1] = 1;

                                                        }

                                             }

                                             for (k = 0; k < N; k++) {

                                                        if (m[a][sk][k] == 0)局所解析関数(sk, k, a);

                                                        if (m[a][k][tk] == 0)局所解析関数(k, tk, a);

                                                        s1 = RN * (sk / RN) + (k / RN);

                                                        t1 = RN * (tk / RN) + (k % RN);

                                                        if (m[a][s1][t1] == 0)局所解析関数(s1, t1, a);

                                             }

                                  }

                      }

           }

}

void ライン排除関数(size_t a) {

           ライン行排除関数(a);

           if (空欄数[a] == 0) {

                      cn[a] = 1;

                      return;

           }

           ライン列排除関数(a);

           if (空欄数[a] == 0) {

                      cn[a] = 1;

                      return;

           }

           ラインブロック排除関数(a);

}

void 相補確定とそれによる行排除関数(size_t a) {

           size_t i, j, k, w, onoff[N];

           size_t ckotae[N], l;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  for (k = j + 1; k < N; k++) {

                                             if (mx[a][i][j] == 2 && mx[a][i][k] == 2) {

                                                        for (l = 0; l < N; l++) {

                                                                   onoff[l] = 0;

                                                        }

                                                        for (l = 0; l < 2; l++) {

                                                                   onoff[rlst[a][i][j][l] - 1] = 1;

                                                                   onoff[rlst[a][i][k][l] - 1] = 1;

                                                        }

                                                        w = 0;

                                                        for (l = 0; l < N; l++) {

                                                                   if (onoff[l] == 1) {

                                                                              ckotae[w] = l;

                                                                              w = w + 1;

                                                                   }

                                                        }

                                                        if (w == 2) {

                                                                   for (l = 0; l < N; l++) {

                                                                              if (l != j && l != k) {

                                                                                          if (m[a][i][l] == 0) {

                                                                                                     wb[a][i][l][ckotae[0]] = 1;

                                                                                                     wb[a][i][l][ckotae[1]] = 1;

                                                                                          }

                                                                              }

                                                                   }

                                                                   for (l = 0; l < N; l++) {

                                                                              if (l != j && l != k) {

                                                                                          if (m[a][i][l] == 0) {

                                                                                                     局所解析関数(i, l, a);

                                                                                          }

                                                                              }

                                                                   }

                                                        }

                                             }

                                  }

                      }

           }

}

void 相補確定とそれによる列排除関数(size_t a) {

           size_t i, j, k, w, onoff[N];

           size_t ckotae[N], l;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  for (k = j + 1; k < N; k++) {

                                             if (mx[a][j][i] == 2 && mx[a][k][i] == 2) {

                                                        for (l = 0; l < N; l++) {

                                                                   onoff[l] = 0;

                                                        }

                                                        for (l = 0; l < 2; l++) {

                                                                   onoff[rlst[a][j][i][l] - 1] = 1;

                                                                   onoff[rlst[a][k][i][l] - 1] = 1;

                                                        }

                                                        w = 0;

                                                        for (l = 0; l < N; l++) {

                                                                   if (onoff[l] == 1) {

                                                                              ckotae[w] = l;

                                                                              w = w + 1;

                                                                   }

                                                        }

                                                        if (w == 2) {

                                                                   for (l = 0; l < N; l++) {

                                                                              if (l != j && l != k) {

                                                                                          if (m[a][l][i] == 0) {

                                                                                                     wb[a][l][i][ckotae[0]] = 1;

                                                                                                     wb[a][l][i][ckotae[1]] = 1;

                                                                                          }

                                                                              }

                                                                   }

                                                                   for (l = 0; l < N; l++) {

                                                                              if (l != j && l != k) {

                                                                                          if (m[a][l][i] == 0) {

                                                                                                     局所解析関数(l, i, a);

                                                                                          }

                                                                              }

                                                                   }

                                                        }

                                             }

                                  }

                      }

           }

}

void 相補確定とそれによるブロック排除関数(size_t a) {

           size_t i, j, k, w, onoff[N], s1, s2, t1, t2, s3, t3, s4, t4;;

           size_t ckotae[N], l;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  s1 = RN * (i / RN) + (j / RN);

                                  t1 = RN * (i % RN) + (j % RN);

                                  for (k = j + 1; k < N; k++) {

                                             s2 = RN * (i / RN) + (k / RN);

                                             t2 = RN * (i % RN) + (k % RN);

                                             if (mx[a][s1][t1] == 2 && mx[a][s2][t2] == 2) {

                                                        for (l = 0; l < N; l++) {

                                                                   onoff[l] = 0;

                                                        }

                                                        for (l = 0; l < 2; l++) {

                                                                   onoff[rlst[a][s1][t1][l] - 1] = 1;

                                                                   onoff[rlst[a][s2][t2][l] - 1] = 1;

                                                        }

                                                        w = 0;

                                                        for (l = 0; l < N; l++) {

                                                                   if (onoff[l] == 1) {

                                                                              ckotae[w] = l;

                                                                              w = w + 1;

                                                                   }

                                                        }

                                                        if (w == 2) {

                                                                   for (l = 0; l < N; l++) {

                                                                              if (l != j && l != k) {

                                                                                          s3 = RN * (i / RN) + (l / RN);

                                                                                          t3 = RN * (i % RN) + (l % RN);

                                                                                          if (m[a][s3][t3] == 0) {

                                                                                                     wb[a][s3][t3][ckotae[0]] = 1;

                                                                                                     wb[a][s3][t3][ckotae[1]] = 1;

                                                                                          }

                                                                              }

                                                                   }

                                                                   for (l = 0; l < N; l++) {

                                                                              if (l != j && l != k) {

                                                                                          s4 = RN * (i / RN) + (l / RN);

                                                                                          t4 = RN * (i % RN) + (l % RN);

                                                                                          if (m[a][s4][t4] == 0) {

                                                                                                     局所解析関数(s4, t4, a);

                                                                                          }

                                                                              }

                                                                   }

                                                        }

                                             }

                                  }

                      }

           }

}

void 相補確定関数(size_t a) {

           相補確定とそれによる行排除関数(a);

           相補確定とそれによる列排除関数(a);

           相補確定とそれによるブロック排除関数(a);

}

void 三対三確定および排除行関数(size_t a) {

           size_t i, j, k, w, onoff[N];

           size_t ckotae[N], l, n;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  for (k = j + 1; k < N; k++) {

                                             for (l = k + 1; l < N; l++) {

                                                        if ((m[a][i][j] == RN) && (m[a][i][k] == RN) && (m[a][i][l] == RN)) {

                                                                   for (n = 0; n < N; n++) {

                                                                              onoff[n] = 0;

                                                                   }

                                                                   for (n = 0; n < m[a][i][j]; n++) {

                                                                              onoff[rlst[a][i][j][n] - 1] = 1;

                                                                   }

                                                                   for (n = 0; n < m[a][i][k]; n++) {

                                                                              onoff[rlst[a][i][k][n] - 1] = 1;

                                                                   }

                                                                   for (n = 0; n < m[a][i][l]; n++) {

                                                                              onoff[rlst[a][i][l][n] - 1] = 1;

                                                                   }

                                                                   w = 0;

                                                                   for (n = 0; n < N; n++) {

                                                                              if (onoff[n] == 1) {

                                                                                          ckotae[w] = n;

                                                                                          w = w + 1;

                                                                              }

                                                                   }

                                                                   if (w == RN) {

                                                                              for (n = 0; n < N; n++) {

                                                                                          if (n != j && n != k && n != l) {

                                                                                                     if (m[a][i][n] == 0) {

                                                                                                                wb[a][i][n][ckotae[0]] = 1;

                                                                                                                wb[a][i][n][ckotae[1]] = 1;

                                                                                                                wb[a][i][n][ckotae[2]] = 1;

                                                                                                     }

                                                                                          }

                                                                              }

                                                                              for (n = 0; n < N; n++) {

                                                                                          if (n != j && n != k && n != l) {

                                                                                                     if (m[a][i][n] == 0) {

                                                                                                                局所解析関数(i, n, a);

                                                                                                     }

                                                                                          }

                                                                              }

                                                                   }

                                                        }

                                             }

                                  }

                      }

           }

}

void 三対三確定および排除列関数(size_t a) {

           size_t i, j, k, w, onoff[N];

           size_t ckotae[N], l, n;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  for (k = j + 1; k < N; k++) {

                                             for (l = k + 1; l < N; l++) {

                                                        if ((m[a][j][i] == RN) && (m[a][k][i] == RN) && (m[a][l][i] == RN)) {

                                                                   for (n = 0; n < N; n++) {

                                                                              onoff[n] = 0;

                                                                   }

                                                                   for (n = 0; n < m[a][j][i]; n++) {

                                                                              onoff[rlst[a][j][i][n] - 1] = 1;

                                                                   }

                                                                   for (n = 0; n < m[a][k][i]; n++) {

                                                                              onoff[rlst[a][k][i][n] - 1] = 1;

                                                                   }

                                                                   for (n = 0; n < m[a][l][i]; n++) {

                                                                              onoff[rlst[a][l][i][n] - 1] = 1;

                                                                   }

                                                                   w = 0;

                                                                   for (n = 0; n < N; n++) {

                                                                              if (onoff[n] == 1) {

                                                                                          ckotae[w] = n;

                                                                                          w = w + 1;

                                                                              }

                                                                   }

                                                                   if (w == RN) {

                                                                              for (n = 0; n < N; n++) {

                                                                                          if (n != j && n != k && n != l) {

                                                                                                     if (m[a][n][i] == 0) {

                                                                                                                wb[a][n][i][ckotae[0]] = 1;

                                                                                                                wb[a][n][i][ckotae[1]] = 1;

                                                                                                                wb[a][n][i][ckotae[2]] = 1;

                                                                                                     }

                                                                                          }

                                                                              }

                                                                              for (n = 0; n < N; n++) {

                                                                                          if (n != j && n != k && n != l) {

                                                                                                     if (m[a][n][i] == 0) {

                                                                                                                局所解析関数(n, i, a);

                                                                                                     }

                                                                                          }

                                                                              }

                                                                   }

                                                        }

                                             }

                                  }

                      }

           }

}

void 三対三確定および排除ブロック関数(size_t a) {

           size_t i, j, k, w, onoff[N];

           size_t ckotae[N], l, n;

           size_t s1, s2, s3, s4, t1, t2, t3, t4;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  s1 = RN * (i / RN) + (j / RN);

                                  t1 = RN * (i % RN) + (j % RN);

                                  for (k = j + 1; k < N; k++) {

                                             s2 = RN * (i / RN) + (k / RN);

                                             t2 = RN * (i % RN) + (k % RN);

                                             for (l = k + 1; l < N; l++) {

                                                        s3 = RN * (i / RN) + (l / RN);

                                                        t3 = RN * (i % RN) + (l % RN);

                                                        if ((m[a][s1][t1] == RN) && (m[a][s2][t2] == RN) && (m[a][s3][t3] == RN)) {

                                                                   for (n = 0; n < N; n++) {

                                                                              onoff[n] = 0;

                                                                   }

                                                                   for (n = 0; n < m[a][s1][t1]; n++) {

                                                                              onoff[rlst[a][s1][t1][n] - 1] = 1;

                                                                   }

                                                                   for (n = 0; n < m[a][s2][t2]; n++) {

                                                                              onoff[rlst[a][s2][t2][n] - 1] = 1;

                                                                   }

                                                                   for (n = 0; n < m[a][s3][t3]; n++) {

                                                                              onoff[rlst[a][s3][t3][n] - 1] = 1;

                                                                   }

                                                                   w = 0;

                                                                   for (n = 0; n < N; n++) {

                                                                              if (onoff[n] == 1) {

                                                                                          ckotae[w] = n;

                                                                                          w = w + 1;

                                                                              }

                                                                   }

                                                                   if (w == RN) {

                                                                              for (n = 0; n < N; n++) {

                                                                                          if (n != j && n != k && n != l) {

                                                                                                     s4 = RN * (i / RN) + (n / RN);

                                                                                                     t4 = RN * (i % RN) + (n % RN);

                                                                                                     if (m[a][s4][t4] == 0) {

                                                                                                                wb[a][s4][t4][ckotae[0]] = 1;

                                                                                                                wb[a][s4][t4][ckotae[1]] = 1;

                                                                                                                wb[a][s4][t4][ckotae[2]] = 1;

                                                                                                     }

                                                                                          }

                                                                              }

                                                                              for (n = 0; n < N; n++) {

                                                                                          if (n != j && n != k && n != l) {

                                                                                                     s4 = RN * (i / RN) + (n / RN);

                                                                                                     t4 = RN * (i % RN) + (n % RN);

                                                                                                     if (m[a][s4][t4] == 0) {

                                                                                                                局所解析関数(s4, t4, a);

                                                                                                     }

                                                                                          }

                                                                              }

                                                                   }

                                                        }

                                             }

                                  }

                      }

           }

}

void 三対三確定および排除関数(size_t a) {

           三対三確定および排除行関数(a);

           三対三確定および排除列関数(a);

           三対三確定および排除ブロック関数(a);

}

void #排除関数(size_t a) {

           size_t i, j, wx, wy, k;

           size_t yk[N][N], xk[N][N];

           for (i = 0; i < N; i++) {

                      wy = 0;

                      for (j = 0; j < N; j++) {

                                  wx = 0;

                                  for (k = 0; k < N; k++) {

                                             if (m[a][j][k] == 0) {

                                                        if (wb[a][j][k][i] == 0) {

                                                                   yk[wy][wx] = j;

                                                                   xk[wy][wx] = k;

                                                                   wx = wx + 1;

                                                        }

                                             }

                                  }

                                  if (wx == 2) {

                                             wy = wy + 1;

                                  }

                      }

                      if (wy == 2) {

                                  if (xk[0][0] == xk[1][0] && xk[0][1] == xk[1][1]) {

                                             for (k = 0; k < N; k++) {

                                                        if (k != xk[0][0] && k != xk[0][1]) {

                                                                   if (m[a][yk[0][0]][k] == 0) {

                                                                              wb[a][yk[0][0]][k][i] = 1;

                                                                   }

                                                                   if (m[a][yk[1][1]][k] == 0) {

                                                                              wb[a][yk[1][1]][k][i] = 1;

                                                                   }

                                                        }

                                             }

                                             for (k = 0; k < N; k++) {

                                                        if (k != xk[0][0] && k != xk[0][1]) {

                                                                   if (m[a][yk[0][0]][k] == 0) {

                                                                              局所解析関数(yk[0][0], k, a);

                                                                   }

                                                                   if (m[a][yk[1][1]][k] == 0) {

                                                                              局所解析関数(yk[1][1], k, a);

                                                                   }

                                                        }

                                             }

                                             for (k = 0; k < N; k++) {

                                                        if (k != yk[0][0] && k != yk[1][1]) {

                                                                   if (m[a][k][xk[0][0]] == 0) {

                                                                              wb[a][k][xk[0][0]][i] = 1;

                                                                   }

                                                                   if (m[a][k][xk[1][1]] == 0) {

                                                                              wb[a][k][xk[1][1]][i] = 1;

                                                                   }

                                                        }

                                             }

                                             for (k = 0; k < N; k++) {

                                                        if (k != yk[0][0] && k != yk[1][1]) {

                                                                   if (m[a][k][xk[0][0]] == 0) {

                                                                              局所解析関数(k, xk[0][0], a);

                                                                   }

                                                                   if (m[a][k][xk[1][1]] == 0) {

                                                                              局所解析関数(k, xk[1][1], a);

                                                                   }

                                                        }

                                             }

                                  }

                      }

           }

           for (i = 0; i < N; i++) {

                      wx = 0;

                      for (j = 0; j < N; j++) {

                                  wy = 0;

                                  for (k = 0; k < N; k++) {

                                             if (m[a][k][j] == 0) {

                                                        if (wb[a][k][j][i] == 0) {

                                                                   yk[wx][wy] = k;

                                                                   xk[wx][wy] = j;

                                                                   wy = wy + 1;

                                                        }

                                             }

                                  }

                                  if (wy == 2) {

                                             wx = wx + 1;

                                  }

                      }

                      if (wx == 2) {

                                  if (yk[0][0] == yk[1][0] && yk[0][1] == yk[1][1]) {

                                             for (k = 0; k < N; k++) {

                                                        if (k != yk[0][0] && k != yk[0][1]) {

                                                                   if (m[a][k][xk[0][0]] == 0) {

                                                                              wb[a][k][xk[0][0]][i] = 1;

                                                                   }

                                                                   if (m[a][k][xk[1][1]] == 0) {

                                                                              wb[a][k][xk[1][1]][i] = 1;

                                                                   }

                                                        }

                                             }

                                             for (k = 0; k < N; k++) {

                                                        if (k != yk[0][0] && k != yk[1][1]) {

                                                                   if (m[a][k][xk[0][0]] == 0) {

                                                                              局所解析関数(k, xk[0][0], a);

                                                                   }

                                                                   if (m[a][k][xk[1][1]] == 0) {

                                                                              局所解析関数(k, xk[1][1], a);

                                                                   }

                                                        }

                                             }

                                             for (k = 0; k < N; k++) {

                                                        if (k != xk[0][0] && k != xk[1][1]) {

                                                                   if (m[a][yk[0][0]][k] == 0) {

                                                                              wb[a][yk[0][0]][k][i] = 1;

                                                                   }

                                                                   if (m[a][yk[1][1]][k] == 0) {

                                                                              wb[a][yk[1][1]][k][i] = 1;

                                                                   }

                                                        }

                                             }

                                             for (k = 0; k < N; k++) {

                                                        if (k != xk[0][0] && k != xk[1][1]) {

                                                                   if (m[a][yk[0][0]][k] == 0) {

                                                                              局所解析関数(yk[0][0], k, a);

                                                                   }

                                                                   if (m[a][yk[1][1]][k] == 0) {

                                                                              局所解析関数(yk[1][1], k, a);

                                                                   }

                                                        }

                                             }

                                  }

                      }

           }

}

void リスト法関数(size_t a) {

           size_t i, j, k, s, t;

           for (i = 0; i < N; i++) {

                      for (j = 0; j < N; j++) {

                                  if (m[a][i][j] == 0) {

                                             if (mx[a][i][j] == 0) {

                                                        cn[a] = 2;

                                                        return;

                                             }

                                             if (mx[a][i][j] == 1) {

                                                        m[a][i][j] = rlst[a][i][j][0];

                                                        空欄数[a] = 空欄数[a] - 1;

                                                        if (空欄数[a] == 0)return;

                                                        for (k = 0; k < N; k++) {

                                                                   if (m[a][i][k] == 0) {

                                                                              wb[a][i][k][m[a][i][j] - 1] = 1;

                                                                   }

                                                                   if (m[a][k][j] == 0) {

                                                                              wb[a][k][j][m[a][i][j] - 1] = 1;

                                                                   }

                                                                   s = RN * (i / RN) + (k / RN);

                                                                   t = RN * (j / RN) + (k % RN);

                                                                   if (m[a][s][t] == 0) {

                                                                              wb[a][s][t][m[a][i][j] - 1] = 1;

                                                                   }

                                                        }

                                                        for (k = 0; k < N; k++) {

                                                                   if (m[a][i][k] == 0) 局所解析関数(i, k, a);

                                                                   if (m[a][k][j] == 0) 局所解析関数(k, j, a);

                                                                   s = RN * (i / RN) + (k / RN);

                                                                   t = RN * (j / RN) + (k % RN);

                                                                   if (m[a][s][t] == 0) 局所解析関数(s, t, a);

                                                        }

                                             }

                                  }

                      }

           }

}

void 非対称配列関数(size_t a) {

           size_t sss = rand() % (N * N);

           size_t rnk;

           size_t g = rand() % 12;

           if (g == 0)rnk = 7;

           if (g == 1)rnk = 11;

           if (g == 2)rnk = 13;

           if (g == 3)rnk = 17;

           if (g == 4)rnk = 19;

           if (g == 5)rnk = 23;

           if (g == 6)rnk = 29;

           if (g == 7)rnk = 31;

           if (g == 8)rnk = 37;

           if (g == 9)rnk = 41;

           if (g == 10)rnk = 43;

           if (g == 11)rnk = 47;

           for (size_t i = 0; i < N * N; i++) {

                      yy[a][i] = ((i * rnk + sss) % (N * N)) / N;

                      xx[a][i] = ((i * rnk + sss) % (N * N)) % N;

           }

}

void 左右対称配列関数(size_t a) {

           size_t ty, gz;

           if (ヒント数 % 2 == 0) {

                      gz = rand() % 5;

                      if (gz == 0)ty = 0;

                      if (gz > 0 && gz < 4)ty = 2;

                      if (gz == 4)ty = 4;

           }

           else {

                      gz = rand() % 7;

                      if (gz < 4)ty = 1;

                      if (gz > 3 && gz < 6)ty = 3;

                      if (gz == 6)ty = 5;

           }

           //ty = 2;

           size_t s = rand() % 11;

           size_t rnk;

           if (s == 0) rnk = 47;

           if (s == 1) rnk = 7;

           if (s == 2) rnk = 11;

           if (s == 3) rnk = 13;

           if (s == 4) rnk = 17;

           if (s == 5) rnk = 19;

           if (s == 6) rnk = 23;

           if (s == 7) rnk = 29;

           if (s == 8) rnk = 31;

           if (s == 9) rnk = 37;

           if (s == 10) rnk = 41;

           //rnk = 4;

           size_t ss = rand() % N;

           size_t sss = rand() % 36;

           for (size_t i = 0; i < (ヒント数 - ty) / 2; i++) {

                      xx[a][i] = ((i * rnk + sss) % 36) / N;

                      xx[a][ヒント数 - 1 - i] = 8 - xx[a][i];

                      yy[a][i] = ((i * rnk + sss) % 36) % N;

                      yy[a][ヒント数 - 1 - i] = yy[a][i];

           }

           size_t tyrnk;

           while (1) {

                      tyrnk = rand() % 6;

                      if (tyrnk > 2 && tyrnk % 3 != 0)break;

           }

           for (size_t i = 0; i < ty; i++) {

                      xx[a][i + (ヒント数 - ty) / 2] = 4;

                      yy[a][i + (ヒント数 - ty) / 2] = (i * tyrnk + ss) % N;

           }

}

void 上下対称配列関数(size_t a) {

           size_t ty, gz;

           if (ヒント数 % 2 == 0) {

                      gz = rand() % 5;

                      if (gz == 0)ty = 0;

                      if (gz > 0 && gz < 4)ty = 2;

                      if (gz == 4)ty = 4;

           }

           else {

                      gz = rand() % 7;

                      if (gz < 4)ty = 1;

                      if (gz > 3 && gz < 6)ty = 3;

                      if (gz == 6)ty = 5;

           }

           //ty = 2;

           size_t s = rand() % 11;

           size_t rnk;

           if (s == 0) rnk = 47;

           if (s == 1) rnk = 7;

           if (s == 2) rnk = 11;

           if (s == 3) rnk = 13;

           if (s == 4) rnk = 17;

           if (s == 5) rnk = 19;

           if (s == 6) rnk = 23;

           if (s == 7) rnk = 29;

           if (s == 8) rnk = 31;

           if (s == N) rnk = 37;

           if (s == 10) rnk = 41;

           //rnk = 4;

           size_t ss = rand() % N;

           size_t sss = rand() % 36;

           for (size_t i = 0; i < (ヒント数 - ty) / 2; i++) {

                      yy[a][i] = ((i * rnk + sss) % 36) / N;

                      yy[a][ヒント数 - 1 - i] = 8 - yy[a][i];

                      xx[a][i] = ((i * rnk + sss) % 36) % N;

                      xx[a][ヒント数 - 1 - i] = xx[a][i];

           }

           size_t tyrnk;

           while (1) {

                      tyrnk = rand() % 6;

                      if (tyrnk > 2 && tyrnk % 3 != 0)break;

           }

           for (size_t i = 0; i < ty; i++) {

                      yy[a][i + (ヒント数 - ty) / 2] = 4;

                      xx[a][i + (ヒント数 - ty) / 2] = (i * tyrnk + ss) % N;

           }

}

void 点対称配列関数(size_t a) {

           size_t s, rnk, sss;

           s = rand() % 11;

           if (s == 0) rnk = 47;

           if (s == 1) rnk = 7;

           if (s == 2) rnk = 11;

           if (s == 3) rnk = 13;

           if (s == 4) rnk = 17;

           if (s == 5) rnk = 19;

           if (s == 6) rnk = 23;

           if (s == 7) rnk = 29;

           if (s == 8) rnk = 31;

           if (s == 9) rnk = 53;

           if (s == 10) rnk = 61;

           while (1) {

                      s = rand() % (ヒント数 / N + 2);

                      if ((ヒント数 - s) % 2 == 0) break;

           }

           sss = rand() * 40;

           if (ヒント数 % 2 == 0) {

                      for (size_t i = 0; i < ヒント数 / 2; i++) {

                                  yy[a][i] = ((i * rnk + sss) % 40) / N;

                                  yy[a][ヒント数 - 1 - i] = 8 - yy[a][i];

                                  xx[a][i] = ((i * rnk + sss) % 40) % N;

                                  xx[a][ヒント数 - 1 - i] = 8 - xx[a][i];

                      }

           }

           else {

                      for (size_t i = 0; i < ヒント数 / 2; i++) {

                                  yy[a][i] = ((i * rnk + sss) % 40) / N;

                                  yy[a][ヒント数 - 1 - i] = 8 - yy[a][i];

                                  xx[a][i] = ((i * rnk + sss) % 40) % N;

                                  xx[a][ヒント数 - 1 - i] = 8 - xx[a][i];

                      }

                      yy[a][(ヒント数 - 1) / 2] = 4;

                      xx[a][(ヒント数 - 1) / 2] = 4;

           }

}

void 左右上下対称配列関数(size_t a) {

           size_t sss, b, rnk, s, mns;

           size_t kh[16];

           if (ヒント数 % 2 == 0) {

                      if (ヒント数 % 4 == 0) {

                                  s = rand() % 5;

                                  if (s == 0) rnk = 3;

                                  if (s == 1) rnk = 5;

                                  if (s == 2) rnk = 7;

                                  if (s == 3) rnk = 11;

                                  if (s == 4) rnk = 13;

                                  sss = rand() % 16;

                                  b = ヒント数 / 4 - 1;

                                  for (size_t i = 0; i < b + 1; i++) {

                                             kh[i] = (sss + rnk * i) % 16;

                                  }

                                  for (size_t i = 0; i < b + 1; i++) {

                                             yy[a][i] = kh[i] / 4;

                                             xx[a][i] = kh[i] % 4;

                                             yy[a][2 * (b + 1) - i - 1] = yy[a][i];

                                             xx[a][2 * (b + 1) - i - 1] = 8 - xx[a][i];

                                             yy[a][3 * (b + 1) - i - 1] = 8 - yy[a][i];

                                             xx[a][3 * (b + 1) - i - 1] = xx[a][i];

                                             yy[a][4 * (b + 1) - i - 1] = 8 - yy[a][i];

                                             xx[a][4 * (b + 1) - i - 1] = 8 - xx[a][i];

                                  }

                                  return;

                      }

                      s = rand() % 3;

                      if (s < 2) mns = 1; else mns = 3;

                      s = rand() % 4;

                      for (size_t i = 0; i < mns + 1; i++) {

                                  xx[a][i] = 4;

                                  xx[a][2 * mns - 1 - i] = 4;

                                  yy[a][i] = (s + 3 * i) % 4;

                                  yy[a][2 * mns - 1 - i] = 8 - yy[a][i];

                      }

                      b = (ヒント数 - 2 * mns) / 4 - 1;

                      s = rand() % 5;

                      if (s == 0) rnk = 3;

                      if (s == 1) rnk = 5;

                      if (s == 2) rnk = 7;

                      if (s == 3) rnk = 11;

                      if (s == 4) rnk = 13;

                      sss = rand() % 16;

                      for (size_t i = 0; i < b + 1; i++) {

                                  kh[i] = (sss + rnk * i) % 16;

                      }

                      for (size_t i = 0; i < b + 1; i++) {

                                  yy[a][2 * mns + i] = kh[i] / 4;

                                  xx[a][2 * mns + i] = kh[i] % 4;

                                  yy[a][2 * mns + 2 * (b + 1) - i - 1] = yy[a][2 * mns + i];

                                  xx[a][2 * mns + 2 * (b + 1) - i - 1] = 8 - xx[a][2 * mns + i];

                                  yy[a][2 * mns + 3 * (b + 1) - i - 1] = 8 - yy[a][2 * mns + i];

                                  xx[a][2 * mns + 3 * (b + 1) - i - 1] = xx[a][2 * mns + i];

                                  yy[a][2 * mns + 4 * (b + 1) - i - 1] = 8 - yy[a][2 * mns + i];

                                  xx[a][2 * mns + 4 * (b + 1) - i - 1] = 8 - xx[a][2 * mns + i];

                      }

                      return;

           }

           if (ヒント数 % 2 == 1) {

                      xx[a][0] = 4;

                      yy[a][0] = 4;

                      if (((ヒント数 - 1) % 4) == 0) {

                                  s = rand() % 5;

                                  if (s == 0) rnk = 3;

                                  if (s == 1) rnk = 5;

                                  if (s == 2) rnk = 7;

                                  if (s == 3) rnk = 11;

                                  if (s == 4) rnk = 13;

                                  sss = rand() % 16;

                                  b = (ヒント数 - 1) / 4 - 1;

                                  for (size_t i = 0; i < b + 1; i++) {

                                             kh[i] = (sss + rnk * i) % 16;

                                  }

                                  for (size_t i = 0; i < b + 1; i++) {

                                             yy[a][1 + i] = kh[i] / 4;

                                             xx[a][1 + i] = kh[i] % 4;

                                             yy[a][1 + 2 * (b + 1) - i - 1] = yy[a][1 + i];

                                             xx[a][1 + 2 * (b + 1) - i - 1] = 8 - xx[a][1 + i];

                                             yy[a][1 + 3 * (b + 1) - i - 1] = 8 - yy[a][1 + i];

                                             xx[a][1 + 3 * (b + 1) - i - 1] = xx[a][1 + i];

                                             yy[a][1 + 4 * (b + 1) - i - 1] = 8 - yy[a][1 + i];

                                             xx[a][1 + 4 * (b + 1) - i - 1] = 8 - xx[a][1 + i];

                                  }

                                  return;

                      }

                      s = rand() % 3;

                      if (s < 2) mns = 1; else mns = 3;

                      s = rand() % 4;

                      mns = 3;

                      for (size_t i = 0; i < mns; i++) {

                                  xx[a][1 + i] = 4;

                                  xx[a][1 + 2 * mns - 1 - i] = 4;

                                  yy[a][1 + i] = (s + 3 * i) % 4;

                                  yy[a][1 + 2 * mns - 1 - i] = 8 - yy[a][1 + i];

                      }

                      b = (ヒント数 - 1 - 2 * mns) / 4 - 1;

                      s = rand() % 4;

                      if (s == 0) rnk = 3;

                      if (s == 1) rnk = 5;

                      if (s == 2) rnk = 7;

                      if (s == 3) rnk = 11;

                      sss = rand() % 16;

                      for (size_t i = 0; i < b + 1; i++) {

                                  kh[i] = (sss + rnk * i) % 16;

                      }

                      for (size_t i = 0; i < b + 1; i++) {

                                  yy[a][1 + 2 * mns + i] = kh[i] / 4;

                                  xx[a][1 + 2 * mns + i] = kh[i] % 4;

                                  yy[a][1 + 2 * mns + 2 * (b + 1) - i - 1] = yy[a][1 + 2 * mns + i];

                                  xx[a][1 + 2 * mns + 2 * (b + 1) - i - 1] = 8 - xx[a][1 + 2 * mns + i];

                                  yy[a][1 + 2 * mns + 3 * (b + 1) - i - 1] = 8 - yy[a][1 + 2 * mns + i];

                                  xx[a][1 + 2 * mns + 3 * (b + 1) - i - 1] = xx[a][1 + 2 * mns + i];

                                  yy[a][1 + 2 * mns + 4 * (b + 1) - i - 1] = 8 - yy[a][1 + 2 * mns + i];

                                  xx[a][1 + 2 * mns + 4 * (b + 1) - i - 1] = 8 - xx[a][1 + 2 * mns + i];

                      }

           }

}

void ハート型配列関数(size_t a) {

           size_t b[N - 1][N - 1];

           for (size_t i = 0; i < 5; i++) {

                      yy[a][i] = 8 - i;

                      xx[a][i] = 4 - i;

           }

           for (size_t i = 5; i < N; i++) {

                      yy[a][i] = yy[a][i - 4];

                      xx[a][i] = 8 - xx[a][i - 4];

           }

           yy[a][N] = 3;

           xx[a][N] = 0;

           yy[a][10] = 3;

           xx[a][10] = 8;

           for (size_t i = 11; i < 13; i++) {

                      yy[a][i] = 13 - i;

                      xx[a][i] = i - 11;

                      yy[a][i + 2] = yy[a][i];

                      xx[a][i + 2] = 8 - xx[a][i];

           }

           for (size_t i = 15; i < 17; i++) {

                      yy[a][i] = i - 14;

                      xx[a][i] = i - 13;

                      yy[a][i + 2] = yy[a][i];

                      xx[a][i + 2] = 8 - xx[a][i];

           }

           yy[a][19] = 3;

           xx[a][19] = 4;

           for (size_t i = 0; i < 20; i++) {

                      b[yy[a][i]][xx[a][i]] = 10;

           }

           size_t sa, h;

           sa = ヒント数 - 20;

           for (size_t i = 1; i < 8; i++) {

                      h = 0;

                      for (size_t j = 1; j < N; j++) {

                                  if (b[j - 1][i] == 10)  h = h + 1;

                                  if (h == 1 && b[j][i] != 10)  b[j][i] = 3;

                      }

           }

           size_t k, i, j;

           if (ヒント数 % 2 == 0) {

                      for (size_t k = 20; k < 20 + sa / 2; k++) {

                                  while (1) {

                                             i = rand() % N;

                                             j = rand() % 4;

                                             if (b[i][j] == 3) {

                                                        b[i][j] = 4;

                                                        b[i][8 - j] = 4;

                                                        yy[a][k] = i;

                                                        xx[a][k] = j;

                                                        yy[a][k + sa / 2] = i;

                                                        xx[a][k + sa / 2] = 8 - j;

                                                        break;

                                             }

                                  }

                      }

                      return;

           }

           else {

                      while (1) {

                                  j = 4 + rand() % 4;

                                  if (b[j][4] == 3) {

                                             b[j][4] = 4;

                                             yy[a][20] = j;

                                             xx[a][20] = 4;

                                             break;

                                  }

                      }

                      if (ヒント数 > 21) {

                                  for (size_t i = 21; i < 21 + (ヒント数 - 21) / 2; i++) {

                                             size_t s, t;

                                             while (1) {

                                                        s = rand() % N;

                                                        t = rand() % 4;

                                                        if (b[s][t] == 3) {

                                                                   b[s][t] = 4;

                                                                   b[s][8 - t] = 4;

                                                                   yy[a][i] = s;

                                                                   xx[a][i] = t;

                                                                   yy[a][i + (ヒント数 - 21) / 2] = s;

                                                                   xx[a][i + (ヒント数 - 21) / 2] = 8 - t;

                                                                   break;

                                                        }

                                             }

                                  }

                      }

           }

}

void 代入関数(size_t a) {

           for (size_t i = 0; i < N2; i++) {

                      cm[a][yy[a][i]][xx[a][i]] = m[a][yy[a][i]][xx[a][i]];

           }

}

void 問題作成関数(size_t a) {

           初期化1(a);

           for (size_t i = 0; i < ヒント数; i++) {

                      size_t s, t;

                      s = yy[a][i];

                      t = xx[a][i];

                      m[a][s][t] = cm[a][s][t];

                      for (size_t j = 0; j < N; j++) {

                                  if (m[a][s][j] == 0) {

                                             if (wb[a][s][j][m[a][s][t] - 1] == 0) {

                                                        wb[a][s][j][m[a][s][t] - 1] = 1;

                                             }

                                  }

                      }

                      for (size_t j = 0; j < N; j++) {

                                  if (m[a][j][t] == 0) {

                                             if (wb[a][j][t][m[a][s][t] - 1] == 0) {

                                                        wb[a][j][t][m[a][s][t] - 1] = 1;

                                             }

                                  }

                      }

                      for (size_t j = 0; j < N; j++) {

                                  size_t p, q;

                                  p = RN * (s / RN) + (j / RN);

                                  q = RN * (t / RN) + (j % RN);

                                  if (p != s && q != t) {

                                             if (m[a][p][q] == 0) {

                                                        if (wb[a][p][q][m[a][s][t] - 1] == 0) {

                                                                   wb[a][p][q][m[a][s][t] - 1] = 1;

                                                        }

                                             }

                                  }

                      }

           }

           for (size_t i = 0; i < N; i++) {

                      for (size_t j = 0; j < N; j++) {

                                  if (m[a][i][j] == 0)局所解析関数(i, j, a);

                      }

           }

}

void 初期化0(size_t a) {

           for (size_t i = 0; i < N; i++) {

                      for (size_t j = 0; j < N; j++) {

                                  m[a][i][j] = 0;

                                  cm[a][i][j] = 0;

                                  mx[a][i][j] = N;

                                  for (size_t k = 0; k < N; k++) {

                                             wb[a][i][j][k] = 0;

                                  }

                      }

           }

}

void 初期化1(size_t a) {

           cn[a] = 0;

           空欄数[a] = N2 - ヒント数;

           hj1[a] = clock();

           for (size_t i = 0; i < N; i++) {

                      for (size_t j = 0; j < N; j++) {

                                  m[a][i][j] = 0;

                                  //cm[a][i][j] = 0;

                                  mx[a][i][j] = N;

                                  for (size_t k = 0; k < N; k++) {

                                             wb[a][i][j][k] = 0;

                                  }

                      }

           }

}

void 入力順決定関数(size_t g, size_t a) {

           size_t ik, jk, mn = 1000;

           for (size_t i = 0; i < N; i++) {

                      for (size_t j = 0; j < N; j++) {

                                  if (m[a][i][j] == 0) {

                                             if (mx[a][i][j] <= mn) {

                                                        mn = mx[a][i][j];

                                                        ik = i;

                                                        jk = j;

                                             }

                                  }

                      }

           }

           y[a][g] = ik;

           x[a][g] = jk;

           局所解析関数(ik, jk, a);

}

void 問題生成関数(size_t g, size_t a) {

           size_t i, j, s, t, p, q, ii, iii, k;

           size_t gy[N], r[N], b[N];

           if (g < 初期配置数) {

                      s = yy[a][g];

                      t = xx[a][g];

                      局所解析関数(s, t, a);

           }

           else {

                      入力順決定関数(g, a);

                      s = y[a][g];

                      t = x[a][g];

                      局所解析関数(s, t, a);

           }

           if (mx[a][s][t] == 0)return;

           ii = rand() % mx[a][s][t];

           if (cn[a] == 1)return;

           if (継続 == 0)return;

           for (i = 0; i < mx[a][s][t]; i++) {

                      iii = (i + ii) % mx[a][s][t];

                      m[a][s][t] = rlst[a][s][t][iii];

                      for (j = 0; j < N; j++) {

                                  gy[j] = 0;

                                  r[j] = 0;

                                  b[j] = 0;

                      }

                      for (j = 0; j < N; j++) {

                                  if (m[a][s][j] == 0) {

                                             if (wb[a][s][j][m[a][s][t] - 1] == 0) {

                                                        wb[a][s][j][m[a][s][t] - 1] = 1;

                                                        局所解析関数(s, j, a);

                                                        r[j] = 1;

                                             }

                                  }

                      }

                      for (j = 0; j < N; j++) {

                                  if (m[a][j][t] == 0) {

                                             if (wb[a][j][t][m[a][s][t] - 1] == 0) {

                                                        wb[a][j][t][m[a][s][t] - 1] = 1;

                                                        局所解析関数(j, t, a);

                                                        gy[j] = 1;

                                             }

                                  }

                      }

                      for (j = 0; j < N; j++) {

                                  p = RN * (s / RN) + (j / RN);

                                  q = RN * (t / RN) + (j % RN);

                                  if (p != s && q != t) {

                                             if (m[a][p][q] == 0) {

                                                        if (wb[a][p][q][m[a][s][t] - 1] == 0) {

                                                                   wb[a][p][q][m[a][s][t] - 1] = 1;

                                                                   局所解析関数(p, q, a);

                                                                   b[j] = 1;

                                                        }

                                             }

                                  }

                      }

                      if (継続 == 0)return;

                      if (g + 1 < N2) {

                                  問題生成関数(g + 1, a);

                                  if (cn[a] == 1)return;

                                  if (継続 == 0)return;

                      }

                      else {

                                  代入関数(a);

                                  cn[a]++;

                                  if (cn[a] == 1)return;

                                  if (継続 == 0)return;

                      }

                      for (j = 0; j < N; j++) {

                                  if (r[j] == 1) {

                                             wb[a][s][j][m[a][s][t] - 1] = 0;

                                  }

                                  if (gy[j] == 1) {

                                             wb[a][j][t][m[a][s][t] - 1] = 0;

                                  }

                                  p = RN * (s / RN) + (j / RN);

                                  q = RN * (t / RN) + (j % RN);

                                  if (b[j] == 1) {

                                             wb[a][p][q][m[a][s][t] - 1] = 0;

                                  }

                      }

           }

           m[a][s][t] = 0;

           return;

}

void 局所解析関数(size_t s, size_t t, size_t a) {

           //セルの候補数字を探索する関数

           size_t w = 0;

           for (size_t i = 0; i < N; i++) {

                      if (wb[a][s][t][i] == 0) {

                                  rlst[a][s][t][w] = i + 1;

                                  w++;

                      }

           }

           mx[a][s][t] = w;//候補数字数

}

size_t 検証関数(size_t a) {

           size_t p[N];

           //以下行部分に重複がないか調べている。ある場合は0を返す。

           for (size_t i = 0; i < N; i++) {

                      for (size_t j = 0; j < N; j++) {

                                  p[j] = 0;

                      }

                      for (size_t j = 0; j < N; j++) {

                                  p[m[a][i][j] - 1] = 1;

                      }

                      for (size_t j = 0; j < N; j++) {

                                  if (p[j] == 0)return(0);

                      }

           }

           //以下は列部分に重複がないかを知べている。ある場合は0を返す。

           for (size_t i = 0; i < N; i++) {

                      for (size_t j = 0; j < N; j++) {

                                  p[j] = 0;

                      }

                      for (size_t j = 0; j < N; j++) {

                                  p[m[a][j][i] - 1] = 1;

                      }

                      for (size_t j = 0; j < N; j++) {

                                  if (p[j] == 0)return(0);

                      }

           }

           //以下はブロック部分に重複がないかを調べている。ある場合は0を返す。

           for (size_t i = 0; i < N; i++) {

                      for (size_t j = 0; j < N; j++) {

                                  p[j] = 0;

                      }

                      for (size_t j = 0; j < N; j++) {

                                  size_t s, t;

                                  s = RN * (i / RN) + (j / RN);//ブロック内を動くy座標(通常とは逆方向を

                                  //向いていることに注意)

                                  t = RN * (i % RN) + (j % RN);//ブロック内を動くx座標

                                  p[m[a][s][t] - 1] = 1;

                      }

                      for (size_t j = 0; j < N; j++) {

                                  if (p[j] == 0)return(0);

                      }

           }

           return(1);//行・列・ブロックに重複がないときにはじめて1を返している。

}