কতগুলি সুডোকু ধাঁধা বিদ্যমান?


10

এটি সুডোকু সমাধানকারী নয়, সুডোকু চেকারও নয়।

আপনার চ্যালেঞ্জটি হ'ল একটি ফাংশন বা স্ক্রিপ্ট লিখুন যা ইনপুট হিসাবে 2D সুডোকু ধাঁধা (যা ক্লাসিক 9x9 বোর্ডের জন্য 3 , একটি 16x16 বোর্ডের জন্য 4 ইত্যাদি) আকারের " সংখ্যার" সংখ্যার একটি আনুমানিক গণনা করবে এই আকারের জন্য বিদ্যমান স্বতন্ত্র ধাঁধা (সমাধান)

উদাহরণস্বরূপ, ইনপুট 3 দেওয়া, আপনার প্রোগ্রামটিতে 6,670,903,752,021,072,936,960 সংখ্যাটির একটি আনুমানিক মুদ্রণ করা উচিত যা বিভিন্ন প্রতিসাম্য বিবেচনায় নেওয়ার সময় স্বতন্ত্র 9x9 সুডোকু ধাঁধা বা 5,472,730,538 হিসাবে পরিচিত । আপনার সমাধানটিতে প্রতিসরণগুলি গণনা করা বা উপেক্ষা করা হবে কিনা তা উল্লেখ করা উচিত।

"কাঙ্ক্ষিত নির্ভুলতা" অপরিবর্তিত রেখে গেছে: আপনার প্রোগ্রামটি একটি নির্দিষ্ট সময়ের জন্য চলতে পারে এবং তার ফলাফল আউটপুট দিতে পারে, বা একটি নির্দিষ্ট সংখ্যক অঙ্কের মধ্যে এটি গণনা করতে পারে, বা এমনকি চিরতরে চালিত হয়, আরও ভাল এবং আরও ভাল অনুমানের মুদ্রণ করে। মুল বক্তব্যটি হ'ল একটি সীমাবদ্ধ সময়ে ফলাফলকে প্রয়োজনীয় প্রয়োজনীয় নির্ভুলতার সাথে গণনা করা সম্ভব হওয়া উচিত। (সুতরাং "42" একটি গ্রহণযোগ্য উত্তর নয়)) উপলব্ধ ফলাফলের মেশিনে আপনার ফলাফলের যথার্থতা সীমাবদ্ধ করা গ্রহণযোগ্য acceptable

অনলাইন সংস্থান অ্যাক্সেস না করা, ফাইলের নামে উত্স কোড সংরক্ষণ করা ইত্যাদি নয় etc.


পিএস: আমি জানি এটি একটি কঠিন সমস্যা (এনপি-সম্পূর্ণ যদি আমার ভুল না হয় তবে But) তবে এই প্রশ্নটি কেবল একটি আনুমানিক, পরিসংখ্যানগত সমাধান চাইছে। উদাহরণস্বরূপ আপনি একটি এলোমেলো কনফিগারেশন চেষ্টা করতে পারেন যা একটি (বা আরও ভাল দুটি) সীমাবদ্ধতাগুলি পূরণ করে, কতগুলি বিদ্যমান রয়েছে তা গণনা করুন এবং তারপরে আপনি তিনটি সীমাবদ্ধতা পূরণ করে এমন একটি ধাঁধা কতবার পান তা পরীক্ষা করে দেখুন। এটি ছোট আকারের (অবশ্যই আকার = 3 এবং সম্ভবত 4 এর জন্য) একটি শালীন সময়ে কাজ করবে তবে অ্যালগরিদম কোনও আকারের জন্য কাজ করার জন্য যথেষ্ট জেনারেল হওয়া উচিত।

সেরা অ্যালগরিদম জিতেছে।


পিএস 2: বোবা তবে ভাল-গল্ফযুক্তগুলির চেয়ে আরও ভাল সমস্যার সমস্যার প্রতিবিম্বিত করতে এবং চতুর সমাধানগুলিকে উত্সাহিত করার জন্য আমি কোড-গল্ফ থেকে কোড-চ্যালেঞ্জে পরিবর্তিত হয়েছি। তবে যেহেতু দৃশ্যত "সেরা অ্যালগরিদম" অস্পষ্ট, তাই আমি এটি সঠিকভাবে সংজ্ঞা দেওয়ার চেষ্টা করি।

পর্যাপ্ত সময় দেওয়া এবং ধ্রুবক কারণগুলি (সিপিইউ এবং ইন্টারপ্রিটারের গতি সহ) উপেক্ষা করা, বা সমভাবে, তাদের অ্যাসিপোটোটিকাল আচরণ বিবেচনা করে কোন সমাধানটি সঠিক ফলাফলটিকে দ্রুততম রূপান্তরিত করবে?


11
এটি কি আসলেই খুব কঠিন সমস্যা নয় ? আপনি কি {1, 1, 288, 6e21 numbers সংখ্যার উত্পাদন করার জন্য কোনও ফাংশন তৈরি করার সবচেয়ে সংক্ষিপ্ততম উপায় জিজ্ঞাসা করছেন, বা কোনওভাবে এটি n> 3 এ প্রসারিত করতে চান?
অ্যালগরিদমশর্ক

সঠিক সমাধানটি একটি অবিশ্বাস্যরকম কঠিন সমস্যা, তবে একটি আনুমানিক কিছু র্যান্ডম নমুনা এবং আধুনিক সিপিইউ সময়ের কয়েক সেকেন্ডের সাথে গণনা করা যেতে পারে। অবশ্যই স্মার্ট সমাধানগুলি স্বাগত!
টোবিয়া

2
@Tobia এই পদ্ধতির রুবিক্স কিউব এন প্যাচসমূহ প্রয়োজন সমাধানের জন্য অবস্থানের প্রায় সংখ্যা খুঁজে বের করতে ব্যবহৃত হয় kociemba.org/cube.htm তাই এটি সম্ভব একটি পড়তা এই ভাবে পেতে। যাইহোক, আমি যদি এমন একটি প্রোগ্রাম লিখি যা প্রতিটি সারিকে সমাধান করে এবং তারপরে কলাম এবং স্কোয়ারগুলি সমাধান হয়েছে কিনা তা পরীক্ষা করে দেখি তবে এটি ব্রুটেফোর্সের (9!) ^ 9 = 1E50 সম্ভাবনা রয়েছে যার মধ্যে কেবল 6E21 হিট (প্রশ্ন অনুসারে) ।) এটির জন্য গড়ে হিট প্রতি 1.6E28 টি চেষ্টা দরকার। এটা বেশ ধীর। এখন, যদি আমি নিশ্চিত করতে পারি যে উভয় সারি এবং কোলগুলি সঠিক এবং কেবল স্কোয়ারগুলি পরীক্ষা করতে পারি তবে আমি কোথাও পৌঁছে যাব। আহ! আমার একটি ধারণা আছে ...
স্তর নদী সেন্ট

@ স্টেভেভারিল দেখুন? :-)
টোবিয়া

বিশ্লেষণী সমাধান কি নেই?
নিউব্রিক্ট

উত্তর:


3

সি ++

আমি এখানে যা উপস্থাপন করব তা হল একটি অ্যালগরিদম, 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();
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.