Praktische Informatik I – Der Imperative Kern Rekursive Suche
Prof. Dr. Stefan Edelkamp
Institut für Künstliche Intelligenz
Technologie-Zentrum für Informatik und Informationstechnik (TZI) Am Fallturm 1, 28359 Bremen
+49-(0)421-218-64007 www.tzi.de/~edelkamp
Outline
1 Tower-of-Hanoi
2 Labyrinth-Suche
3 Dameprobleme
4 Sudokus
Ewiges Stapeln
Tower-of-Hanoi fragt nach einer Umlegung vonnPlatten von Stapela auf Stapelbunter Zuhilfenahme eines dritten Stapelsc.
Die Platten sind in der Größe verschieden und eine kleinere Platte darf niemalsunterhalb einer größere Platte liegen.
Das folgende Bild zeigtallemöglichen Zustände mitn=2 Platten
Die rekursive Lösung verschiebt einen Stapel der Größendurch das rekursive Verschiebenvon zwei Stapeln der Größen−1.
Programm 1:Die Lösung von Tower-of-Hanoi.
public classHanoi {
/∗∗
∗Constructor for objects of class Gauss
∗/
publicHanoi() {
move(4,’a’,’b’,’c’);// call function }
/∗∗
∗moves of a stack in TOH problem
∗
∗@param y a sample parameter for a method
∗@return the sum of x and y
∗/
public voidmove(intn,chara,charb,charc) {// move stack if(n== 0)return;// stack is empty
move(n−1,a,c,b);// recursive call, a to c via b System.out.println("move "+n+" from "+a+" to "+c);
move(n−1,c,a,b);// recursive call, c to a via b }
}
Outline
1 Tower-of-Hanoi
2 Labyrinth-Suche
3 Dameprobleme
4 Sudokus
Ariadne unterwegs
DasLabyrinthproblem erfragt den Weg vom Start- zum Zielpunkt.
Das Programm 3 liefert die eine Lösung des Labyrinthproblems mit zufällig ausgewürfelten Wänden
DieTiefensucheschaut in alle Himmelsrichtungen und jede besuchte Koordinate wird mit einer Markierung versehen.
DieBesuchtmarkierungverhindert denMehrfachbesuchvon Positionen – dieZielbedingungsichert dieTerminierung
Desweiteren wird dieLösungssequenzauf der Konsole ausgegeben.
Programm 2: Ein Labyrinthproblem.
importjava.util.Random;
public classMaze {
intmaze[][];// maze with walls that block intvisited[][];// memorization to avoid duplicates intgoalx;
intgoaly;
publicMaze(intx,inty) { Random r=newRandom();
maze=new int[x][y];
visited=new int[x][y];
for(inti=0;i<x;i++) for(intj=0;j<y;j++)
maze[i][j] =visited[i][j] = 0;
for(inti=1;i<x−1;i++) for(intj=1;j<y−1;j++)
if(r.nextInt() % 5 != 0) maze[i][j] = 1;
goalx=x−1;goaly=y−1;
maze[goalx][goaly] = 1;
}
Programm 3:Ein Labyrinth (Tiefensuch-) Löser.
public voiddfs(intx,inty) {
if(maze[x][y] == 0 ||visited[x][y] != 0)return;// failure System.out.println(" @ ("+x+","+y+")");// output if(x==goalx&&y==goaly) {// goal coordinates found
System.out.println("goal found");
System.exit(1);
}
visited[x][y] = 1;// memorize, not to be visited again dfs(x,y+1);dfs(x,y−1);// calls to neighbors dfs(x+1,y);dfs(x−1,y);// calls to neighbors }
}
Outline
1 Tower-of-Hanoi
2 Labyrinth-Suche
3 Dameprobleme
4 Sudokus
Bitte nicht schlagen!
Dasn-Dameproblem fragt nach der Platzierung vonnDamen auf einem(n×n)großen Schachspiel, dass keine Dame eine andere (vertikal, horizontal, oder diagonal) bedroht.
Die Lösung produziert im Gegensatz zu Tower-of-HanoiRücksprünge – die bei illegalen Stellungen den Lösungsprozess weiterführen.
Das Programm 4 erzeugtalleLösungen.
Es existiert einesuchfreie Lösungdes Problems.
Aufgabe: Gibt es Werte vonnfür die Sie die Lösung direkt angeben können?
Tipp: Die Werte vonn, bei denen eine einfache Konstruktion funktioniert haben einen Abstand von 6 und die Konstruktion nutzt Rösselsprünge
Programm 4: Die Lösung des Dameproblems.
public classQueens {
private int[]a;
publicQueens(intn) { a=new int[n];
solve(n,0);
}
public booleanlegal(intq,introw) { for(intcolumn=0;column<row;column++)
if(a[column] ==q||a[column]−q==column−row||q−a[column] ==column−row) return false;
return true;
}
public voidsolve(intn,intj) { if(j==n) {
for(inti=0;i<n;i++) {// for each row for(intk=0;k<n;k++)// for each column
if(i==a[k])System.out.print("@");elseSystem.out.print(".");
System.out.println();
} }
for(intq=0;q<n;q++)
if(legal(q,j)) {a[j] =q;solve(n,j+1); } }
}
Outline
1 Tower-of-Hanoi
2 Labyrinth-Suche
3 Dameprobleme
4 Sudokus
Sichtlich gelöst
EinSudokubesteht aus 9×9 Feldern, die zusätzlich in 3×3 Blöcken mit 3×3 Feldern aufgeteilt sind.
Zeilen, Spalten und Blöcke enthaltenalleZahlen von 1 bis 9einmal Sudokus wurden wahrscheinlich um 1970 erstmalig vom
Rätselspezialisten Dell im MagazinMathematische Rätsel und logische Problemeveröffentlicht.
1984 publizierte ein japanischer Zeitschriftenverleger das Rätsel in der ZeitungMonthly Nikolist
Der folgendeLöserfür Sudokus ist praktisch.
Programm 5:Ein Sudokuproblem-Löser.
public classSudoku {
public chars[] = {’0’,’0’,’0’,’0’,’0’,’0’,’0’,’0’,’0’,
’0’,’0’,’0’,’0’,’0’,’3’,’0’,’8’,’5’,
’0’,’0’,’1’,’0’,’2’,’0’,’0’,’0’,’0’,
’0’,’0’,’0’,’5’,’0’,’7’,’0’,’0’,’0’,
’0’,’0’,’4’,’0’,’0’,’0’,’1’,’0’,’0’,
’0’,’9’,’0’,’0’,’0’,’0’,’0’,’0’,’0’,
’5’,’0’,’0’,’0’,’0’,’0’,’0’,’7’,’3’,
’0’,’0’,’2’,’0’,’1’,’0’,’0’,’0’,’0’,
’0’,’0’,’0’,’0’,’4’,’0’,’0’,’0’,’9’};
/∗∗
∗calling the solver
∗/
public voidsolve() { show();search(0);show();
}
private voidshow() { for(inti=0;i<9;i++) {
for(intj=0;j<9;j++)
System.out.print(s[i∗9+j] ==’0’?".":s[i∗9+j]);
System.out.println();
}
System.out.println();
}
public booleantest(chard,intr,intc) { for(inti=0;i<9;i++)
if(s[9∗r+i] ==d||s[9∗i+c] ==d||s[9∗(r/3∗3+i/3)+(c/3∗3+i%3)] ==d) return false;
return true;
} /∗∗
∗backtrack search for a Sudoku solution
∗
∗@param p current position in string
∗@return true, if solution found, or false, if not
∗/
public booleansearch(intpos) { if(pos== 81)return true;
if(s[pos] >’0’) {
if(search(pos+1))return true;
} else
for(inti=0;i<9;i++)
if(test((char) (’1’+i),pos/9,pos%9)) { s[pos] = (char) (’1’+i);
if(search(pos+1))return true;
s[pos] = 0;
} return false;
}
Stefan Edelkamp (IAI) PI 1 – Imperativer Kern November 14, 2013 14 / 15
Programm 6:Ein Sudokuproblem-Löser.
public booleantest(chard,intr,intc) { for(inti=0;i<9;i++)
if(s[9∗r+i] ==d||s[9∗i+c] ==d||s[9∗(r/3∗3+i/3)+(c/3∗3+i%3)] ==d) return false;
return true;
}
public booleansearch(intpos) { if(pos== 81)return true;
if(s[pos] >’0’) {
if(search(pos+1))return true;
} else
for(inti=0;i<9;i++)
if(test((char) (’1’+i),pos/9,pos%9)) { s[pos] = (char) (’1’+i);
if(search(pos+1))return true;
s[pos] = 0;
} return false;
} }