Erstellung matrix von zahlen, die einzigartig in Zeile und Spalte
Wenn dir ein besserer Titel nach der Lektüre die Frage, bitte fühlen Sie sich frei, es zu ändern.
So, als input habe ich eine ganze Zahl, die eine gerade Zahl zwischen 2 und 20. Nennen wir diese ganze Zahl $teams
. Was ich tun müssen, ist erzeugen eine $teams x $teams
große matrix von zahlen zwischen 1 und $teams-1
(inklusive) unter Beachtung der folgenden Regeln:
- Der diagonalen (von oben Links nach unten rechts) hat den Wert -1.
- Die gleiche Nummer erscheinen nicht in der gleichen Spalte oder Zeile mehr als einmal.
- Wenn eine Nummer angezeigt, die in Spalte N, im Mai dann nicht angezeigt, in der Zeile N. Zum Beispiel, wenn es erscheint in der Spalte #2, kann es nicht angezeigt wird in der Zeile #2, etc.
Beachten Sie, dass wir nur den Blick auf den Teil oberhalb der Diagonale. Der Teil darunter ist nur ein Spiegelbild der, dass (jede Zahl ist die Reflexion + $teams - 1), und es spielt keine Rolle für dieses problem.
Den ersten 2 Bedingungen waren relativ einfach zu bewerkstelligen, aber der 3. ist, mich zu töten. Ich weiß nicht, wie es geschehen zu lassen, vor allem, da die $teams
Nummer könnte jede gerade Zahl zwischen 2 und 20. Der code, der eine korrekte Ausgabe für die Bedingungen 1 und 2 ist unten gegeben. Kann mir jemand helfen mit Bedingung Nummer 3?
$teams = 6; //example value - should work for any even Int between 2 and 20
$games = array(); //2D array tracking which week teams will be playing
//do the work
for( $i=1; $i<=$teams; $i++ ) {
$games[$i] = array();
for( $j=1; $j<=$teams; $j++ ) {
$games[$i][$j] = getWeek($i, $j, $teams);
}
}
//show output
echo '<pre>';
$max=0;
foreach($games as $key => $row) {
foreach($row as $k => $col) {
printf('%4d', is_null($col) ? -2 : $col);
if($col > $max){
$max=$col;
}
}
echo "\n";
}
printf("%d teams in %d weeks, %.2f weeks per team\n", $teams, $max, $max/$teams);
echo '</pre>';
function getWeek($home, $away, $num_teams) {
if($home == $away){
return -1;
}
$week = $home+$away-2;
if($week >= $num_teams){
$week = $week-$num_teams+1;
}
if($home>$away){
$week += $num_teams-1;
}
return $week;
}
Den aktuellen code (für $teams=6) gibt die folgende Ausgabe:
-1 1 2 3 4 5
6 -1 3 4 5 1
7 8 -1 5 1 2
8 9 10 -1 2 3
9 10 6 7 -1 4
10 6 7 8 9 -1
6 teams in 10 weeks, 1.67 weeks per team
Wie Sie sehen, wird die Zahl 1 angezeigt, sowohl in der 2. Spalte und 2. Zeile, die Zahl 4 erscheint sowohl in der 5. Spalte und 5. Zeile usw, die Pausen-Regel #3.
- Vielleicht gibt es einfachere Lösungen, aber man konnte einen Blick auf backtracking: en.wikipedia.org/wiki/Backtracking
- Danke, aber ich würde eher zu entdecken einfacher, die möglichen Lösungen zuerst. Backtracking sieht aus wie es könnte auf jeden Fall lösen es, aber würde eine Menge Aufwand und scheint nicht sehr effizient in Bezug auf die Anzahl der Iterationen (wenn das nicht zu viel von einem Problem bei der geringen Anzahl von $teams).
- Eine Sache, die mir eingefallen ist, als Sie sagte: "die Nummer wird in der n-TEN Spalte", und bezieht sich auf den
nth collumn
von der ersten Zeile. Nun, wissen Sie, dass in der ersten Zeile haben Sie die zahlen von-1
zun-1
. Beim generieren der zahlen für Zeile Nummerx
können Sie einfach überspringen Sie die Zahl, die in$games[1][x]
. Hoffe, das hilft etwas 😉 - Werde ich versuchen, danke. Ich vermute, dass die Letzte Zeile eine falsche Eingabe obwohl, da gibt es keine Wahl an dieser Stelle.
- aber die Letzte Zeile ist unter der diagonalen, und Sie sagte nur, die Einträge oben sind relevant oder habe ich etwas falsch gemacht? 😉
- Ich meine die Zeile oberhalb der letzten, sorry - das einzige, wo Nummer 4 ist den ganzen Weg auf der rechten Seite in meinem Beispiel. Für die, die eine Zahl, es ist nicht eine Wahl, so wird es das sein, was übrig ist, nachdem die anderen gefüllt sind, so gibt es keine Möglichkeit zu wissen, ob es wird richtig sein (denke ich).
- Ich würde sagen, versuchen, die richtige Lösung zu erreichen, die auf einem Stück Papier zuerst, um dann zu schauen, ob Sie extrahieren können einige Abhängigkeiten zwischen den zahlen in den Zeilen und Spalten, die würde führen Sie zu den richtigen Algorithmus.
- Ist das nicht eine Variante des n-Damen-problem? en.wikipedia.org/wiki/Eight_queens_puzzle
- Es ist ähnlich, aber ich würde nicht nennen es eine Variante, wie meine Dritte Bedingung, die Sie trennt - in der 8-Damen-problem, es ist notwendig für die Königinnen erscheinen in jeder Spalte und Zeile nur einmal, sondern per definition, dass auch Pausen-Regel #3 mein problem ist, wie zum Beispiel, es gibt eine Königin die beiden in Zeile 2 und Spalte B (sprechen in Schach AGB).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube nicht, dass es eine deterministische Art und Weise, dieses problem zu lösen, ohne dass Ihr Programm noch einige trial-and-error (zu raten und dann backtracking, falls die Vermutung Konflikte mit den Regeln).
Meine Idee ist, ändern Sie nur die getWeek () - Funktion auf, übergeben aber die
$games
array, dann:Getestet habe ich es für 4, 6, 8, 10 und 20 teams, und es funktionierte perfekt. Ich lege einen Sicherheits-Mechanismus, der
$week
auf 0, im Falle der while-Schleife droht zu einer unendlichen, aber das wird nicht passieren.Hier ist der gesamte code:
getWeek
Funktion:- Und das ist das Ergebnis für
$teams=10
:Kann die Frage gelöst werden, ohne das schätzen oder die backtracing durch die Schaffung eines round-robin-Zeitplan für die n-teams spielen gegen einander in n Runden, dann von diesem build ein array mit den Zeitplan wie beschrieben in der Frage
Bauen Sie den Zeitplan Ort der n (hier 6) teams, die in zwei Reihen
Dies ist Runde 1, wo 1 erfüllt 6, 2 erfüllt, 5, und 3 erfüllt 4.
Dann für jede Runde, drehen die teams, außer team 1, was den kompletten Zeitplan
Diese können dargestellt werden als ein array mit jeder Zeile, die eine Woche, in der das team in der ersten Spalte trifft sich das team in der letzten Sekunde erfüllt die vorletzte usw.
Vertreter der teams, die als Zeilen und Spalten, mit Wochen, wie die Einträge der Tabelle, diese wird
Folgende code ist der code zu generieren, diese für verschiedene Anzahl teams:
buildSchedule
. Dies ist möglich, da jede Zeile erfüllt requrements #2 und #3 (jedes team spielt nur ein match in einer Woche).Ist eine Lösung, um pass zu
getWeek()
ein array mit den zahlen, die Sie ausschließen möchten (ie. ein array mit allen zahlen, die auf der Spalte entspricht der aktuellen Zeile).Können Sie erstellen so eine exclude-array und übergibt es an
getWeek()
wie diese:Dann was übrig bleibt, ist zu prüfen, in
getWeek()
nicht include eine der zahlen übergeben, in der$exclude
array, so etwas wie dieses:$exclude
array zeigen nicht die richtigen Werte, und außerdem, was ist$your_new_valid_value
? Als jovan die Antwort zeigt, ich denke, es muss eine while-Schleife gibt es nicht eine if-Bedingung.AKTUALISIERT: ich habe versucht, zu implementieren eine Lösung mit backtracking. Der code könnte wahrscheinlich ein umschreiben (vielleicht eine Klasse) und Dinge, die optimiert werden konnten.
Die Idee ist ein Spaziergang durch alle Lösungen, aber halt eine Filiale, sobald klar wird, dass der Zweig bricht eine der drei Regeln. Mit 6 teams, eine Lösung gefunden werden, in 71 versucht - auch wenn es theoretisch besteht 759,375 Kombinationen.
Sehen http://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF für die Berechnung der Gesamt-Spiele benötigt.
Er druckt:
$teams-1
oberhalb der Diagonale.$teams-1
Teil.