Sudoku Programmers Forum Index

 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister   ProfileProfile   Log inLog in          Games  Calendar

Log in to check your private messagesLog in to check your private messages   

Solver cant solve middle sudokus

 
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Solving sudoku
View previous topic :: View next topic  
Author Message
Auri84

Joined: 02 May 2006
Posts: 1
:

Items
PostPosted: Tue May 02, 2006 2:51 pm    Post subject: Solver cant solve middle sudokus Reply with quote

Hi i have written a Sudoku Solver in Java. Comment are german, sry but my english isnt well and it is my first big java programm.

i have test it with some sudokus an i cant solve heavy und middle sudokus. plz help. what rule i have to implement that it works with middle sudokus.

Quote:
package Sudoku;
import java.util.*;
import java.lang.Object;

class Sudoku {

/**
* @param feld ist die Klassenvariable
*/
public static int feld[][];
static int unsolved[][];

/**
* Methode die das Integer Feld in ein String Feld umwandelt
* Welches für die Methode JTable erforderlich ist
* @param feld 2 Dimensionales Feld, welche die Sudokuwerte beinhaltet
* @return
*/
public Sudoku(int[][]arg){
feld = arg;
unsolved = copyfeld(arg);
}

public String[][] toStringArray() {
String[][] feldString = new String[9][9];
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++){
String s= "";
s += ""+feld[i][j];
feldString[i][j] = s;
}
return feldString;

}



/**
* Ist eine Methode die als Bedingung genutz wird. M.h. der
* Methode wird festgestellt wann es keine leeren Stellen mehr gibt
* und durch diese Methode terminiert dann auch der Algorithmus
*
* @param feld 2 Dimensionales Feld, welche die Sudokuwerte beinhaltet
* @return
*/
private boolean feldKomplett() {
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
if (feld[i][j] == 0)
return false;
return true;
}


/**
* In dieser Methode werden Hilfsfelder erstellt in denen sich dann die
* möglichen lösungen für eine Zelle des Sudokus befinden
*
* es wird geprüft ob die zahl in der spalte, reihe oder im black schon vorhanden is
* wenn ja dann wird diese aus dem Hilffeld gelöscht
*
* das Hilfsfeld hat zu anfang alle zahlen von 1 bis 9
*
* und im idealfall nach dem durchlauf der methode für diese eine stelle nur noch einen wert
*
* @param feld 2 Dimensionales Feld, welche die Sudokuwerte beinhaltet
* @return
*/
private Vector[][] auswertenfeld() {
Vector[][] ergebnis = new Vector[9][9];
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
if (feld[i][j] == 0) {
ergebnis[i][j] = new Vector();
for (int k = 1; k <= 9; k++)
ergebnis[i][j].add(new Integer(k));
}
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
if (feld[i][j] == 0) {
// nach bekannten Zahlen sehen in der reihe
for (int k = 0; k < 9; k++)
if (feld[i][k] != 0)
ergebnis[i][j].remove(new Integer(feld[i][k]));
// nach bekannten Zahlen sehen in der spalte
for (int k = 0; k < 9; k++)
if (feld[k][j] != 0)
ergebnis[i][j].remove(new Integer(feld[k][j]));
// nach bekannten Zahlen sehen im block3x3
for (int k = 3*(i/3); k < 3*(i/3)+3; k++)
for (int l = 3*(j/3); l < 3*(j/3)+3; l++)
if (feld[k][l] != 0)
ergebnis[i][j].remove(new Integer(feld[k][l]));
}
return ergebnis;
}

private int[][] fuellefeld(Vector[][] werte) {
int[][] ergebnis = copyfeld(feld);

for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
if (feld[i][j] == 0) {
if (werte[i][j].size() == 1) {
ergebnis[i][j] = ((Integer)werte[i][j].get(0)).intValue();
continue;
}
for (int n = 0; n < werte[i][j].size(); n++) {
int num = ((Integer)werte[i][j].get(n)).intValue();

// schaut nach einzel werten in der reihe
boolean einfuegen = true;
for (int k = 0; k < 9; k++)
if ((feld[i][k] == 0) && (k != j) &&
werte[i][k].contains(new Integer(num)))
{
einfuegen = false;
break;
}
if (einfuegen) {
ergebnis[i][j] = num;
break;
}

// schaut nach einzel werten in der spalte
einfuegen = true;
for (int k = 0; k < 9; k++)
if ((feld[k][j] == 0) && (k != i) &&
werte[k][j].contains(new Integer(num)))
{
einfuegen = false;
break;
}
if (einfuegen) {
ergebnis[i][j] = num;
break;
}

// schaut nach bekannten werten im block
einfuegen = true;
boolean continuation = true;
for (int k = 3*(i/3); k < 3*(i/3)+3; k++) {
if (!continuation)
break;
for (int l = 3*(j/3); l < 3*(j/3)+3; l++)
if ((feld[k][l] == 0) &&
!((k == i) && (l == j)) &&
werte[k][l].contains(new Integer(num)))
{
continuation = false;
einfuegen = false;
break;
}
}
if (einfuegen) {
ergebnis[i][j] = num;
break;
}
}
}
return ergebnis;
}


