Die Programmiersprache Ruby (German Edition)
angegebenen Zeile zurückgeben
def rowdigits(row)
# Das Teil-Array extrahieren, das die Zeile darstellt, und alle
# Nullen entfernen. Array-Subtraktion bildet eine Mengendifferenz
# mit Entfernung von Duplikaten.
@grid[row*9,9] - [0]
end
# Ein Array aller bekannten Werte in der angegebenen Spalte
# zurückgeben
def coldigits(col)
result = [] # Mit einem leeren Array beginnen
col.step(80, 9) {|i| # Schleife von col bis 80 in Neunerschritten
v = @grid[i] # Wert der Zelle bei diesem Index ermitteln
result << v if (v != 0) # Ans Array anfügen, falls nicht 0
}
result # Das Array zurückgeben
end
# Boxnummer dem Index der linken oberen Ecke der Box zuordnen
BoxToIndex = [0, 3, 6, 27, 30, 33, 54, 57, 60].freeze
# Array aller bekannten Werte in der angegebenen Box zurückgeben
def boxdigits(b)
# Boxnummer in den Index der linken oberen Ecke der Box konvertieren
i = BoxToIndex[b]
# Ein Array von Werten ohne 0-Elemente zurückgeben
[
@grid[i], @grid[i+1], @grid[i+2],
@grid[i+9], @grid[i+10], @grid[i+11],
@grid[i+18], @grid[i+19], @grid[i+20]
] - [0]
end
end # Dies ist das Ende der Klasse Puzzle.
# Eine Ausnahme dieser Klasse zeigt ungültige Eingaben an.
class Invalid < StandardError
end
# Eine Ausnahme dieser Klasse zeigt an, dass ein Puzzle übermäßig
# beschränkt ist, so dass keine Lösung möglich ist.
class Impossible < StandardError
end
#
# Diese Methode scannt ein Puzzle und sucht nach unbekannten Zellen, die
# nur einen einzigen möglichen Wert haben. Wenn sie welche findet, setzt
# sie ihre Werte. Da das Ändern einer Zelle die möglichen Werte für andere
# Zellen verändert, fährt sie mit dem Scannen fort, bis sie das ganze
# Puzzle gescannt hat, ohne Zellen zu finden, deren Wert sie setzen kann.
#
# Diese Methode gibt drei Werte zurück. Wenn sie das Puzzle löst, sind
# alle drei Werte nil. Andernfalls sind die ersten beiden Rückgabewerte
# die Zeile und Spalte einer Zelle, deren Wert noch unbekannt ist. Der
# dritte Wert ist die Menge der möglichen Werte für diese Zeile und
# Spalte. Das ist eine Mindestmenge möglicher Werte: Es gibt keine
# Zelle im Puzzle, die weniger mögliche Werte hat. Dieser komplexe Rück-
# gabewert ermöglicht praktische Heuristik in der Methode solve(): Diese
# Methode kann Werte für Zellen so erraten, dass der erratene Wert
# mit größtmöglicher Wahrscheinlichkeit korrekt ist.
#
# Diese Methode löst Impossible aus, wenn sie eine Zelle findet, für
# die es keine möglichen Werte gibt. Das kann geschehen, wenn das
# Puzzle übermäßig beschränkt ist oder wenn die untenstehende Methode
# solve() falsch geraten hat.
#
# Diese Methode modifiziert das angegebene Puzzle-Objekt selbst.
# Wenn has_duplicates? beim Einstieg false ist, ist es auch beim
# Ausstieg false.
#
def Sudoku.scan(puzzle)
unchanged = false # Dies ist unsere Schleifenvariable.
# Schleife, bis wir das ganze Spielfeld ohne Änderung gescannt haben
until unchanged
unchanged = true # Annahme: Diesmal werden keine Zellen geändert
rmin,cmin,pmin = nil # Zelle mit kleinster möglicher Menge
min = 10 # Mehr als die maximale Anzahl Möglichkeiten
# Schleife über die Zellen mit unbekanntem Wert
puzzle.each_unknown do |row, col, box|
# Menge der Werte finden, die in diese Zelle passen könnten
p = puzzle.possible(row, col, box)
# Je nach Größe der Menge p verzweigen
# Wir beachten drei Fälle: p.size==0, p.size==1 und p.size > 1.
case p.size
when 0 # Keine möglichen Werte: Puzzle übermäßig beschränkt
raise Impossible
when 1 # Eindeutiger Wert gefunden, im Gitter setzen
puzzle[row,col] = p[0] # Position im Gitter auf den Wert setzen
unchanged = false # Änderung kennzeichnen
else # Für jede andere Anzahl von Möglichkeiten
# Die kleinste mögliche Menge von Möglichkeiten merken
# Aber nicht darum kümmern, ob wir diese Schleife wiederholen
if unchanged && p.size < min
min = p.size # Aktuelle kleinste Menge
rmin, cmin, pmin = row, col, p # Parallele Wertzuweisung
end
end
end
end
# Zelle mit der kleinsten Menge von Möglichkeiten zurückgeben
# Beachten Sie mehrere Rückgabewerte.
return rmin, cmin, pmin
end
# Ein Sudoku-Puzzle lösen, wenn möglich mit einfacher Logik, aber wenn
# nötig mit Brute-Force. Dies ist eine rekursive Methode. Sie gibt ent-
# weder eine Lösung zurück oder löst eine Ausnahme aus. Die Lösung wird
# als neues Puzzle-Objekt ohne
Weitere Kostenlose Bücher