这是我的解决方案,但是可能有更好的方法来写这个。
基本上我有一个包含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]]
答案 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)