/**
* Methode im das feld/sudoku auszugeben
*
*
* @param feld
*/
public void printfeld() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++)
if (feld[i][j] != 0)
System.out.print(feld[i][j] + " ");
else
System.out.print(". ");
System.out.println();
}
System.out.println();
}

/**
* Methode um 2 Felder b1 und b2 zu vergleichen
*
* @param b1
* @param feld
* @return
*/
public boolean feldistGleich(int[][] b1) {
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
if (b1[i][j] != feld[i][j])
return false;
return true;
}

/**
* Methode um ein Feld zu kopieren
*
* @param b
* @return
*/
public int[][] copyfeld(int[][] b) {
int[][] ergebnis = new int[9][9];
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
ergebnis[i][j] = b[i][j];
return ergebnis;
}
/**
* Methode die das Sudoku auflöst
*
* @return
*/
public int[][] loesen(){
Vector[][] werte;
int[][] altesFeld;
//printfeld(feld);
while (!feldKomplett()) {
werte = auswertenfeld();
altesFeld = copyfeld(feld);
feld = fuellefeld(werte);
if (feldistGleich(altesFeld)) {
System.err.println("Das Sudoku ist nicht lösbar.");
System.exit(1);
}
//printfeld(feld);


}return feld;
}



public int[][] getfeld() {
return feld;
}

public void setfeld(int[][] feld) {
this.feld = feld;
}
}
Back to top
View user's profile Send private message
lawrence

Joined: 18 Apr 2006
Posts: 3
:

Items
PostPosted: Tue May 09, 2006 3:05 pm    Post subject: Reply with quote

Hi Auri84,

Can you give me some unsolved sudokus that your program cannot solve? I'd like to test my solver program.

Anyway, have you implemented Dancing Links algorithm? My first solver mimics human way in solving and got stucked (i.e. took a way long time to solve) some sudokus, but when I switch to dancing links, it churns sudokus in under 1 or 2 seconds, and I'm only using VBA.

regards,
eka
Back to top
View user's profile Send private message
Volker1953_Hamburg

Joined: 23 May 2006
Posts: 4
:

Items
PostPosted: Tue May 23, 2006 11:11 pm    Post subject: Reply with quote

Ich bin kein JAVA-Programmierer und kann das Programm bzw. die "Methoden" daher nur ungefähr verfolgen.
Mir scheint, daß dort lediglich das Verfahren: "Absolute Singles" bzw. "Naked Singles" angewandt wird.

Es sollte mindestens das Verfahren: "Hidden Singles" zusätzlich angewandt werden. HiddenSingles sind solche, die je in einer BOX, ROW oder COLUMN nur einmal gesetzt werden können.

Die Methode: "Feldkomplett" sollte ggf. nicht (nur) einen booleschen Wert liefern, sondern die konkrete Zahl der Leerstellen. Auch mit ganzen Zahlen können meist problemlos Bedingungen abgefragt werden. In den meisten Systemen ist
FALSE == 0 und
TRUE jeder Wert ungleich 0.

Es könnte damit eine Methode: "Findfirstmoves" nach folgendem Muster (Pseudo-Code!) geschrieben werden:

Methode Findfirstmoves
{ FindNakedSingles
Feldkomplett(alt)

SOLANGE ( Feldkomplett(alt) ungleich 0 ?)
FindHiddensingles
SOLANGE ( Feldkomplett(alt) > Feldkomplett(neu) ? )
FindNakedSingles
-> zum SCHLEIFENENDE
SCHLEIFENENDE
}

Nach den FindFirstMoves, (die die Felder nicht nur finden, sondern auch füllen), muß sich ggf. das Verfahren: "Trial and Error" anschließen.

p.s.:
1. Evtl. ist es insbesondere bei den Schleifen einfacher und schneller, das Sudoku-Feld nicht als 9 mal 9 Felder ( i von 1 bis 9; j von 1 bis 9 ), sondern als 81 Felder zu beschreiben ( i von 0 bis 80 bzw. von 1 bis 81 ).

2. Was man BERECHNEN kann, sollte man nicht als BEDINGUNG formulieren, hier z.B. in feldkomplett:

Nicht:
{ ...
if (feld[i][j] == 0)
return false;
return true;
}

(Mangels JAVA-Kenntniossen bei mir:
Was wird da eigentlich als "letzter" Wert geliefert?
Ist sichergestellt, daß FALSE geliefert wird, wenn nur ein einziges Feld in der Mitte frei ist?)

Sondern in etwa:
{ ...
return (feld[i][j] == 0);
return true;
}

bzw. sogar noch kürzer:
{ ...
return (feld[i][j]);
}

Ich weiß allerdings leider nicht, ob eine derart "schlanke" Lösung in JAVE möglich ist.
Ich selbst benutze Forth (WinForth32).
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Solving sudoku All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Sudoku Programmers topic RSS feed 


Powered by phpBB © 2001, 2005 phpBB Group

Igloo Theme Version 1.0 :: Created By: Andrew Charron