yingpotter

[99p]NonoGram

Aug 30th, 2011
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Data.List
  2.  
  3. ----- predefined consts and inputs
  4. type Matrix a = [[a]]
  5. type Board = Matrix Int
  6. type Puzzle a = ([[a]],[[a]])
  7.  
  8. nonopuz1 :: Puzzle Int
  9. nonopuz1 = ([[4]],[[1],[1],[1],[0]])
  10. nonopuz2 :: Puzzle Int
  11. nonopuz2 = ([[3],[2,1],[3,2],[2,2],[6],[1,5],[6],[1],[2]], [[1,2],[3,1],[1,5],[7,1],[5],[3],[4],[3]])
  12. nonopuz3 :: Puzzle Int
  13. nonopuz3 = ([[1],[3],[1]], [[1],[3],[1]])
  14. nonopuz4:: Puzzle Int
  15. nonopuz4 = ([[2],[2,2],[3],[1,1],[2]], [[2,2],[2,1],[1],[2],[3]])
  16. nonopuz5 :: Puzzle Int
  17. nonopuz5 = ([[6],[3],[3,1],[2,2],[2,3],[5],[4],[5],[2,5],[1,6]], [[5,2],[5,1],[3],[1],[1,1],[1,1,3],[5],[6],[7],[8]])
  18. nonopuz6 :: Puzzle Int
  19. nonopuz6 = ([[5,2,4],[3,9],[3,5],[3,4],[4,3],[1,2,2],[1,1,1],[9,1,1],[1,4,4],[1,4,2,1],[4,3],[6],[4,1],[1,1,3],[1,8]]
  20.            ,[[1,2,3,2],[8,2],[5,8],[3,9],[1,1,5],[6],[1,1],[3,2,3],[4,2,1,1],[4,3,1],[4,4,1],[5,2],[2,2],[2,1,2],[2,1,1,1,1]])
  21. nonopuz7 :: Puzzle Int
  22. nonopuz7 = ([[6,1,1],[1,6,2],[1,8,2,2],[2,3,6],[1,1,3,2,3],[1,3,1,1,2],[3,2,1,1],[4,2,1],[5,3,2],[1,6,2],[6,2,1,2],[2,7,3,1,1,3],[2,6,7,3],
  23.              [3,7,6,3],[3,7,8,1],[3,9,3,4],[8,5,1],[4,8],[4,1,4,5],[3,4,1,3],[3,1,9],[1,2,3,8],[1,3,9],[2,1,13],[2,1,4,4]]
  24.            ,[[3,10,4],[1,9,2],[3,6],[1,6,3],[3,11,2,2],[1,13,4],[3,5,7,3],[6,9],[5,1,6,3],[8,1,7],[2,3,8],[3,2,5],[1,3,3,3],[1,3,2,3],[4,3],
  25.              [6,2],[4,1,3],[2,3,5],[1,2,5],[1,2,4],[2,2,2,7],[4,3,1,5],[4,3,7],[4,7,7],[4,7,6]])          
  26. nonopuz8 :: Puzzle Int
  27. nonopuz8 = ([[2],[2],[2],[2]], [[2],[4],[2]])
  28. nonopuz9 :: Puzzle Int
  29. nonopuz9 = ([[2],[1,2],[1,1],[2],[1],[3],[3],[2,2],[2,1],[2,2,1],[2,3],[2,2]], [[2,1],[1,3],[2,4],[3,4],[4],[3],[3],[3],[2],[2]])
  30.  
  31. nonosol2 :: Board
  32. nonosol2 = [[-1,1,-1], [1,1,1], [-1,1,-1]]
  33. testtest :: Board
  34. testtest = [[-1,2],[-1,2,3],[2,3,4],[3,4,5],[4,5,-6],[5,-6,7],[-6,7,8],[7,8,9],[8,9,-10],[9,-10]]
  35.  
  36. ----- solution verification
  37. lineCal :: (Num a, Ord a) => [a] -> [Int]
  38. lineCal row  = map length $ filter (\xs -> (head xs > 0)) (groupBy (\x y -> (x > 0) == (y > 0)) row)
  39. veriSol :: (Num a, Ord a) => Puzzle Int -> [[a]] -> Bool
  40. veriSol puz brd = (fst puz == map lineCal brd) && (snd puz == map lineCal (transpose brd))
  41.  
  42. ----- solution permutation
  43. brdCreate :: Puzzle a -> Board
  44. brdCreate puz = replicate (length $ fst puz) $ replicate (length $ snd puz) 0
  45. choices :: Board -> Matrix [Int]
  46. choices brd = map (map choice) brd
  47.               where choice e = if (e == 0) then [-1, 1] else [e]
  48. matCart :: Matrix [a] -> [Matrix a]
  49. matCart = cartProd . (map cartProd)
  50.           where cartProd :: [[a]] -> [[a]]
  51.                 cartProd [] = [[]]
  52.                 cartProd (ls:lss) = [ x:xs | x <- ls, xs <- cartProd lss ]
  53. solPermu puz = filter (veriSol puz) ( matCart $ choices (brdCreate puz) )
  54.  
  55. ----- deduction solver
  56. labeling :: [Int] -> [Int]
  57. labeling clue = labeling' 1 clue
  58.                where labeling' n []     = [-n,-n]
  59.                       labeling' n (x:xs) = [-n,-n] ++ [n+1 .. n+x] ++ labeling' (n+x+1) xs
  60.  
  61. lbLinject :: [Int] -> [Int] -> [Int]
  62. lbLinject _ [] = []
  63. lbLinject clue curlabel = nub [snd x | x <- zippedlabelpair,  fst x `elem` curlabel]
  64.                           where zippedlabelpair = zip (labeling clue) (tail $ labeling clue)
  65. lbRinject :: [Int] -> [Int] -> [Int]
  66. lbRinject _ [] = []
  67. lbRinject clue curlabel = nub [fst x | x <- zippedlabelpair,  snd x `elem` curlabel]
  68.                           where zippedlabelpair = zip (labeling clue) (tail $ labeling clue)
  69.                          
  70. reduce :: [Int] -> Int -> [Int]
  71. reduce xs blkstat
  72.        |  blkstat == -1   = filter ( < 0 ) xs
  73.        |  blkstat == 1    = filter ( > 0 ) xs
  74.        |  blkstat == 0    = filter ( \x -> True ) xs
  75.  
  76. judgeLeft :: [Int] -> [Int] -> [[Int]]
  77. judgeLeft clue stats = judgeLeft' startlabel stats
  78.                       where startlabel = [-1,2]
  79.                             judgeLeft' :: [Int] -> [Int] -> [[Int]]
  80.                              judgeLeft' _ [] = []
  81.                             judgeLeft' curlabel (cur:curstats) = (reduce curlabel cur) : (judgeLeft' nextlabel curstats)
  82.                                                                   where nextlabel = lbLinject clue (reduce curlabel cur)
  83. judgeRight :: [Int] -> [Int] -> [[Int]]
  84. judgeRight clue stats = reverse ( judgeRight' startlabel (reverse stats) )
  85.                         where startlabel = take 2 (nub $reverse $labeling clue)
  86.                               judgeRight' :: [Int] -> [Int] -> [[Int]]
  87.                              judgeRight' _ [] = []
  88.                               judgeRight' curlabel (cur:curstats) = (reduce curlabel cur) : (judgeRight' nextlabel curstats)
  89.                                                                     where nextlabel = lbRinject clue (reduce curlabel cur)
  90. judgeMent :: [Int] -> [Int] -> [[Int]]
  91. judgeMent clue stats = map (\x -> (fst x) `intersect` (snd x)) (zip (judgeLeft clue stats) (judgeRight clue stats) )
  92. deterBlk :: [Int] -> Int
  93. deterBlk lblist
  94.           |  all (> 0) lblist  = 1
  95.           |  all (< 0) lblist  = -1
  96.           |  otherwise          = 0
  97.  
  98. lineSolve :: [Int] -> [Int] -> [Int]
  99. lineSolve clue stats
  100.           | clue == []    = replicate (length stats) (-1)
  101.           | otherwise     = if ([] `elem` lblists) then [] else (map deterBlk lblists)
  102.                             where lblists = (judgeMent clue stats)
  103.          
  104. rowsSolve :: [[Int]] -> Board -> Board
  105. rowsSolve _ [] = []
  106. rowsSolve (clue:rowclues) (stats:rowstats) = (lineSolve clue stats) : (rowsSolve rowclues rowstats)
  107.  
  108. allSolve :: Puzzle Int -> Board -> Board
  109. allSolve _ [] = []
  110. allSolve puz rowstats =  if ([] `elem` rowstats) then [] else
  111.                           ( transpose (rowsSolve (snd puz) $ transpose (rowsSolve (fst puz) rowstats)) )
  112.  
  113. fixPt :: Eq a => (a -> a) -> a -> a
  114. fixPt f x = if (x == f x) then x else (fixPt f $f x)
  115.  
  116. deduSolver :: Puzzle Int -> Board -> Board
  117. deduSolver puz statz = fixPt (allSolve puz) statz
  118.  
  119. ------ statz properties
  120. failSol :: Board -> Bool
  121. failSol statz = statz == []
  122. compSol :: Board -> Bool
  123. compSol statz = (statz /= []) && (and $map (all (/= 0)) statz)
  124. incompSol :: Board -> Bool
  125. incompSol statz = (statz /= []) && (or $map (any (== 0)) statz)
  126.  
  127. ------ guessing incompletes
  128. -- just replace first 0 with -1 and 1 (slow method)
  129. fstZero :: [Int] -> [[Int]]
  130. fstZero xs = [ x1 ++ [c] ++ x2 | c <- [-1,1] ]
  131.              where (x1,(x:x2)) = break (== 0) xs
  132. fzGuess :: Board -> [Board]
  133. fzGuess statz = [rows1 ++ [row] ++ rows2 | row <- fstZero row ]
  134.                 where (rows1, (row:rows2)) = break (0 `elem`) statz
  135.  
  136. ------ nonogram solver
  137. nonoSolver :: Puzzle Int -> Board -> [Board]
  138. nonoSolver puz statee
  139.     | failSol statz      = []
  140.     | compSol statz      = [statz]
  141.     | incompSol statz    = concatMap (nonoSolver puz) (fzGuess statz)
  142.     where statz = deduSolver puz statee
  143. nonoSolve  :: Puzzle Int -> [Board]
  144. nonoSolve puz = nonoSolver puz (brdCreate puz)
Advertisement
Add Comment
Please, Sign In to add comment