转换9x9列表,使每行包含3x3块

时间:2015-10-02 13:54:34

标签: haskell

这是我的解决方案,但是可能有更好的方法来写这个。

基本上我有一个包含9行的列表,每行包含9个元素,表示示例中显示的9x9数独。我想转换该列表,以便每行对应于数独的3x3块

我该如何改善这个?

-- returns 9 rows that corresponds to the 3x3 blocks in a sudoku
-- splits the list, transposes, concats, and then combines into 9 rows
all3x3blocks :: [Block] -> [Block] 
all3x3blocks b = combineList (concat (transpose (splitList b)))

-- splits up each of the 9 rows into 3 parts with 3 elements in each
splitList :: [Block] -> [[Block]]
splitList b = [mySplit 3 x | x <- b ]

-- splits a list into n sized lists
mySplit :: Int -> Block -> [Block]
mySplit _ [] = []
mySplit n list = firstSplit : (mySplit n rest)
  where
    (firstSplit,rest) = splitAt n list

-- combines a split row, by combining 3 parts into 1 row with 9 elements
combineList :: [Block] -> [Block]
combineList [] = []
combineList list = concat(split) : combineList rest
    where (split, rest) = splitAt 3 list

type Block = [Maybe Int]

example :: [Block]
example =
    [ [Just 3, Just 6, Nothing,Nothing,Just 7, Just 1, Just 2, Nothing,Nothing]
    , [Nothing,Just 5, Nothing,Nothing,Nothing,Nothing,Just 1, Just 8, Nothing]
    , [Nothing,Nothing,Just 9, Just 2, Nothing,Just 4, Just 7, Nothing,Nothing]
    , [Nothing,Nothing,Nothing,Nothing,Just 1, Just 3, Nothing,Just 2, Just 8]
    , [Just 4, Nothing,Nothing,Just 5, Nothing,Just 2, Nothing,Nothing,Just 9]
    , [Just 2, Just 7, Nothing,Just 4, Just 6, Nothing,Nothing,Nothing,Nothing]
    , [Nothing,Nothing,Just 5, Just 3, Nothing,Just 8, Just 9, Nothing,Nothing]
    , [Nothing,Just 8, Just 3, Nothing,Nothing,Nothing,Nothing,Just 6, Nothing]
    , [Nothing,Nothing,Just 7, Just 6, Just 9, Nothing,Nothing,Just 4, Just 3]
    ]

-- Desired outcome after transformation
[[Just 3,Just 6,Nothing,Nothing,Just 5,Nothing,Nothing,Nothing,Just 9]
,[Nothing,Nothing,Nothing,Just 4,Nothing,Nothing,Just 2,Just 7,Nothing]
,[Nothing,Nothing,Just 5,Nothing,Just 8,Just 3,Nothing,Nothing,Just 7]
,[Nothing,Just 7,Just 1,Nothing,Nothing,Nothing,Just 2,Nothing,Just 4]
,[Nothing,Just 1,Just 3,Just 5,Nothing,Just 2,Just 4,Just 6,Nothing]
,[Just 3,Nothing,Just 8,Nothing,Nothing,Nothing,Just 6,Just 9,Nothing]
,[Just 2,Nothing,Nothing,Just 1,Just 8,Nothing,Just 7,Nothing,Nothing]
,[Nothing,Just 2,Just 8,Nothing,Nothing,Just 9,Nothing,Nothing,Nothing]
,[Just 9,Nothing,Nothing,Nothing,Just 6,Nothing,Nothing,Just 4,Just 3]]

1 个答案:

答案 0 :(得分:4)

基本上和你一样,但我会把它写成一个管道:

sudokuClusters :: [[c]] -> [ [[c]] ]   -- note this is polymorphic: no reason
sudokuClusters =                       -- it should only work with `Maybe Int`!
      concat              -- gather 3×3-blocks from each triplet of rows
    . map transpose       -- combine cell-triplets that were vertical neighbours
    . splitsEach 3        -- partition rows
    . map (splitsEach 3)  -- partition each row

splitsEach :: Int -> [a] -> [[a]]
splitsEach _ [] = []
splitsEach n l = firstSplit : splitsEach n rest
 where (firstSplit, rest) = splitAt n l

一个有趣的,更通用的解决方案是:

recluster :: (∀ x . [x] -> [[x]]) -> [[c]] -> [ [[c]] ]
recluster f = concatMap transpose . f . map f

sudokuClusters = recluster (splitsEach 3)
相关问题