मुझे नहीं पता कि मैं क्या गलत कर रहा हूं, और मैं पूरे दिन इस कोड पर देख रहा हूं। यह जावा में एक "मानक" सुडोकू सॉल्वर है, जो int[][]
0 के साथ खाली रिक्त स्थान लेता है। यह देखते हुए कि मैं केवल 35 छेद वाले बोर्ड में गुजर रहा हूं, यह बड़ी संख्या में समस्याओं को हल करने में सक्षम होना चाहिए, लेकिन केवल ~ 66% हल कर सकता है। दूसरों में, कुछ (आमतौर पर 2 या 4) खाली रिक्त स्थान शेष होते हैं, जो हल करना असंभव है (यानी एक अनुचित संख्या board
में लिखी गई है।) लगभग हमेशा, यह 9 गुम हो जाएगा।सुडोकू सॉल्वर बग
मैं समझता हूं कि ऐसा सरल समाधान सभी सुडोकस को हल नहीं करेगा। मैं जानबूझ कर इसे आसान दे रहा हूँ।
import java.util.ArrayList;
import java.util.List;
public class SudokuSolver
{
public SudokuSolver()
{
init();
}
public boolean solve()
{
/* Each method checks (in different ways) to see if it can find a new number
If said method does find a number, it sets off a chain reaction, starting back at the beginning.
*/
int countdown = 20;
while(!solved() && --countdown > 0)
{
if(given())
continue;
if(findSingletons())
continue;
if(zerosLeft() <= 4)
justGuess();
}
return solved();
}
public boolean given()
{
boolean repeat = false;
//Iterate through every given number
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(board[i][j] != 0 && !found[i][j])
{
repeat = true;
foundNum(i, j, board[i][j]);
}
}
}
//Call given every time a new number is found
return repeat;
}
public boolean findSingletons()
{
boolean repeat = false;
//LOTS of iteration, but I'm out of ideas.
int[] values;
ArrayList<Integer> singletons = new ArrayList<Integer>();
for(int i=0;i<9;i++)
{
values = new int[10];
singletons.clear();
for(int j=0;j<9;j++)
for(int k=0;k<possible[i][j].size();k++)
values[possible[i][j].get(k)]++;
for(int j=1;j<10;j++)
if(values[j] == 1)
singletons.add(j);
for(int j=0;j<9;j++)
for(int k=0;k<singletons.size();k++)
if(possible[i][j].contains(singletons.get(k)))
{
foundNum(i, j, singletons.get(k));
repeat = true;
}
}
for(int i=0;i<9;i++)
{
values = new int[10];
singletons.clear();
for(int j=0;j<9;j++)
for(int k=0;k<possible[j][i].size();k++)
values[possible[j][i].get(k)]++;
for(int j=1;j<10;j++)
if(values[j] == 1)
singletons.add(j);
for(int j=0;j<9;j++)
for(int k=0;k<singletons.size();k++)
if(possible[j][i].contains(singletons.get(k)))
{
foundNum(j, i, singletons.get(k));
repeat = true;
}
}
int[] corners = {0,3,6};
for(int a=0;a<3;a++)
for(int l=0;l<3;l++)
for(int i=corners[a];i<corners[a]+3;i++)
{
values = new int[10];
singletons.clear();
for(int j=corners[l];j<corners[l]+3;j++)
for(int k=0;k<possible[i][j].size();k++)
values[possible[i][j].get(k)]++;
for(int j=1;j<10;j++)
if(values[j] == 1)
singletons.add(j);
for(int j=0;j<9;j++)
for(int k=0;k<singletons.size();k++)
if(possible[i][j].contains(singletons.get(k)))
{
foundNum(i, j, singletons.get(k));
repeat = true;
}
}
return repeat;
}
public void justGuess()
{
outer:
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
if(board[i][j] == 0)
{
foundNum(i, j, possible[i][j].get(0));
break outer;
}
}
public void foundNum(int x, int y, int numFound)
{
if(board[x][y] != 0 && board[x][y] != numFound)
{
throw new RuntimeException("Attempting to place a number where one was already found");
}
board[x][y] = numFound;
possible[x][y].clear();
possible[x][y].add(numFound);
found[x][y] = true;
for(int i=0;i<9;i++) {
if(i != x)
if(possible[i][y].indexOf(numFound) != -1)
possible[i][y].remove(possible[i][y].indexOf(numFound));
}
for(int i=0;i<9;i++) {
if(i != y)
if(possible[x][i].indexOf(numFound) != -1)
possible[x][i].remove(possible[x][i].indexOf(numFound));
}
int cornerX = 0;
int cornerY = 0;
if(x > 2)
if(x > 5)
cornerX = 6;
else
cornerX = 3;
if(y > 2)
if(y > 5)
cornerY = 6;
else
cornerY = 3;
for(int i=cornerX;i<10 && i<cornerX+3;i++)
for(int j=cornerY;j<10 && j<cornerY+3;j++)
if(i != x && j != y)
if(possible[i][j].indexOf(numFound) != -1)
possible[i][j].remove(possible[i][j].indexOf(numFound));
}
public boolean solved() {
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
if(!found[i][j])
return false;
return true;
}
public void reset(int[][] board)
{
this.board = board;
init();
}
public void init()
{
possible = new ArrayList[9][9];
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
{
possible[i][j] = new ArrayList<Integer>();
for(int k=1;k<10;k++)
possible[i][j].add(k);
}
found = new boolean[9][9];
}
public void print()
{
for(int i=0;i<9;i++)
{
if(i%3==0 && i != 0)
System.out.println("- - - | - - - | - - -");
for(int j=0;j<9;j++)
{
if(j%3==0 & j != 0)
System.out.print("| ");
System.out.print(board[i][j] + " ");
}
System.out.println();
}
System.out.println();
}
private int zerosLeft()
{
int empty = 0;
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
if(board[i][j] == 0)
empty++;
return empty;
}
private void data(int difficulty)
{
int empty = 0;
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
if(board[i][j] == 0)
empty++;
System.out.println(empty);
}
public static void main(String[] args)
{
SudokuGenerator sg = new SudokuGenerator();
SudokuSolver ss = new SudokuSolver();
int[][] tempBoard = {{4, 0, 1, 0, 9, 7, 0, 5, 8 },
{2, 0, 0, 5, 3, 1, 4, 0, 6 },
{5, 0, 6, 4, 0, 2, 0, 3, 9 },
{0, 9, 0, 0, 0, 4, 3, 0, 2 },
{0, 0, 0, 9, 0, 0, 6, 4, 7 },
{7, 0, 4, 0, 0, 0, 9, 0, 5 },
{0, 0, 7, 0, 0, 3, 8, 9, 4 },
{8, 5, 0, 1, 4, 9, 7, 0, 0 },
{9, 0, 3, 8, 7, 6, 0, 0, 0 }};
ss.reset(tempBoard);
System.out.println(ss.solve());
ss.print();
ss.data(35);
}
int[][] board;
ArrayList<Integer>[][] possible;
boolean[][] found;
}
मैं प्रोग्रामिंग के लिए अभी भी नया हूं, इसलिए इसे हल करने के अलावा अन्य सलाह का स्वागत होगा। (विशेष रूप से possible
को अनुकूलित करना। यह आज तक लिखा गया सबसे बड़ा कोड है।)
धन्यवाद!
बनाने के तरीके खोजने के लिए कर रहे हैं "यह सबसे अपवित्र कोड मैं तारीख को लिखा है है।" एरिक लिपर्ट ने सी # में अपनी [ग्राफ रंग श्रृंखला] (http://blogs.msdn.com/b/ericlippert/archive/tags/graph+colouring/) के हिस्से के रूप में एक सुंदर सुडोकू सॉल्वर लिखा था। यह कुछ विशेषताओं का उपयोग करता है जिनमें जावा नहीं है, लेकिन मैं वैसे भी एक नज़र डालने की सलाह देता हूं। –
विशिष्ट तरीकों का परीक्षण करने के लिए जुनीट परीक्षण लिखकर ड्राइव विकास। टेस्ट ड्राइव डेवलपमेंट (टीडीडी) पर पढ़ें, ऑब्जेक्ट ओरिएंटेड डिज़ाइन पर पढ़ें। यहां कुछ स्पष्ट कोड पुन: कारक हैं जिन्हें लागू किया जाना चाहिए, पूर्ण समीक्षा करने के लिए अभी समय नहीं है। लेकिन यहां कुछ मुख्य विशेषताएं हैं: ढूंढें सिंगलेट बहुत लंबा है। इसे छोटे तरीकों से दोबारा करने पर विचार करें। एक प्रिंट विधि का उपयोग करने के बजाय toString ओवरराइड; कोड को देखें जो मैंने एक समान लेकिन सरल समस्या पर लिखा है https://github.com/RobertKielty/q8impl/tree/master/workspace/EightQueens –
@Rob: आप अपनी टिप्पणियां हटा सकते हैं (क्या आपको इसके लिए और अधिक प्रतिष्ठा चाहिए ?) - उदाहरण के लिए यदि आप समय-समय पर "एंटर" हिट करते हैं, शायद एक नई लाइन बनाने के लिए। –