एक न्यूनतम-क्लू सुडोकू अनसुना बनाएँ


16

इस प्रश्न को बताते हुए मेरा प्रयास है , लेकिन अधिक उद्देश्य से सुलझाने की कसौटी के साथ।

आपका कार्य एक प्रोग्राम या फ़ंक्शन का निर्माण करना है Sजो आपकी पसंद के प्रारूप में एक हल किए गए सुडोकू ग्रिड को लेता है और यथासंभव Sअनूठे समाधान के साथ कुछ सुराग के साथ एक समस्या ग्रिड उत्पन्न करने का प्रयास करता है । (इससे कोई फ़र्क नहीं पड़ता कि Sब्रूट फ़ोर्स सहित, अद्वितीय समाधान क्या है, जब तक कि समाधान अनूठे रूप से अद्वितीय है)।


इस फ़ाइल (7.82 एमबी डाउनलोड) में पाए गए 100,000 सॉल्यूशन ग्रिड के सेट के माध्यम से इसे चलाकर आपका प्रोग्राम रन किया जाएगा , और आपके समाधान से उत्पन्न होने वाली सभी 100,000 समस्या ग्रिड में सुराग की संख्या को जोड़ देगा।

उपरोक्त परीक्षण फ़ाइल में सुडोकू समाधान को बाएं से दाएं, फिर ऊपर से नीचे तक 81-वर्ण स्ट्रिंग के रूप में व्यक्त किया गया है। परीक्षण फ़ाइल में इनपुट को एक उपयोगी समाधान में बदलने के लिए आवश्यक कोड आपके समाधान की बाइट गणना की ओर नहीं गिरेगा।

मेरी फ्लड पेंट चुनौती के रूप में , आपके कार्यक्रम को वास्तव में सभी 100,000 पहेलियों के लिए एक वैध समाधान माना जाना चाहिए। वह कार्यक्रम जो सभी 100,000 परीक्षण मामलों के लिए सबसे कम कुल सुराग का उत्पादन करता है, विजेता होता है, जिसमें छोटे कोड एक टाई को तोड़ते हैं।


वर्तमान स्कोरबोर्ड:

  1. 2,361,024 - नटकी, सी
  2. 2,580,210 - es1024, पीएचपी
  3. 6,000,000 - कारपेटपाइथन, पायथन 2
  4. 7,200,000 - जो जेड, पायथन

इसके अलावा, आप यह सुनिश्चित कर सकते हैं कि 1,700,000 से कम समाधान का दावा करने वाला कोई भी समाधान एक फोन है, लेकिन मैं यह देखना चाहता हूं कि ये कितने कम हो सकते हैं।
जो जेड।

जवाबों:


8

C - 2,361,024 2,509,949 सुराग

अंतिम सेल से शुरू होने वाले सुराग निकालें यदि एक क्रूर बल सॉल्वर केवल एक अनूठा समाधान पाता है।

दूसरा प्रयास: यह तय करने के लिए कि किस क्रम में अंतिम से शुरू करने के बजाय सुराग निकालने के लिए अनुमानी का उपयोग करें। इससे कोड बहुत धीमा हो जाता है (परिणाम की गणना करने के लिए 2 के बजाय 20 मिनट)। मैं सॉल्वर को तेज कर सकता था, विभिन्न उत्तराधिकारियों के साथ प्रयोग करने के लिए, लेकिन अब यह कर देगा।

#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

संख्याओं की निचली पंक्ति को हटाने से सभी मामलों में पहेली हल हो जाती है, क्योंकि प्रत्येक कॉलम में अभी भी 8 में से 9 नंबर भरे हुए हैं, और नीचे की पंक्ति में प्रत्येक संख्या कॉलम में बचे हुए नौवें नंबर की बस है।

यदि कोई गंभीर दावेदार कानूनी रूप से इस से भी बदतर स्कोर करता है, तो मैं हैरान रह जाऊंगा।


मेरा मतलब है, आप सिर्फ पिछले एक को हटा सकते हैं।
देखिए

आप पूरी तरह से हल की हुई चीज़ को भी छोड़ सकते हैं, लेकिन उनमें से कोई भी गंभीर दावेदार नहीं होगा।
जो जेड

तो यह एक गंभीर दावेदार क्यों है?
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

PHP - 2,580,210 सुराग

यह पहले अंतिम पंक्ति और कॉलम को हटाता है, और हर बॉक्स के निचले दाएं कोने को। यह तब प्रत्येक सेल को खाली करने की कोशिश करता है, बोर्ड को एक साधारण सॉल्वर के माध्यम से चलाने के बाद प्रत्येक परिवर्तन सुनिश्चित करने के लिए बोर्ड अभी भी स्पष्ट रूप से हल करने योग्य है।

नीचे दिए गए अधिकांश कोड को मेरे पुराने उत्तरों में से एक से संशोधित किया गया था । 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;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.