开发者

need help writing a function candidates in Haskell

Hi take a look at this thread already processing this subject And also this thread might be of intrest.

Im trying to write a fu开发者_开发百科nction

candidates :: Sudoku -> Pos -> [Int]

that given a Sudoku

data Sudoku = Sudoku { rows :: [[Maybe Int]] }
 deriving ( Show, Eq )

and a position (type Pos = (Int, Int)) determines what numbers that you can write there, for example in a sudoku row that already contains (1,2,4,7,9,x,x) you cant write any of the already existing numbers in the last row. Also the other problem is to check the hight as well as the width so no numbers occur more than once (ordinary sudoku rules). So any suggestions on how to start?

Example: Sudoku> candidates example (0,2) [4,8]


I remember doing this project in my Algorithms class in college. My best advice, particularly for someone who is writing in Haskell for learning and not for production, is to write 'top down'. First, ask yourself what do you need to do to solve this problem? Then just write it down with descriptive functions (even if they don't yet exist). Then stub in the functions you need. For example, a start might be:

candidates :: Sudoku -> Pos -> [Int]
candidates s p = union (rowCands s p) (colCands s p) (blockCands s p)

rowCands :: Sudoku -> Pos -> [Int]
rowCands = undefined
colCands :: Sudoku -> Pos -> [Int]
colCands = undefined
blockCands :: Sudoku -> Pos -> [Int]
blockCands = undefined

From this, you would simply start describing top-down how to solve the rowCands problem, until you've answered everything. Note that sometimes you'll want to write a function similar to union, but surely its already been written before. Try checking out http://haskell.org/hoogle. You can search for function names or even type signatures. Maybe there is a union somewhere already written in the standard libraries?

As an interesting question for you to answer yourself, what is the type of undefined and why does it type check? It is not a special keyword; it is merely a predefined function.


Here is a solution using Data.Set. You can use S.elems to get the list, but if you are making a sudoku solver, you might be looking for S.size.

import qualified Data.Set as S
import Data.Maybe(catMaybes)   

fullSet = S.fromAscList [1..9]

fromJustL = S.fromList . concatMaybes

candidates s x =
  rowSet s x `S.intersection` colSet s x `S.intersection` cellSet s x

rowSet s (i,_) = fullSet `S.difference` fromJustL (s !! i)
colSet s (_,i) = fullSet `S.difference` fromJustL (map (!!i) s)
cellSet s (i,j) = fullSet `S.difference` fromJustL (concatMap (g j) (g i s))
  where
  g i | i < 3     = take 3 
      | i < 6     = take 3 . drop 3
      | otherwise = take 3 . drop 6
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