সি ++
আমি এখানে যা উপস্থাপন করব তা হল একটি অ্যালগরিদম, 3x3 কেসের উদাহরণ সহ চিত্রিত। এটি তাত্ত্বিকভাবে এনএক্সএন ক্ষেত্রে বাড়ানো যেতে পারে তবে এর জন্য আরও অনেক শক্তিশালী কম্পিউটার এবং / অথবা কিছু উদ্ভাবনী টুইট দরকার হবে। আমি যখন যাচ্ছি তখন কিছু উন্নতির উল্লেখ করব।
আরও যাবার আগে আসুন সুডোকু গ্রিডের প্রতিসাম্যগুলি লক্ষ্য করুন, অর্থাত্ ট্রান্সফর্মেশন যা অপ্রয়োজনীয় উপায়ে অন্য গ্রিডের দিকে পরিচালিত করে। ব্লকের আকার 3 এর জন্য প্রতিসারণগুলি নিম্নরূপ:
অনুভূমিক প্রতিসাম্য
**The N=3 sudoku is said to consist of 3 "bands" of 3 "rows" each**
permute the three bands: 3! permutations = 6
permute the rows in each band: 3 bands, 3! permutations each =(3!)^3=216
উল্লম্ব প্রতিসাম্য
**The N=3 sudoku is said to consist of 3 "stacks" of 3 "columns" each.**
the count is the same as for horizontal.
নোট করুন যে গ্রিডের অনুভূমিক এবং উল্লম্ব প্রতিচ্ছবিগুলি এর সংমিশ্রণে অর্জন করা যায়, তাই তাদের গণনা করার দরকার নেই। আরও একটি স্থানিক প্রতিসাম্যতা বিবেচনা করা দরকার, যা ট্রান্সপোসিং হচ্ছে, এটি একটি ফ্যাক্টর 2
। এটির মোট স্থানগত প্রতিসাম্যতা দেয়
2*(N!*(N!)^N)^2 = 2*(6*216)^2=3359232 spatial symmetries for the case N=3.
তারপরে আর একটি, খুব গুরুত্বপূর্ণ প্রতিসাম্য, যার নাম রিলেবেলিং।
Relabelling gives a further (N^2)!=9!=362880 symmetries for the case N=3. So the total
number of symmetries is 362880*3359232=1218998108160.
এই সংখ্যার দ্বারা প্রতিসম-অনন্য সমাধানের সংখ্যাটি কেবলমাত্র সমাধানের মোট সংখ্যা খুঁজে পাওয়া যায় না, কারণ অটোমোরফিক সমাধানগুলির একটি সংখ্যা (1% এরও কম) রয়েছে। এর অর্থ এই যে বিশেষ সমাধানগুলির জন্য একটি প্রতিসৃত অপারেশন রয়েছে যা সেগুলি তাদের নিজের কাছে মানচিত্র করে তোলে বা একাধিক প্রতিসাম্য ক্রিয়াকলাপ যা তাদেরকে একই অন্যান্য সমাধানে ম্যাপ করে।
সমাধানের সংখ্যাটি অনুমান করার জন্য, আমি 4 টি ধাপে সমস্যার সাথে যোগাযোগ করি:
1. r[362880][12]
0 থেকে 8 সংখ্যার সমস্ত সম্ভাব্য ক্রম দিয়ে একটি অ্যারে পূরণ করুন (এটি প্রোগ্রামিং, এবং এটি সিতে রয়েছে, সুতরাং আমরা 1 থেকে 9 ব্যবহার করব না) আপনি যদি অবাক হন তবে আপনি লক্ষ্য করবেন যে দ্বিতীয় সাবস্ক্রিপ্ট এটি নয়, এটি নয়, কারণ এটি করার সময়, মনে রাখবেন যে আমরা এটিকে একটি "সারি" হিসাবে বিবেচনা করতে যাচ্ছি আমরা আরও তিনটি পূর্ণসংখ্যা গণনা করি r[9,10,11] == 1<<a | 1<<b | 1<<c
যেখানে 9,10,11 প্রথম, দ্বিতীয় এবং তৃতীয় স্ট্যাকের উল্লেখ করে এবং a, b, c হল এই সারির প্রতিটি স্ট্যাকের তিনটি সংখ্যা।
b
২ সারির একটি ব্যান্ডের সমস্ত সম্ভাব্য সমাধান সহ একটি অ্যারে পূরণ করুন । এটি যুক্তিসঙ্গতভাবে ছোট রাখতে, কেবল সেই সমাধানগুলি অন্তর্ভুক্ত করুন যেখানে শীর্ষ সারি 012,345,678 8 আমি নিষ্ঠুর বল দ্বারা, সমস্ত সম্ভাব্য মধ্যম সারিগুলি তৈরি করে এবং এ্যান্ডিংয়ের r[0][10,11,12]
মাধ্যমে এটি করি r[i][10,11,12]
। যে কোনও ধনাত্মক মান মানে একই স্কোয়ারে দুটি অভিন্ন সংখ্যা রয়েছে এবং ব্যান্ডটি অবৈধ। প্রথম দুটি সারিটির জন্য যখন একটি বৈধ সংমিশ্রণ থাকে, আমি একই কৌশল দিয়ে তৃতীয় (নীচে) সারিটি অনুসন্ধান করি।
আমি অ্যারেটিকে বি [2000000] [9] হিসাবে মাত্রিক আকার দিয়েছি কিন্তু প্রোগ্রামটি কেবল 1306368 সমাধান খুঁজে পেয়েছে। আমি জানি না যে সেখানে কত ছিল, তাই আমি অ্যারের মাত্রাটি এর মতো রেখে দিয়েছি। এটি আসলে একটি একক ব্যান্ডের জন্য কেবলমাত্র অর্ধেক সম্ভাব্য সমাধান (উইকিপিডিয়ায় যাচাই করা হয়েছে), কারণ আমি কেবলমাত্র বর্তমান মান থেকে i
উপরের দিকে তৃতীয় সারির স্ক্যান করি । সমাধানগুলির অর্ধেকটি তৃতীয় এবং তৃতীয় সারির বিনিময় দ্বারা তুচ্ছভাবে খুঁজে পাওয়া যায়।
অ্যারেতে যেভাবে তথ্য সংরক্ষণ করা হয় b
তা প্রথমে কিছুটা বিভ্রান্তিকর। 0..8
প্রদত্ত অবস্থানে পাওয়া সংখ্যাগুলি সংরক্ষণ করতে প্রতিটি পূর্ণসংখ্যা ব্যবহার করার পরিবর্তে , এখানে প্রতিটি পূর্ণসংখ্যার একটির সংখ্যা বিবেচনা 0..8
করে এবং এটি চিহ্নিত করে যে এটি কলামগুলিতে পাওয়া যাবে। এইভাবে b[x][7]==100100001
ইঙ্গিত দেয় যে সমাধানের জন্য x 7 নম্বরটি 0,5 এবং 8 (ডান থেকে বাম দিকে) কলামগুলিতে পাওয়া যায় this উপস্থাপনা এটি করতে সুবিধাজনক করে তোলে।
উপরের দুটি পদক্ষেপটি সেটআপটিকে অন্তর্ভুক্ত করে এবং প্রায় এক মিনিট সময় নেয় (আমি অপ্রয়োজনীয় ডেটা আউটপুট সরিয়ে ফেললে সম্ভবত কম কম less নীচের দুটি পদক্ষেপই প্রকৃত অনুসন্ধান search
3 প্রথম দুটি ব্যান্ডের সংঘাত না ঘটে এর জন্য সমাধানের জন্য এলোমেলোভাবে অনুসন্ধান করুন (যেমন প্রদত্ত কলামে দু'বার একই সংখ্যা নেই always আমরা ব্যান্ড 1 এর জন্য একটি র্যান্ডম সলিউশনটি বেছে নিই, সর্বদা ক্রমান্বন 0, এবং সাথে ব্যান্ড 2 এর জন্য একটি র্যান্ডম সলিউশন বেছে নিই with একটি এলোমেলো অনুগমন। ফলাফলটি সাধারণত 9999 টিরও কম চেষ্টাতে পাওয়া যায় (প্রথম ধাপের হিট রেট হাজার রেঞ্জে) এবং এক সেকেন্ডের একটি ভগ্নাংশ নেয় perm অনুমানের মাধ্যমে, আমি বলতে চাই যে দ্বিতীয় ব্যান্ডের জন্য আমরা খ থেকে সমাধান নিই [] [] যেখানে প্রথম সারিতে সর্বদা 012,345,678 থাকে এবং এটিকে পুনরায় বিলোপ দেয় যাতে প্রথম সারিতে সংখ্যার যে কোনও সম্ভাব্য ক্রম সম্ভব হয়।
4 যখন পদক্ষেপ 3 এ হিট পাওয়া যায়, তখন তৃতীয় ব্যান্ডের জন্য একটি সমাধান অনুসন্ধান করুন যা অন্য দুটির সাথে সংঘর্ষ না করে। আমরা কেবল একটি চেষ্টা করতে চাই না, অন্যথায় 3 ধাপের প্রসেসিংয়ের সময় নষ্ট হবে। অন্যদিকে আমরা এর মধ্যে একটি প্রচুর পরিমাণে প্রচেষ্টা রাখতে চাই না।
কেবল মজাদার জন্য, গত রাতে আমি এটি সম্ভব সবচেয়ে দু: খজনক উপায়ে করেছি, তবে এটি এখনও আকর্ষণীয় ছিল (কারণ এটি যুগে যুগে কিছুই ছিল না, তারপরে বিস্ফোরণে বিপুল সংখ্যক সমাধান পাওয়া গেল dat) একটি ছোট্ট হ্যাক এমনকি একটি ডেটাপয়েন্ট পেতে সারা রাত লেগেছিল even (!z)
আমি শেষ k
লুপটি বাতিল করতে পেরেছিলাম যত তাড়াতাড়ি আমরা জানতে পারি এটি কোনও বৈধ সমাধান নয় (এটি এটি প্রায় 9 গুণ দ্রুত চালায়)) এটি শেষ গ্রিডের জন্য 1186585 সমাধানগুলি খুঁজে পেয়েছিল সবশেষে 1303068 ক্যানোনিকাল সমাধানগুলির সমস্ত 362880 রিলেবিলিং অনুসন্ধান করার পরে ব্লক, মোট 474054819840 সম্ভাবনা। দ্বিতীয় পর্যায়ে এটি 400000 সালে 1 এর হিট রেট। আমি স্ক্যানের চেয়ে এলোমেলো অনুসন্ধানের সাথে শীঘ্রই আবার চেষ্টা করব। এটি কয়েক মিলিয়ন চেষ্টা করে একটি যুক্তিসঙ্গত উত্তর দেওয়া উচিত, যা কেবল কয়েক সেকেন্ড সময় নেয়।
সামগ্রিক উত্তরটি হওয়া উচিত (362880 * (1306368 * 2)) ^ 3 * হিট রেট = 8.5E35 * হিট রেট। প্রশ্নের নম্বর থেকে ফিরে গণনা করে, আমি 1 / 1.2E14 এর হিট রেট আশা করি। আমার একক ডেটাপয়েন্টের সাথে এখন পর্যন্ত আমি যা পেয়েছি তা হ'ল 1 / (400000 * 1000) যা প্রায় দশ মিলিয়ন এর ফ্যাক্টর দ্বারা প্রকাশিত। এটি সুযোগের অসাধারণতা, আমার প্রোগ্রামে একটি ত্রুটি বা আমার গণিতে একটি ত্রুটি হতে পারে। আমি আরও কিছু পরীক্ষা চালানো না হওয়া পর্যন্ত এটি কোনটি তা আমি জানি না।
আমি আজ রাতের জন্য এই এখানে রাখব। পাঠ্যটি কিছুটা চূর্ণবিচূর্ণ, আমি শীঘ্রই এটিকে পরিস্কার করব এবং আশা করছি আরও কিছু ফলাফল যুক্ত করব এবং কীভাবে এটি আরও দ্রুত করা যায় এবং কীভাবে ধারণাটি এন = 4 এ প্রসারিত করা যায় সে সম্পর্কে কয়েকটি শব্দ। আমি মনে করি না যে আমি আমার প্রোগ্রামে আরও অনেক পরিবর্তন করব, যদিও :-)
আহ .. প্রোগ্রাম:
#include "stdafx.h"
#define _CRT_RAND_S
#include <algorithm>
#include <time.h>
unsigned int n[] = { 0,1,2,3,4,5,6,7,8 }, r[362880][12], b[2000000][9],i,j,k,l,u,v,w,x,y,z;
int main () {
//Run through all possible permutations of n[] and load them into r[][]
i=0;
do {
r[i][9] = r[i][10] = r[i][11]=0;
for (l = 0; l < 9; l++){
r[i][l] = n[l];
r[i][9 + l / 3] |= 1 << n[l];
}
if((i+1)%5040==0) printf("%d%d%d %d%d%d %d%d%d %o %o %o %o \n"
,r[i][0],r[i][1],r[i][2],r[i][3],r[i][4],r[i][5],r[i][6],r[i][7],r[i][8],r[i][9],r[i][10],r[i][11],r[i][9]+r[i][10]+r[i][11]);
i++;
} while ( std::next_permutation(n,n+9) );
//Initialise b[][]
for (l = 0; l<2000000; l++) for (k = 0; k<9; k++) b[l][k]=0;
//fill b[][] with all solutions of the first band, where row0 ={0,1,2,3,4,5,6,7,8} and row1<row2
l=0;
for (i = 0; i<362880; i++)
if (!(r[0][9] & r[i][9] | r[0][10] & r[i][10] | r[0][11] & r[i][11])){printf("%d %d \n",i,l);
for (j=i; j<362880;j++)
if(!(r[0][9]&r[j][9] | r[0][10]&r[j][10] | r[0][11]&r[j][11] | r[j][9]&r[i][9] | r[j][10]&r[i][10] | r[j][11]&r[i][11] )){
for (k = 0; k < 9; k++){
b[l][r[0][k]]|=1<<k;
b[l][r[i][k]]|=1<<k;
b[l][r[j][k]]|=1<<k;
}
l++;
}
// printf("%d%d%d %d%d%d %d%d%d %o %o %o %o \n"
// ,r[i][0],r[i][1],r[i][2],r[i][3],r[i][4],r[i][5],r[i][6],r[i][7],r[i][8],r[i][9],r[i][10],r[i][11],r[i][9]+r[i][10]+r[i][11]);
// printf("%d%d%d %d%d%d %d%d%d %o %o %o %o \n"
// ,r[j][0],r[j][1],r[j][2],r[j][3],r[j][4],r[j][5],r[j][6],r[j][7],r[j][8],r[j][9],r[j][10],r[j][11],r[j][9]+r[j][10]+r[j][11]);
// printf("%d %d %o %o %o %o %o %o %o %o %o \n",i,l,b[l][0],b[l][1],b[l][2],b[l][3],b[l][4],b[l][5],b[l][6],b[l][7],b[l][8]);
}
// find a random solution for the first 2 bands
l=0;
do{
rand_s(&u); u /= INT_MIN / -653184; //1st band selection
rand_s(&v); v /= INT_MIN / -181440; //2nd band permutation
rand_s(&w); w /= INT_MIN / -653184; //2nd band selection
z = 0;
for (k = 0; k < 9; k++) z |= b[u][k] & b[w][r[v][k]];
l++;
} while (z);
printf("finished random after %d tries \n",l);
printf("found solution with top band %d permutation 0, and middle band %d permutation %d \n",u,w,v);
getchar();
// scan all possibilities for the last band
l=0;
for (i = 0; i < 362880; i++) for (j = 0; j < 1306368; j++){
z=0;
for(k=0;(k<9)&&(!z);k++) z|= b[u][k] & b[j][r[i][k]] | b[j][r[i][k]] & b[w][r[v][k]];
if (!z){ l++; printf("solution %d : i= %d j=%d",l,i,j); }
}
printf("finished bottom band scan at %d millisec \n", clock()); getchar();
}