Я бы немного упростил это.Слой - это список чисел:
type Layer = [Int]
-- e.g. [4,3,1,2]
Правило - это список фиксированных назначений для некоторых элементов.
data Must = Any | Only Int -- Yes, it's just Maybe with different labels
type Rule = [Must]
-- e.g. [Any,Only 3,Any,Any]
Вам понадобится функция, которая может генерировать слой изтот, что под ним:
nextLayer :: Layer -> Layer
nextLayer = undefined
-- nextLayer [4,3,1,2] == [7,4,3]
и функция для проверки слоя на соответствие действительному правилу
isLayerValid :: Rule -> Layer -> Bool
isLayerValid = undefined
-- isLayerValid [Any,Any,Only 3] [1,2,3] == True
-- isLayerValid [Any,Any,Only 3] [1,3,2] == False
Загадка - это просто список правил:
type Riddle = [Rule]
riddle :: Riddle
riddle = [[Any, Only 3, Any, Any], [Any, Any, Only 3], [Any, Any], [Any]]
, а решение - это список слоев, начинающихся с некоторой базы.
type Pyramid = [Layer]
pyramid :: Layer -> Pyramid
pyramid [] = []
pyramid base = base : pyramid (nextLayer base)
-- pyramid [4,3,1,2] == [[4,3,1,2],[7,4,3],[11,7],[18]]
A правильное решение - это решение, которое проверяет данную загадку:
isValidFor :: Riddle -> Pyramid -> Bool
isValidFor [] [] = True
isValidFor (r:rs) (x:xs) = isLayerValid r x && isValidFor rs xs
-- isValidFor riddle (pyramid [4,3,1,2]) == True
-- isValidFor riddle (pyramid [1,3,4,2]) == False
Хитрость заключается в том, чтобы сгенерировать все потенциальные решения
permutations :: [Int] -> [[Int]]
permutations ns = undefined
-- e.g. allSolutions = map pyramid (permutations [1..n])
и отфильтровать их с помощью теста решения:
solutions :: Riddle -> [Pyramid]
solutions r = filter (isValidFor r) (map pyramid (permutations [1..length r]))
-- solutions riddle == [pyramid [4,3,1,2], pyramid [4,3,2,1]]