Advertisement
Guest User

Untitled

a guest
Dec 9th, 2016
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.33 KB | None | 0 0
  1. --Assignment E
  2.  
  3. type Pos = (Int,Int)
  4.  
  5. --returns a list of postions for all the blanks in the sudoku
  6. blanks :: Sudoku -> [Pos]
  7. blanks sud = [(x,y) | x<-[0..8], y<- [0..8] , (((rows sud) !! x)!! y)==Nothing ]
  8.  
  9. --Property for testing if all the positions returned from blanks are actully blanks in the Sudoku
  10. prop_IsAllBlank :: Sudoku -> Bool-- FEL
  11. prop_IsAllBlank sud = all member (blanks sud) where
  12. member x = (((rows sud)!! (fst x)) !! (snd x)) == Nothing
  13.  
  14. --updates the given list with a value at an index
  15. (!!=) :: [a] -> (Int,a) -> [a]
  16. (!!=) l (i,e) | i <length l && i>=0 = take (i) l ++ e:(drop (i+1) l)
  17. | otherwise = l
  18.  
  19. --test if the list is equally large after/before the use of !!= and prop_exchangedItem
  20. prop_update_elem :: [String] -> (Int,String) -> Bool
  21. prop_update_elem l (i,e) = length l == length ( l !!= (i,e)) && prop_exchangedItem l (i,e)
  22.  
  23. --tests if the given index has changed to the correct value (when the index is allowed)
  24. prop_exchangedItem :: [String] -> (Int,String) -> Bool
  25. prop_exchangedItem l (i,e) | i <length l && i>=0 = (l !!= (i,e)) !! i == e
  26. | otherwise = True
  27.  
  28. --tests if all the other elements remain unchanged
  29. prop_allElem :: [String] -> (Int,String) -> Bool
  30. prop_allElem l (i,e) = take i l ++ drop (i+1) l == take i (l !!= (i,e)) ++ drop (i+1) (l !!= (i,e))
  31.  
  32. --updates a specific postion in a Sudoku, given that the index is valid
  33. update :: Sudoku -> Pos -> Maybe Int -> Sudoku
  34. update sud (row,col) e | checkSizes row && checkSizes col = Sudoku (rows sud !!= (row,updatedE))
  35. | otherwise = error "postion out of sudoku index" where
  36. checkSizes a = a>=0 && a<9
  37. updatedE = (rows sud !! row) !!= (col,e)
  38.  
  39. --tests that if the pos is within the sudoku, if the sudoku updates the sudoku with the correct element
  40. prop_update :: Sudoku -> Pos -> Maybe Int -> Bool
  41. prop_update sud (row,col) e | (checkSize row) && (checkSize col) = ((rows (update sud (row,col) e) !! row) !! col == e)
  42. | otherwise = True where
  43. checkSize a = a>=0 && a<9
  44.  
  45. --gets the possible candidates for a blank position, pos should be a blank pos in the sudoku
  46. candidates :: Sudoku -> Pos -> [Int]
  47. candidates (Sudoku l) (row,col) = [1..9] \\ (nub (rowPossible l row ++ rowPossible (transpose l) col ++ blocksPossible l (row,col)))
  48.  
  49. --fetches a row and returns all the element's that are Just n
  50. rowPossible :: [[Maybe Int]] -> Int -> [Int]
  51. rowPossible l row = map fromJust [ el | el<-((l) !! row), el /= Nothing]
  52.  
  53. --returns the block that the position belongs to, and that are Just n
  54. blocksPossible :: [[Maybe Int]] -> Pos -> [Int]
  55. blocksPossible l (row,col) = map fromJust (delete Nothing (nub (getBlock (reduce row) (reduce col) (Sudoku l)))) where
  56. reduce a | a==0 || a==3 || a==6 = a
  57. | otherwise = reduce (a-1)
  58.  
  59. --checks if the suduko still follow the rules aftet an update of a blank pos.
  60. prop_candidates :: Sudoku -> Bool
  61. prop_candidates sud | isSudoku sud && isOkay sud = and [ checkOne x | x<-candidates sud pos ]
  62. | otherwise = True where
  63. checkOne x = isSudoku (updSud x) && isOkay (updSud x)
  64. updSud x = update sud pos (Just x)
  65. pos = head (blanks sud)
  66.  
  67.  
  68. --Assignment F
  69.  
  70. --Solves a Sudoku
  71. solve :: Sudoku -> Maybe Sudoku
  72. solve sud | isOkay sud && isSudoku sud = solve' sud (candidates sud (head (blanks sud)))
  73. | otherwise = Nothing
  74.  
  75. --recursive function to solve the sudoku which uses backtracking, takes a sudoku and a list of candidates for
  76. --the first blank position in the sudoku.
  77. solve' :: Sudoku -> [Int] -> Maybe Sudoku
  78. solve' sud [] = Nothing
  79. solve' sud (c:cs) = if isSolved newSud then Just newSud -- returns the sudoku if found a solution
  80. else if isJust ret then ret --searches for a possible solution recursively
  81. else solve' sud cs where -- tries another candidate if the first one doesn't succeed.
  82. newSud = (update sud (head (blanks sud)) (Just c)) -- updates the sudoku with the first candidate
  83. ret = solve' newSud (candidates newSud (head (blanks newSud))) -- recursively searches for a solution
  84.  
  85. --reads, solves and prints the Sudoku
  86. readAndSolve :: FilePath -> IO ()
  87. readAndSolve path = do sud <- readSudoku path
  88. if (solve sud) == Nothing then putStr "No solution found"
  89. else printSudoku (fromJust (solve sud))
  90.  
  91. --checks if the first Sudoku is a solution of the second sudoku
  92. isSolutionOf :: Sudoku -> Sudoku -> Bool
  93. isSolutionOf sol sud = isOkay sol && isSolved sol && checkSol sol sud where
  94. checkSol sol sud = and [ checkEle x y (rows sol) (rows sud) | x<-[0..8],
  95. y<-[0..8], ((rows sud) !! x) !! y /=Nothing] where
  96. checkEle x y sol sud = ((sud!! x) !! y) == ((sol!! x) !! y)
  97.  
  98. --Property for testing isSolutionOf, discards the invalid sudokus
  99. prop_SolveSound :: Sudoku -> Property
  100. prop_SolveSound sud = isSudoku sud && isOkay sud ==> ((fromMaybe sud (solve sud)) `isSolutionOf` sud)
  101.  
  102. fewerChecks prop = quickCheckWith stdArgs{ maxSuccess = 30 } prop
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement