| Programmieraufgaben Hier wird regelmäßig eine neue Programmieraufgabe gestellt, die dann gelöst werden soll und in Zusammenarbeit mit den Moderatoren auch besprochen werden kann. |
Diskussion: Ein Schachbrett - acht Damen im Forum Programmieraufgaben, in der Kategorie Code Kitchen; Anzeige Eingereicht von JTron, mich wundert es, dass es diesen Klassiker noch nicht gab ;) Das Programm soll dem Benutzer ...
![]() |
| | #1 (permalink) |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Anzeige Eingereicht von JTron, mich wundert es, dass es diesen Klassiker noch nicht gab ;) Das Programm soll dem Benutzer alle Möglichkeiten zeigen, wie man 8 Damen auf einem Schachbrett platzieren kann, ohne dass sie sich gegenseitig bedrohen. Am besten so: 0 = leer 1 = dame 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Zur Erinnerung: eine Dame kann eine andere Figur sowohl horizontal, vertikal wie auch diagonal "bedrohen". D.h sie sollten sich nicht in die Quere kommen. Schöner wäre es natürlich, wenn das Programm das allgemeine Problem löst: n-Damen auf einem nXn Brett
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. |
| | |
| | #2 (permalink) |
| Senior Member Registriert seit: 10.03.07 ![]() Likes: 19 | Ich durfte das im ersten Semester im Informatikunterricht schon lösen in Setl2. Einfach am Anfang die Anzahl der Damen aendern und man kann beliebiege Feldgrößen berechnen. Ausgabe ist allerdings etwas anders als vorgegeben, hab keine Lust das jetzt noch anzupassen. Hier mal die Lösung ohne Kommentare: Code Angehängt noch die Datei mit Kommentaren. |
| | |
| | #4 (permalink) |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Ich habe hier eine etwas andere Lösungsmethode ("Heuristik"). Sie liefert zwar nur eine mögliche Lösung zurück, dafür aber auch für deutlich größere n der Trick besteht darin, eine für das jeweilige n passende Startgröße zu wählen - ist sie zu groß, wird bei kleineren n unnötig Zeit "verplempert", ist sie zu klein, wird bei größeren n zu wenig "Suchraum" abgedeckt und es dauert wiederum womöglichst viel zu lange. Start: java Main <populationsize> <n> Bsp: java Main 1000 8 um eine Lösung für ein 8x8 Brett zu erhalten Erfahrungswerte:Startgröße 1000 - 10000 sehr grobe Orientierungswerte für n=8 werden ~40ms - 260ms benötigt n=10 ~40 bis 200ms n=12 ~150 bis 1000ms n=20 ~500ms bis 10s (populationsize sollte ab n>=20 auf 10000 hochgeschraubt werden) n=50 ~ab 8sek Main.java Creature.java World.java Edit: eine Lösung für n=100 (ca 5 min) Vieles hängt von den gewählten Parametern ab. Zugegebenermaßen eignet sich das Verfahren eher dazu, möglichst schnell eine suboptiomale Lösung zu erhalten - insbesondere bei dem Schritt "99% optimal -> 100%" wird es sehr deutlich. Im Anhang die aktualierte Version+"binary"
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. |
| | |
| | #5 (permalink) |
| Guest Likes: | hier, musste selbst erstmal nachdenken und im internet schauen: Code: class NDamen def initialize(size) @size = size @brett = [] end def to_s versuch(0) end private def feld_frei(ix, iy) for i in 0..iy-1 if (@brett[i] == ix) || (((@brett[i].to_i)-ix).abs) == ((i - iy).abs) return false end end return true end def versuch(n) if n == @size print_one else for i in 0..@size-1 if feld_frei(i,n) @brett[n] = i versuch(n+1) end end end end def print_one for i in 0..@size-1 for j in 0..@size-1 if j == @brett[ i ] print "*" else print "." end end print "\n" end print "\n\n" gets end end x = NDamen.new(8) x.to_s |
|
| | #6 (permalink) |
| Registriert seit: 22.03.08 ![]() Likes: 0 | Nimmt als erstes Argument n an. Falls kein Argument übergeben wird, wird n von STDIN gelesen. n-Damenproblem auf n*n-Brett in perl ?: Wer auf Farbe steht, kann die outputField Funktion mit dieser hier ersetzen: Code: sub outputField {
use Term::ANSIColor qw(:constants);
my @field = @_;
my $switch = 1;
for (1 .. $n) {print "--"}
print "\n";
foreach my $rowRef (@field) {
foreach my $pos (@$rowRef) {
if ($switch) {print ON_RED}
else {print RESET}
$switch = not $switch;
if ($pos) {print "\@ "}
else {print " "}
}
print RESET, "\n";
unless ($n % 2) {$switch = not $switch}
}
} |
| | |
| | #7 (permalink) |
| Senior Member Registriert seit: 03.09.05 ![]() Likes: 0 | Hier noch 'ne Alternative zum Standard-Backtracking(jedoch auch nur eine Lösung pro Durchlauf): Man wählt eine zufällige Permutation und versucht diese durch Tauschen von Damen zu einer Lösung zu bringen. Damit kommt man dann sogar auf O(n^3) pro Permutation und für größere Bretter geht die Anzahl an benötigten Permutationen gegen 1. Vorsicht: unoptimiert und unsauber: nqueens.h nqueens.cpp main.cpp (können "glücksbedingt" mehr oder weniger stark variieren) n=100: 0.6s n=1000: 21.18s n=5000: 9:18min |
| | |
| | #8 (permalink) |
| auf die gefahr hin als noob oder ähnliches hingestellt zu werden^^ woher kommt bitte die imense zeitsteigerung von 1000 auf 5000 durchläufe? | |
| | |
| | #9 (permalink) |
| Senior Member Registriert seit: 03.09.05 ![]() Likes: 0 | Nunja, dass liegt daran, dass die Zeit nicht linear, sondern immernoch polynomiell(was schonmal ein großer Vorteil zum exponentiellen Backtracking-Algorithmus ist) ansteigt, d.h. verdoppelt man die Größe verdoppelt sich nicht die Zeit, sondern sie wächst stärker an.(Z.B. für x^3: 10^3=1000 50^3=125000) |
| | |
| | #10 (permalink) |
| Registriert seit: 21.04.08 ![]() Likes: 0 | Meine Java Lösung Code: import java.util.ArrayList;
import java.util.List;
public class Queenproblem {
public static void main(String[] args) {
Solver solver = new Queenproblem().new Solver(8);
System.out.println("Anzahl Lösungen: "+ solver.getSolutionCount());
System.out.println("\n"+ solver.printFields());
}
class Solver {
private int queensCount = 0;
private List<int[][]> solutions = null;
public Solver(int queensCount){
this.queensCount = queensCount;
this.solutions = new ArrayList<int[][]>();
this.doIt(0, 1, new int[8][8]);
}
private void doIt(int row, int queen, int[][] field){
if(queen > queensCount){
solutions.add(cloneField(field));
return;
}
for(int i=0; i<8; i++){
if(!isConflict(row, i, field)){
field[row][i] = queen;
doIt(row+1, queen+1, field);
field[row][i] = 0;
}
}
}
private boolean isConflict(int row, int col, int[][] field){
for(int i=0; i<8; i++){
for(int z=0; z<8; z++){
if(field[i][z] > 0){
if(i == row || z == col){ // selbe reihe oder selbe spalte
return true;
}
else if((i-z) == (row-col)){ // selbe diagonale lo->ru
return true;
}
else if((i+z) == (row+col)){ // selbe diagonale ro->lu
return true;
}
}
}
}
return false;
}
private int[][] cloneField(int[][] field){
int[][] clone = new int[8][8];
for(int i=0; i<8; i++){
clone[i] = field[i].clone();
}
return clone;
}
public int getSolutionCount(){
return solutions.size();
}
public String printFields(){
String returnString = "";
for(int[][] field : solutions){
for(int[] row : field){
for(int value : row) {
returnString += value +" ";
}
returnString += "\n";
}
returnString += "\n";
};
return returnString.substring(0,returnString.length()-2);
}
}
} |
| | |
| | #11 (permalink) | |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | BF (sucht alle Lösungen): primitiv besser Beide sind dazu geeignet, nach allen Lösungen zu suchen (sonst kann man sich auch eine bestimmte anzeigen lassen). Nur der erste ist eben etwas langsammer Suchen aller Lösungen (ok, ohne sie zu printen) für N=12 dauert 3 Sek, für N=13 ca. 21 Sekunden. Aufruf mit: solve(N,Result). Bsp: Zitat:
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. | |
| | |
![]() |
| - Anzeige - | |
| |
| Themen-Optionen | |
| Ansicht | |
| |