Das schwierigste Sudoku der Welt

Neue Frage »

pintman Auf diesen Beitrag antworten »
Das schwierigste Sudoku der Welt
Ein finnischer Mathematiker behauptet, das schwierigste Sudoku der Welt entwickelt zu haben.

[attach]25188[/attach]

Könnt ihr es trotzdem lösen?

edit von sulo: Grafik als Dateianhang eingefügt, damit das Rätsel erhalten bleibt.
HAL 9000 Auf diesen Beitrag antworten »

Sooo schwer ist es nun auch wieder nicht. Augenzwinkern
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452
pintman Auf diesen Beitrag antworten »

Na dann mal her mit der Lösung. verwirrt
pintman Auf diesen Beitrag antworten »

Aber halt, die ist ja schon längst da. geschockt
HAL 9000 Auf diesen Beitrag antworten »

Ja wenn man so eine verknotete Optik hat (wie in deinem Avatar), da sieht man das nicht so schnell. Big Laugh
hawe Auf diesen Beitrag antworten »

Komme auf die gleiche Lösung, wer hätte das gedacht ;-)
muss allerdings gestehen, dass ich Excel dazu angelernt habe...
 
 
allahahbarpingok Auf diesen Beitrag antworten »

Also schwer ist bei Sudoku wohl Definitionssache. Thereotisch existieren simple Algorithmen, mit welchen man immer eine Lösung findet, falls es eine gibt Augenzwinkern Reines durch-x-en...
pintman Auf diesen Beitrag antworten »

Was meinst du mit "x-en"? Kannst du einen simplen Algorithmus zum Lösen kurz skizzieren?
IfindU Auf diesen Beitrag antworten »

Der "simpelste" und langsamste wird sein: Setze in jedes freie Feld jede mögliche Zahl ein und überprüfe und ob das Ergebnis eine Lösung ist.

Die gleiche Idee, aber deutlich schneller ist es per Backtracking zu implementieren. Du setzt zwar immer fortlaufend Zahlen ein, aber prüfst dabei immer, ob du damit nicht schon Regeln verletzt hast. Wenn ja, verbessere die Zahlen davor bis du wieder ein zulässiges Muster hast und setzt weiter fort.
HAL 9000 Auf diesen Beitrag antworten »

Zitat:
Original von IfindU
Die gleiche Idee, aber deutlich schneller ist es per Backtracking zu implementieren. Du setzt zwar immer fortlaufend Zahlen ein, aber prüfst dabei immer, ob du damit nicht schon Regeln verletzt hast. Wenn ja, verbessere die Zahlen davor bis du wieder ein zulässiges Muster hast und setzt weiter fort.

So ist es.


Ich hatte schon vor Jahren, als damals der Sudoku-Hype anfing, ein kleines Progrämmchen geschrieben, welches zwar nicht Sudokus vollständig lösen konnte (außer die ganz primitiven), aber zumindest folgende, an sich grob eintönige Hilfsarbeiten übernimmt:

1) Man kann ja für jedes Feld über seine Zugehörigkeit zu Zeile/Spalte/Subquadrat feststellen, welche Ziffern überhaupt noch in diesem Feld in Frage kommen.

2) Für jede Zeile/Spalte/Subquadrat und jede der Ziffern 1-9 (sofern nicht schon "gelöst" in der entsprechenden Subeinheit) schaut man nach, wie oft diese Ziffer in den per Punkt 1) ermittelten "Restmengen" vorkommt. Ist das nur einmal, dann ist auch dieses Feld mit dieser Ziffer gelöst.

Weiter habe ich das Programmfragment nicht ausgeführt, aber die dann anstehenden Fallunterscheidungen ("Branch") kann man dann wirklich mit Brute-Force (und erneutem "Bound" per 1) und 2)) bewältigen, ohne dass die Sache zu sehr ausufert.
Bernhard1 Auf diesen Beitrag antworten »

Zitat:
Original von IfindU
Der "simpelste" und langsamste wird sein: Setze in jedes freie Feld jede mögliche Zahl ein und überprüfe und ob das Ergebnis eine Lösung ist.

So etwas wäre nicht nur langsam, sondern zu langsam. Selbst wenn ein PC mit einer Taktrate von 10GHz pro Takt eine Möglichkeit ausprobieren könnte, würde dieser Rechner etwa 1e39 Jahre für dieses Vorhaben benötigen Big Laugh .
Bernhard1 Auf diesen Beitrag antworten »

Zitat:
Original von HAL 9000
Weiter habe ich das Programmfragment nicht ausgeführt, aber die dann anstehenden Fallunterscheidungen ("Branch") kann man dann wirklich mit Brute-Force (und erneutem "Bound" per 1) und 2)) bewältigen, ohne dass die Sache zu sehr ausufert.

Hi HAL,

in welcher Programmiersprache ist das denn geschrieben? Existiert der Code noch? Hättest Du Lust das Fragment bei sourceforge.net zu veröffentlichen? Man könnte es dann als Freizeitprojekt weiterentwickeln und im "Endstadium" auf das hier vorgeschlagene Sudoku loslassen.

