Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Assignment E
- type Pos = (Int,Int)
- --returns a list of postions for all the blanks in the sudoku
- blanks :: Sudoku -> [Pos]
- blanks sud = [(x,y) | x<-[0..8], y<- [0..8] , (((rows sud) !! x)!! y)==Nothing ]
- --Property for testing if all the positions returned from blanks are actully blanks in the Sudoku
- prop_IsAllBlank :: Sudoku -> Bool-- FEL
- prop_IsAllBlank sud = all member (blanks sud) where
- member x = (((rows sud)!! (fst x)) !! (snd x)) == Nothing
- --updates the given list with a value at an index
- (!!=) :: [a] -> (Int,a) -> [a]
- (!!=) l (i,e) | i <length l && i>=0 = take (i) l ++ e:(drop (i+1) l)
- | otherwise = l
- --test if the list is equally large after/before the use of !!= and prop_exchangedItem
- prop_update_elem :: [String] -> (Int,String) -> Bool
- prop_update_elem l (i,e) = length l == length ( l !!= (i,e)) && prop_exchangedItem l (i,e)
- --tests if the given index has changed to the correct value (when the index is allowed)
- prop_exchangedItem :: [String] -> (Int,String) -> Bool
- prop_exchangedItem l (i,e) | i <length l && i>=0 = (l !!= (i,e)) !! i == e
- | otherwise = True
- --tests if all the other elements remain unchanged
- prop_allElem :: [String] -> (Int,String) -> Bool
- prop_allElem l (i,e) = take i l ++ drop (i+1) l == take i (l !!= (i,e)) ++ drop (i+1) (l !!= (i,e))
- --updates a specific postion in a Sudoku, given that the index is valid
- update :: Sudoku -> Pos -> Maybe Int -> Sudoku
- update sud (row,col) e | checkSizes row && checkSizes col = Sudoku (rows sud !!= (row,updatedE))
- | otherwise = error "postion out of sudoku index" where
- checkSizes a = a>=0 && a<9
- updatedE = (rows sud !! row) !!= (col,e)
- --tests that if the pos is within the sudoku, if the sudoku updates the sudoku with the correct element
- prop_update :: Sudoku -> Pos -> Maybe Int -> Bool
- prop_update sud (row,col) e | (checkSize row) && (checkSize col) = ((rows (update sud (row,col) e) !! row) !! col == e)
- | otherwise = True where
- checkSize a = a>=0 && a<9
- --gets the possible candidates for a blank position, pos should be a blank pos in the sudoku
- candidates :: Sudoku -> Pos -> [Int]
- candidates (Sudoku l) (row,col) = [1..9] \\ (nub (rowPossible l row ++ rowPossible (transpose l) col ++ blocksPossible l (row,col)))
- --fetches a row and returns all the element's that are Just n
- rowPossible :: [[Maybe Int]] -> Int -> [Int]
- rowPossible l row = map fromJust [ el | el<-((l) !! row), el /= Nothing]
- --returns the block that the position belongs to, and that are Just n
- blocksPossible :: [[Maybe Int]] -> Pos -> [Int]
- blocksPossible l (row,col) = map fromJust (delete Nothing (nub (getBlock (reduce row) (reduce col) (Sudoku l)))) where
- reduce a | a==0 || a==3 || a==6 = a
- | otherwise = reduce (a-1)
- --checks if the suduko still follow the rules aftet an update of a blank pos.
- prop_candidates :: Sudoku -> Bool
- prop_candidates sud | isSudoku sud && isOkay sud = and [ checkOne x | x<-candidates sud pos ]
- | otherwise = True where
- checkOne x = isSudoku (updSud x) && isOkay (updSud x)
- updSud x = update sud pos (Just x)
- pos = head (blanks sud)
- --Assignment F
- --Solves a Sudoku
- solve :: Sudoku -> Maybe Sudoku
- solve sud | isOkay sud && isSudoku sud = solve' sud (candidates sud (head (blanks sud)))
- | otherwise = Nothing
- --recursive function to solve the sudoku which uses backtracking, takes a sudoku and a list of candidates for
- --the first blank position in the sudoku.
- solve' :: Sudoku -> [Int] -> Maybe Sudoku
- solve' sud [] = Nothing
- solve' sud (c:cs) = if isSolved newSud then Just newSud -- returns the sudoku if found a solution
- else if isJust ret then ret --searches for a possible solution recursively
- else solve' sud cs where -- tries another candidate if the first one doesn't succeed.
- newSud = (update sud (head (blanks sud)) (Just c)) -- updates the sudoku with the first candidate
- ret = solve' newSud (candidates newSud (head (blanks newSud))) -- recursively searches for a solution
- --reads, solves and prints the Sudoku
- readAndSolve :: FilePath -> IO ()
- readAndSolve path = do sud <- readSudoku path
- if (solve sud) == Nothing then putStr "No solution found"
- else printSudoku (fromJust (solve sud))
- --checks if the first Sudoku is a solution of the second sudoku
- isSolutionOf :: Sudoku -> Sudoku -> Bool
- isSolutionOf sol sud = isOkay sol && isSolved sol && checkSol sol sud where
- checkSol sol sud = and [ checkEle x y (rows sol) (rows sud) | x<-[0..8],
- y<-[0..8], ((rows sud) !! x) !! y /=Nothing] where
- checkEle x y sol sud = ((sud!! x) !! y) == ((sol!! x) !! y)
- --Property for testing isSolutionOf, discards the invalid sudokus
- prop_SolveSound :: Sudoku -> Property
- prop_SolveSound sud = isSudoku sud && isOkay sud ==> ((fromMaybe sud (solve sud)) `isSolutionOf` sud)
- fewerChecks prop = quickCheckWith stdArgs{ maxSuccess = 30 } prop
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement