একটি সর্বনিম্ন-ক্লু সুডোকু আনসলভার তৈরি করুন


16

এই প্রশ্নটি উল্লেখ করার জন্য আমার প্রচেষ্টা , তবে আরও উদ্দেশ্যমূলক সমাধানের মানদণ্ড দিয়ে।

আপনার কাজটি এমন একটি প্রোগ্রাম বা ফাংশন তৈরি করা যা Sআপনার পছন্দের বিন্যাসে একটি সমাধান করা সুডোকু গ্রিড গ্রহণ করে এবং Sএর অনন্য সমাধান হিসাবে যতটা সম্ভব সংকেত সহ একটি সমস্যা গ্রিড তৈরি করার চেষ্টা করে । ( Sযতক্ষণ না সমাধানটি কার্যকরভাবে অনন্য থাকে ততক্ষণ কোন কার্যকর পদ্ধতিটি ব্রুট ফোর্স সহ অনন্য সমাধান কী তা বিবেচনা করে না ))


আপনার প্রোগ্রামটি এই ফাইলে পাওয়া ,000০,০০০ সলিউশন গ্রিডের একটি সেট (7..৮২ এমবি ডাউনলোড) এর মাধ্যমে চালিয়ে এবং আপনার সমাধানের ফলে তৈরি সমস্ত 100,000 সমস্যা গ্রিডে ক্লুগুলির সংখ্যা যুক্ত করে স্কোর করা হবে।

উপরের টেস্ট ফাইলের সুডোকু সমাধানগুলি 81-অক্ষরের স্ট্রিং হিসাবে প্রকাশ করা হয়েছে, বাম থেকে ডানে, তারপরে উপর থেকে নীচে। পরীক্ষার ফাইলে ইনপুটটিকে ব্যবহারযোগ্য সমাধানে পরিণত করার জন্য প্রয়োজনীয় কোডটি আপনার সমাধানের বাইট গণনা অনুসারে গণনা করবে না।

আমার বন্যা পেইন্ট চ্যালেঞ্জ হিসাবে, আপনার প্রোগ্রামটি অবশ্যই সমস্ত 100,000 ধাঁধাকে একটি বৈধ সমাধান হিসাবে বিবেচনা করার জন্য একটি বৈধ আউটপুট তৈরি করতে হবে। যে প্রোগ্রামটি সমস্ত 100,000 পরীক্ষার ক্ষেত্রে সবচেয়ে কম সংখ্যক ক্লু বের করে দেয় তা হ'ল বিজয়ী, সংক্ষিপ্ত কোডটি টাই করে breaking


বর্তমান স্কোরবোর্ড:

  1. 2,361,024 - নটকি, সি
  2. 2,580,210 - es1024, পিএইচপি
  3. 6,000,000 - কার্পেট পাইথন, পাইথন 2
  4. 7,200,000 - জো জেড, পাইথন

এছাড়াও, আপনি নিশ্চিত হয়ে উঠতে পারেন যে ১,7০০,০০০ এরও কম সমাধান দাবি করা যে কোনও সমাধান হ'ল ফোকাস, তবে আমি দেখতে চাই যে এগুলি কতটা কম যায়।
জো জে।

উত্তর:


8

সি - 2,361,024 2,509,949 ক্লু

যদি কোনও শক্তিশালী শক্তি সমাধানকারী কেবল একটি অনন্য সমাধান খুঁজে পায় তবে সর্বশেষ কক্ষ থেকে শুরু হওয়া সূত্রগুলি সরিয়ে ফেলুন।

দ্বিতীয়বার চেষ্টা করুন: শেষ থেকে শুরু না করে কোন ক্রমটি সরিয়ে ফেলতে হবে তা সিদ্ধান্ত নিতে হিউরিস্টিক ব্যবহার করুন। এটি কোডটিকে আরও ধীর করে তোলে (ফলাফল গণনা করার জন্য 2 পরিবর্তে 20 মিনিট)। আমি বিভিন্ন দ্র with তাত্ত্বিকতা নিয়ে পরীক্ষা-নিরীক্ষার জন্য সমাধানকারীকে আরও দ্রুত তৈরি করতে পারতাম, তবে আপাতত তা করবে।

#include <stdio.h>
#include <string.h>
char ll[100];
short b[81];
char m[81];
char idx[81][24];
int s;
char lg[513];
void pri2() {
    int i;
    for(i=0;i<81;i++) putchar(lg[b[i]]);
    putchar('\n');
}
void solve(pos){
int i,p;
if (s > 1) return;
if (pos == 81) { s++; return; }
if (b[pos]) return solve(pos+1);
for (p=i=0;i<24;i++) p |= b[idx[pos][i]];
for (i = 0; i < 9; i++) if (!(p&(1<<i))) {
    b[pos] = 1 << i;
    solve(pos + 1);
}
b[pos] = 0;
}
int main() {
    int i,j,t;
    for(i=0;i<9;i++) lg[1<<i]='1'+i;
    lg[0] = '.';
    for(i=0;i<81;i++) {
    t = 0;
    for(j=0;j<9;j++) if(i/9*9 + j != i) idx[i][t++] = i/9*9 + j;
    for(j=0;j<9;j++) if(i%9 + j*9 != i) idx[i][t++] = i%9 + j*9;
    for(j=0;j<81;j++) if(j/27 == i/27 && i%9/3 == j%9/3 && i!=j) idx[i][t++] = j;
    }
    while(scanf("%s ",ll)>0) {
    memset(m, 0, sizeof(m));
    for(i=0;i<81;i++) b[i] = 1 << (ll[i]-'1');
    for(i=0;i<81;i++) {
    int j,k,l = 99;
    for(k=0;k<81;k++) if (m[k] <= l) l = m[k], j = k;
    m[j] = 24;
    t = b[j]; b[j] = 0;
    s = 0; solve(0);
    if (s > 1) b[j] = t;
    else for(k=0;k<24;k++) m[idx[j][k]]++;
    }
    pri2();
    }
    return 0;
}

1

পাইথন - 7,200,000 ক্লু

যথারীতি, এখানে একটি শেষ-স্থানের রেফারেন্স সমাধান:

def f(x): return x[:72] + "." * 9

সংখ্যার নীচের সারিটি সরিয়ে ফেলা সমস্ত ক্ষেত্রে ধাঁধাটি সমাধানযোগ্যভাবে ফেলে দেয়, যেহেতু প্রতিটি কলামে এখনও 9 টির মধ্যে 8 টি নম্বর ভরা রয়েছে, এবং নীচের সারিতে প্রতিটি সংখ্যা কলামে কেবলমাত্র নবম সংখ্যাটি বাকী রয়েছে।

কোনও গুরুতর প্রতিযোগী যদি এইটির চেয়ে আইনত আরও খারাপ স্কোর পরিচালনা করে তবে আমি অবাক হয়ে যাব।


আমি বলতে চাইছি আপনি শেষটিকে সরাতে পারবেন।
সন্ধান

আপনি কেবল পুরো বিষয়টি সমাধান করতে পারেন, তবে তাদের উভয়েরই একজন গুরুতর প্রতিযোগী হবে না।
জো জেড।

তাহলে কেন এটি মারাত্মক প্রতিযোগী?
theonlygusti

এটা না। এ কারণেই আমি বলেছিলাম যে কোনও গুরুতর প্রতিযোগী যদি এই অ-গুরুতর প্রতিযোগীর চেয়েও খারাপ স্কোর করতে সক্ষম হন তবে আমি হতবাক হয়ে যাব।
জো জেড।

1

পাইথন 2 - 6,000,000 ক্লু

একটি সহজ সমাধান যা এই ধাঁধাগুলি সমাধানের 3 সাধারণ পদ্ধতি ব্যবহার করে:

def f(x): 
    return ''.join('.' if i<9 or i%9==0 or (i+23)%27 in (0,3) else c 
        for i,c in enumerate(x))

এই ফাংশনটি এর মতো ক্লু ফর্ম্যাট তৈরি করে:

.........
.dddddddd
.dddddddd
.ddd.dd.d
.dddddddd
.dddddddd
.ddd.dd.d
.dddddddd
.dddddddd

এটি সর্বদা সমাধান করা যেতে পারে। 4 3x3 অংশগুলি প্রথমে সমাধান করা হবে, তারপরে 8 টি কলাম, তারপরে 9 টি সারি।


1

পিএইচপি - 2,580,210 ক্লু

এটি প্রথমে সর্বশেষ সারি এবং কলাম এবং প্রতিটি বাক্সের নীচে ডান কোণটি সরিয়ে দেয়। এরপরে বোর্ডটি নির্বিঘ্নে দ্রবণযোগ্য ensure

নীচের কোডটির বেশিরভাগটি আমার পুরানো উত্তরগুলির মধ্যে একটি থেকে পরিবর্তিত হয়েছিল । printBoardখালি কোষগুলির জন্য 0s ব্যবহার করে।

<?php
// checks each row/col/block and removes impossible candidates
function reduce($cand){
    do{
        $old = $cand;
        for($r = 0; $r < 9; ++$r){
        for($c = 0; $c < 9; ++$c){
            if(count($cand[$r][$c]) == 1){ // if filled in
                // remove values from row and col and block
                $remove = $cand[$r][$c];
                for($i = 0; $i < 9; ++$i){
                    $cand[$r][$i] = array_diff($cand[$r][$i],$remove);
                    $cand[$i][$c] = array_diff($cand[$i][$c],$remove);
                    $br = floor($r/3)*3+$i/3;
                    $bc = floor($c/3)*3+$i%3;
                    $cand[$br][$bc] = array_diff($cand[$br][$bc],$remove);
                }
                $cand[$r][$c] = $remove;
            }
        }}
    }while($old != $cand);
    return $cand;
}

// checks candidate list for completion
function done($cand){
    for($r = 0; $r < 9; ++$r){
    for($c = 0; $c < 9; ++$c){
        if(count($cand[$r][$c]) != 1)
            return false;
    }}
    return true;
}

// board format: [[1,2,0,3,..],[..],..], $b[$row][$col]
function solve($board){
    $cand = [[],[],[],[],[],[],[],[],[]];
    for($r = 0; $r < 9; ++$r){
    for($c = 0; $c < 9; ++$c){
        if($board[$r][$c]){ // if filled in
            $cand[$r][$c] = [$board[$r][$c]];
        }else{
            $cand[$r][$c] = range(1, 9);
        }
    }}
    $cand = reduce($cand);

    if(done($cand))  // goto not really necessary
        goto end;    // but it feels good to use it 
    else return false;

    end:
    // back to board format
    $b = [];
    for($r = 0; $r < 9; ++$r){
        $b[$r] = [];
        for($c = 0; $c < 9; ++$c){
            if(count($cand[$r][$c]) == 1)
                $b[$r][$c] = array_pop($cand[$r][$c]);
            else 
                $b[$r][$c] = 0;
        }
    }
    return $b;
}

function add_zeros($board, $ind){
    for($r = 0; $r < 9; ++$r){
    for($c = 0; $c < 9; ++$c){
        $R = ($r + (int)($ind/9)) % 9;
        $C = ($c + (int)($ind%9)) % 9;
        if($board[$R][$C]){
            $tmp = $board[$R][$C];
            $board[$R][$C] = 0;
            if(!solve($board))
                $board[$R][$C] = $tmp;
        }   
    }}
    return $board;
}

function generate($board, $ind){
    // remove last row+col
    $board[8] = [0,0,0,0,0,0,0,0,0];
    foreach($board as &$j) $j[8] = 0;

    // remove bottom corner of each box
    $board[2][2] = $board[2][5] = $board[5][2] = $board[5][5] = 0;

    $board = add_zeros($board, $ind);

    return $board;    
}
function countClues($board){
    $str = implode(array_map('implode', $board));
    return 81 - substr_count($str, '0');
}

function generateBoard($board){
    return generate($board, 0);
}

function printBoard($board){
    for($i = 0; $i < 9; ++$i){
        echo implode(' ', $board[$i]) . PHP_EOL;
    }
    flush();
}
function readBoard($str){
    $tmp = str_split($str, 9);
    $board = [];
    for($i = 0; $i < 9; ++$i)
        $board[] = str_split($tmp[$i], 1);
    return $board;
}
// testing
$n = 0;
$f = fopen('ppcg_sudoku_testing.txt', 'r');
while(($l = fgets($f)) !== false){
    $board = readBoard(trim($l));
    $n += countClues(generateBoard($board));
}
echo $n;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.