import Data.STRef.Lazy
import Data.Array.ST (STArray, newArray, readArray, writeArray)
import Data.Array.IArray (listArray)
import Data.Array.Unboxed (UArray, (!))
import Control.Monad.ST.Lazy
import Control.Monad (replicateM, forM_, when)
import Data.List
--import System.IO.Unsafe (unsafePerformIO)
data DNode s = DNode {left, right, up, down, ctl :: STRef s (DNode s),
size :: STRef s Int,
row, col :: Int} | Null
instance Eq (DNode s) where
--Null == Null = True
--Null == (DNode _ _ _ _ _ _ _ _) = False
--(DNode _ _ _ _ _ _ _ _) == Null = False
a == b = row a == row b && col a == col b
newDNode l r u d size row col =
do l' <- newSTRef l
r' <- newSTRef r
u' <- newSTRef u
d' <- newSTRef d
ctl' <- newSTRef Null
size' <- newSTRef size
return (DNode l' r' u' d' ctl' size' row col)
getAttr :: (DNode s -> STRef s a) -> DNode s -> ST s a
getAttr dir node = readSTRef (dir node)
setAttr :: (DNode s -> STRef s a) -> DNode s -> a -> ST s ()
setAttr dir node = writeSTRef (dir node)
buildDLX :: [UArray Int Bool] -> Int -> Int -> ST s (DNode s)
buildDLX bitmap nrow ncol =
do chead <- newArray (0, ncol - 1) Null :: ST s (STArray s Int (DNode s))
h <- newDNode Null Null Null Null 0 (-1) (-1)
setAttr left h h
setAttr right h h
setAttr up h h
setAttr down h h
forM_ [0..ncol-1] $ \j -> do
hl <- getAttr left h
p <- newDNode hl h Null Null 0 (-1) j
setAttr right hl p
setAttr left h p
setAttr up p p
setAttr down p p
writeArray chead j p
rhead <- newDNode Null Null Null Null 0 0 (-1)
forM_ (zip [0..nrow-1] bitmap) $ \(i, row) -> do
setAttr left rhead rhead
setAttr right rhead rhead
forM_ [0..ncol-1] $ \j -> do
if row ! j then do
rl <- getAttr left rhead
ct <- readArray chead j
cs <- getAttr size ct
setAttr size ct (cs + 1)
cu <- getAttr up ct
p <- newDNode rl rhead cu ct 0 i j
setAttr right rl p
setAttr left rhead p
setAttr down cu p
setAttr up ct p
setAttr ctl p ct
else return ()
rl <- getAttr left rhead
rr <- getAttr right rhead
setAttr right rl rr
setAttr left rr rl
return h
forEach step start f = step start >>= loop
where loop now = when (now /= start) (f now >> step now >>= loop)
forEach' step start f = step start >>= loop
where loop now = if now /= start then do
r <- f now
rs <- step now >>= loop
return (r:rs)
else return []
setCover :: DNode s -> ST s ()
setCover pctl =
do cl <- getAttr left pctl
cr <- getAttr right pctl
setAttr right cl cr
setAttr left cr cl
forEach (getAttr down) pctl $ \p ->
forEach (getAttr right) p $ \q -> do
qu <- getAttr up q
qd <- getAttr down q
qct <- getAttr ctl q
qcs <- getAttr size qct
setAttr down qu qd
setAttr up qd qu
setAttr size qct (qcs - 1)
setUncover :: DNode s -> ST s ()
setUncover pctl =
do cl <- getAttr left pctl
cr <- getAttr right pctl
setAttr right cl pctl
setAttr left cr pctl
forEach (getAttr up) pctl $ \p ->
forEach (getAttr left) p $ \q -> do
qu <- getAttr up q
qd <- getAttr down q
qct <- getAttr ctl q
qcs <- getAttr size qct
setAttr down qu q
setAttr up qd q
setAttr size qct (qcs + 1)
solve bitmap ncol =
runST $ do dlx <- buildDLX bitmap (length bitmap) ncol
solve' dlx 0 []
where solve' head step plan =
do hl <- getAttr left head
if hl == head then
return [plan]
else do
best <- newSTRef (9999, Null)
forEach (getAttr right) head $ \p -> do
sp <- getAttr size p
(m, y) <- readSTRef best
when (sp < m)
(writeSTRef best (sp, p))
(m, y) <- readSTRef best
--y <- getAttr right head
setCover y
res <-
forEach' (getAttr down) y $ \p -> do
forEach (getAttr right) p $ \q -> do
qctl <- getAttr ctl q
setCover qctl
r' <- solve' head (step + 1) (row p:plan)
forEach (getAttr left) p $ \q -> do
qctl <- getAttr ctl q
setUncover qctl
return r'
setUncover y
return (concat res)
sudoku :: [[Int]] -> [[[Int]]]
sudoku prob = [[[d | y <- [0..blockN - 1],
d <- [1..blockN],
(x, y, d) `elem` pos] |
x <- [0..blockN - 1],
let pos = map (\x -> all!!x) sol] | sol <- solve bitmap colN]
where sudokuN = 3
blockN = sudokuN ^ 2
secN = blockN ^ 2
colN = secN * 4
fixed = filter (\(_, _, d) -> d /= 0) $
concatMap (\(r, l) -> (zipWith (\c x -> (r, c, x)) [0..]) l) (zip [0..] prob)
fixedPos = map (\(a, b, _) -> (a, b)) fixed
all = fixed ++ [(x, y, d) | x <- [0..blockN - 1], y <- [0..blockN - 1],
d <- [1..blockN], (x, y) `notElem` fixedPos]
makeBits [] n = replicate n False
makeBits (x:xs) n = replicate x False ++ (True:makeBits (map (\t -> t - x - 1) xs) (n - x - 1))
bitmap = [listArray (0, colN - 1) $
makeBits [x * blockN + y,
secN + ((x `div` sudokuN) * sudokuN + y `div` sudokuN) * blockN + d - 1,
secN * 2 + x * blockN + d - 1,
secN * 3 + y * blockN + d - 1] colN | (x, y, d) <- all]
split _ [] = []
split c s
| s' == [] = []
| otherwise = let (h, rest) = span (/= c) s' in h:split c rest
where s' = snd $ span (== c) s
main = do lines <- replicateM 9 getLine
let prob = map (\l -> map read (split ' ' l) :: [Int]) lines
forM_ (sudoku prob) $ \sol -> do
putStrLn $ intercalate "\n" (map (\l -> intercalate " " (map show l)) sol) ++ "\n"