EDIT: PS: Genaugenommen wäre ich persönlich nur an C/C++ interessiert.
HAL 9000 Auf diesen Beitrag antworten »

Zitat:
Original von Telefonmann1
in welcher Programmiersprache ist das denn geschrieben? Existiert der Code noch?

In gutem alten C, und ja, der Code existiert noch. Allerdings ist wirklich nicht viel dabei, ich hab ja eigentlich alles oben beschrieben, was da gemacht wurde.

Es würde mich eigentlich sehr wundern, wenn in den 6 Jahren, seit ich das geschrieben habe, nicht schon was besseres - auch im Freeware-Bereich - veröffentlicht wurde? Ich hab allerdings nichts dazu jetzt recherchiert, weil mich das Thema auch nicht sonderlich interessiert.
Bernhard1 Auf diesen Beitrag antworten »

Für die ganz Eiligen gibt es tatsächlich einen interessanten Online-Solver. Für das hier vorgestellte Sudoku braucht dieser Solver weniger als eine Sekunde.

http://www.sudoku-lobby.de/sudoku-loesung/sudoku.sudoku?IDraster=430708
hawe Auf diesen Beitrag antworten »

Meine Lösung in VBA benutzt einige einfache Lösungsstrategien wie "Sichtbares/verstecktes Einzelfel" usw. und wenn ich damit nicht weiterkomme versucht ich per Rateversuch und Backtracking weiterzumachen.
Die meisten als "schwer", "mega schwer", usw. bezeichneten Sudokus benötigen wenige Sekungen (Rateversuche). Für diese Version arbeitet der VBA-Interpreter ca 60 Sekunden mit Anzeige aller Lösungsschritte...
RavenOnJ Auf diesen Beitrag antworten »

Ich habe gerade eben diesen Thread entdeckt.

Zitat:
Original von Telefonmann1

in welcher Programmiersprache ist das denn geschrieben? Existiert der Code noch? Hättest Du Lust das Fragment bei sourceforge.net zu veröffentlichen? Man könnte es dann als Freizeitprojekt weiterentwickeln und im "Endstadium" auf das hier vorgeschlagene Sudoku loslassen.

EDIT: PS: Genaugenommen wäre ich persönlich nur an C/C++ interessiert.


Falls du immer noch an einem Programm interessiert wärst: Ich hätte eins, allerdings in Java, was aber für einen C++-Kenner kein Problem sein sollte. Hab ich mal vor Jahren geschrieben. So was lohnt sich nicht als "Projekt". Ich hatte damals, wenn ich mich richtig erinnere, etwa zwei bis drei Stunden für das Ganze gebraucht. Es liefert in weniger als 1 Sekunde die Lösung deines "schwierigsten Sudokus der Welt".
wernerwilligustav Auf diesen Beitrag antworten »
RE: Das schwierigste Sudoku der Welt
Bitte schöööön. Gelöst mit Backtracking. Meines Wissens besteht die am dünnsten besetzte, eindeutig lösbare Variante aus 17 Einträgen. Das sind hier mehr.
RavenOnJ Auf diesen Beitrag antworten »

Ein kleines Haskell-Programm. Enthält ein wenig überflüssiges Beiwerk für verschiedene Datenformate usw.. Hatte keine Lust das zu streamlinen. Lösung dauert im Interpreter je nach Schwierigkeitsgrad bis zu einer halben Minute. Kompiliert dagegen etwa 1 sec. (Aufruf alles in einer Zeile; das matheboard-rendering macht daraus zwei ?!?)
solveS " 800000000003600000070090200050007000000045700000100030001000068008500010090
000400"
ergibt als Lösung
["812753649","943682175","675491283","154237896","369845721","287169534","521974368","438526917","796318452"]

Oder kompiliert (Programm: Sudoku.exe):
Sudoku 800000000003600000070090200050007000000045700000100030001000068008500010090
000400
ergibt
812753649943682175675491283154237896369845721287169534521974368438526917796
318452
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
module Sudoku where

import Data.Char (digitToInt)
import System.Environment (getArgs)

type Row a = [a]
type Column a = [a]
type Matrix a = [Row a]
type Digit = Int
type Grid = Matrix Digit
type CharGrid = Matrix Char

class Blank a where
   blank :: a->Bool

instance Blank Char where
    blank c = c == ' ' || c == '0'

instance Blank Int where
   blank n = n==0

digits = [1..9]

toDigits :: [Char] -> [Int]
toDigits [] = []
toDigits (c:cs) | blank c = 0 : toDigits cs
                | otherwise = digitToInt c : toDigits cs

toChars :: [Int] -> [Char]
toChars [] = []
toChars (x:xs) | x<0 || x >9 = error "number must be in the range 0 to 9"
               | blank x = '0' : toChars xs
               | otherwise = "0123456789" !! x : toChars xs

-- Die üblichen 9er-Zeilen; die Daten liegen in einem String vor, ohne Lösung. 
-- Format: ein String aus 81 Ziffern, 0 bis 9. Ungesetzte Felder sind 0 
stringToCharGrid :: String -> CharGrid
stringToCharGrid [] = []
stringToCharGrid s = (take 9 s) : stringToCharGrid (drop 9 s)

