数独の正解図をランダムに作る

1つの数字に着目して、3×3のブロックごとに配置できる可能性を考えていくと
9*6*3*6*4*2*3*2*1 = 46656通りある。
まずは事前にそれをすべて書き出すことにする。
(過去にやったのでそのまま流用)
touch-sp.hatenablog.com

036147258
036147285
036147528
036147582
・
・
・

46656個の文字列(9文字)から1文字目、2文字目、3文字目・・・とすべて重複しないようにランダムに9個抽出することが今回のストラテジーである。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> mylist = new List<string>();

            using (System.IO.StreamReader file = new System.IO.StreamReader("resource.txt"))
            {
                string line = "";
                // test.txtを1行ずつ読み込んでいき、末端(何もない行)までwhile文で繰り返す
                while ((line = file.ReadLine()) != null)
                {
                    mylist.Add(line);
                }
            }

            string[] b = new string[9];
            int[] kazu = new int[81];

            int[] start_position = { 0, 3, 6, 27, 30, 33, 54, 57, 60 };
            int[] next_position = { 0, 1, 2, 9, 10, 11, 18, 19, 20 };

            List<string> result = new List<string>();

            Stopwatch sw = new Stopwatch();
            sw.Start();

            for (int mycount = 0; mycount < 40000; mycount++)
            {
                string[] a = new string[9];
                System.Random r = new System.Random();
                int rnd = r.Next(46656);
                a[0] = mylist[rnd];

                List<string> mylist2 = mylist.Where(c => hantei(a[0],c)).ToList();

                System.Random r2 = new System.Random();
                rnd = r2.Next(mylist2.Count());
                a[1] = mylist2[rnd];

                List<string> mylist3 = mylist2.Where(c => hantei(a[1], c)).ToList();

                System.Random r3 = new System.Random();
                rnd = r3.Next(mylist3.Count());
                a[2] = mylist3[rnd];

                List<string> mylist4 = mylist3.Where(c => hantei(a[2], c)).ToList();

                b = Try(a, mylist4);
                
                for (int i = 0; i < 9; i++)
                {
                    for (int ii = 0; ii < 9; ii++)
                    {
                        int position = start_position[ii] + next_position[(int)char.GetNumericValue(b[i][ii])];
                        kazu[position] = i + 1;
                    }
                }
                string sdData = string.Join("", kazu);
                result.Add(sdData);
            }
            
            System.IO.File.WriteAllLines(@"sudoku_answer.txt", result);

            sw.Stop();
            Console.WriteLine(sw.Elapsed.ToString());
            Console.WriteLine("finish...");
            Console.ReadLine();
        }
        static bool hantei(string x, string y)
        {
            for(int i = 0; i < 9; i++)
            {
                if (x[i] == y[i])
                {
                    return false;
                }
            }
            return true;
        }
        static string[] Try(string[] a, List<string> mylist)
        {
            //0(空欄)を探す→存在しない場合には-1を返す
            int blank = Array.IndexOf(a, null);
            if (blank != -1)
            {
                var ary = Enumerable.Range(0, mylist.Count()).ToArray();
                int[] ary2 = ary.OrderBy(t => Guid.NewGuid()).ToArray();

                for (int i = 0; i < mylist.Count(); i++)
                {   
                    if (isOK(blank, mylist[ary2[i]], a))
                    {
                        a[blank] = mylist[ary2[i]];
                        Try(a, mylist);
                        int blank2 = Array.IndexOf(a, null);
                        if (blank2 == -1)
                        {
                            break;
                        }
                        a[blank] = null;
                    }
                }
            }
            return a;
        }
        static bool isOK(int x, string L, string[] a)
        {
            for(int i = 0; i < x; i++)
            {
                for (int indx = 0; indx < 9; indx++)
                {
                    if (L[indx] == a[i][indx])
                    {
                        return false;
                    }
                }
            }
            return true;
        }
    }
}
  1. まず一つ目をランダムに選択
  2. その後選択できるリストを絞り込む
  3. 二つ目をランダムに選択
  4. 再度選択できるリストを絞り込む
  5. 3つ目をランダムに選択
  6. 再再度選択できるリストを絞り込む
  7. 残りの6つはバックトラック法で選択
  8. 最初に戻り同様のことを繰り返す

ただし、通常のバックトラック法ではすべての解を見つけてしまうため、ここでは1つの解が見つかった時点で多重ループを抜けるように工夫してある。
以下の環境で40000個作るのに14分かかった。速いのか遅いのか?

Windows 10 Pro
Visual Studio 2017
Intel(R) Core(TM) i7-4600U CPU @2.10GHz 2.69GHz
RAM:8.0GB