charGridToDigits :: CharGrid -> Grid
charGridToDigits [] = []
charGridToDigits (r:rs) = toDigits r : charGridToDigits rs

intGridToChars :: Grid -> CharGrid
intGridToChars [] = []
intGridToChars (r:rs) = toChars r : intGridToChars rs

nodups :: Eq a => [a] -> Bool
nodups [] = True
nodups [x] = True
nodups (x:xs) = all (/=x) xs && nodups xs

-- Liste muss sortiert sein
removeDups :: (Eq a) => [a] -> [a]
removeDups [] = []
removeDups [x] = [x]
removeDups (x:xs) | x == head xs = x: removeDups (tail xs)
                 | otherwise = x : removeDups xs

rows :: Matrix a -> Matrix a
rows = id

cols  :: Matrix a -> Matrix a
cols [] = []
cols [xs] = [[x] | x <- xs]
cols (xs:xss) = zipWith (:) xs (cols xss)

boxs :: Matrix a -> Matrix a
boxs = map ungroup . ungroup . map cols . group . map group

group :: [a] -> [[a]]
group [] = []
group xs = take 3 xs : group (drop 3 xs)

ungroup :: [[a]] -> [a]
ungroup = concat

pruneRow :: Row [Digit] -> Row [Digit]
pruneRow row = map (removeFixed fixed) row
                   where fixed = [d | [d] <- row]

removeFixed :: [Digit] -> [Digit] -> [Digit]
removeFixed ds [x] = [x] -- fixierte Zellen sollen erhalten bleiben
removeFixed ds xs = filter (`notElem` ds) xs --  alles aus xs entfernen, was in ds enthalten

{- die Funktion f kann eine von rows, cols oder boxs sein.
   Die Boxes und Columns werden zuerst in Zeilen transformiert, worauf dann pruneRow angewendet wird. 
   Hernach wieder Rückwandlung. Möglich, wenn  f.f = id gilt, was hier immer der Fall ist.
-}
pruneBy  :: (Matrix [Digit] -> Matrix [Digit]) -> Matrix [Digit] -> Matrix [Digit]
pruneBy f = f . map pruneRow . f


prune :: Matrix [Digit] -> Matrix [Digit]
prune = pruneBy boxs . pruneBy cols . pruneBy rows

-- die Auswahlmöglichkeiten einer Zelle
choices :: Grid -> Matrix [Digit]
choices = map (map choice)


choice d = if blank d then digits else [d]

cp :: [[a]] -> [[a]]
cp [] = [[]]
cp (xs:xss) = [x:ys | x <- xs, ys <- yss]
                  where yss = cp xss

expand :: Matrix [Digit] -> [Grid]
expand = cp . map cp

many :: Eq a => (a->a) -> a -> a
many f x = if x == y then x else many f y
         where y = f x


isSingle :: [a] -> Bool
isSingle [_] = True
isSingle _ = False

expand1 :: Matrix [Digit] -> [ Matrix[Digit] ]
expand1 rows  = [rows1 ++ [row1 ++ [c]:row2] ++ rows2 | c <- cs]
                 where     
                   (rows1,row:rows2) = break (any smallest ) rows
                   (row1,cs:row2) = break  smallest row
                   smallest cs = length cs == n
                   n = minimum (lengthInCellNotOne rows)

lengthInCellNotOne :: Matrix [Digit] -> [Int]
lengthInCellNotOne = filter (/=1) . map length . concat

complete :: Matrix [Digit] -> Bool
complete = all (all isSingle)

safe :: Matrix [Digit] -> Bool
safe m = all ok (rows m) && all ok (cols m) && all ok (boxs m) 

ok :: Eq a => Row  [a] -> Bool
ok row = nodups [x | [x] <- row]

extract :: Matrix [Digit] -> Grid
extract = map (map head)

-- searchM mit many prune, search nur einfaches prune; nur experimentell, bringt nicht viel
searchM ::Matrix [Digit] -> [Grid]
searchM  cm 
    | not (safe pm) = []
    | complete pm = [extract pm]
    | otherwise = concat . map searchM. expand1 $ pm
          where pm = many prune cm

solveM :: Grid -> [Grid]
solveM =  searchM . choices

search :: Matrix [Digit] -> [Grid]
search cm 
    | not (safe pm) = []
    | complete pm = [extract pm]
    | otherwise = concat . map search . expand1 $ pm
       where pm = prune cm

solve :: Grid -> [Grid]
solve =  search . choices

solveC :: CharGrid -> [CharGrid]
solveC = map intGridToChars . solve . charGridToDigits

solveS s = head . solveC $ stringToCharGrid s

flattenGrid :: CharGrid -> String
flattenGrid [] = ""
flattenGrid cg = head cg ++ flattenGrid (tail cg)

putLines :: String -> IO ()
putLines [] = return ()
putLines s = putStrLn (take 9 s) >>= return (putLines (drop 9 s))

main = do 
          args <- getArgs
          let result = flattenGrid . solveS $ head args 
          putStrLn result
          putLines result
Neue Frage »
Antworten »



Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »