【问题标题】:higher order functions riddle solving function in haskellhaskell中的高阶函数解谜函数
【发布时间】:2023-03-12 08:49:01
【问题描述】:

我正在尝试用金字塔重现谜题:

金字塔的最后一层是数字从 1 到 n 的排列,其中 n 是字段数。然后,不在最低层中的每个其他字段都是该数字对角线下方的数字之和。

所以我想创建一个函数,当给出左边的谜语时,它会返回右边的解决方案。我打算通过枚举这样的层来做到这一点:

对于我制作了自定义数据类型的图层:

data Layer = One | Two | Three | Four | Five | Six
deriving (Eq,Ord,Enum,Show)

和其他类型:

type LayerDepth = Layer
type FieldNumber = Int
type FieldContent = Int
type FieldAssignment = (FieldNumber -> FieldContent)
type PyramidRiddle = FieldAssignment
type PyramidSolution = FieldAssignment
type PyramidSolutions = [PyramidSolution]

和功能:

solveRiddle :: LayerDepth -> PyramidRiddle -> Pyramidsolutions

对于图示示例,我将创建类型为 (FieldNumber -> FieldContent) 的匿名函数:

fieldAssignment1 = \n -> if (n==6) || n==8) then 3 else 0

此函数将第 6 和第 8 字段标记为数字 3

然后调用: solveRiddle Four fieldAssignment1 ->> [pyramidSolution1, pyramidSolution2]

Four 表示四层,PyramidSolutions 是具有谜题解的 FieldAssignments 列表

我的问题:

我会以某种方式需要返回一个函数,该函数将给定字段分配计算最后一层中的排列,并在此基础上将数字分配给其余字段。

有点像这样:

pyramidSolution1 = \n -> case n of 1 -> 18
                                   2 -> 11 
                                   3 -> 7
                                   4 -> 7 
                                   5 -> 4 
                                   6 -> 3 
                                   7 -> 4 
                                   8 -> 3 
                                   9 -> 1 
                                  10 -> 2
                                   _ -> 0 

pyramidSolution2 = \n -> case n of 1 -> 20
                                   2 -> 12 
                                   3 -> 8
                                   4 -> 7 
                                   5 -> 5 
                                   6 -> 3 
                                   7 -> 4 
                                   8 -> 3 
                                   9 -> 2 
                                  10 -> 1
                                   _ -> 0 

但是解决这个问题的最佳方法是什么?

我如何分配数字的排列,并知道如何放置它们,数字向上是下面数字的总和?

在上面的代码中实现匿名函数 pyramidSolution1 和 pyramidSolution2 的最佳方法是什么?

【问题讨论】:

    标签: haskell higher-order-functions


    【解决方案1】:

    我会稍微简化一下。层是数字列表:

    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]]
    

    正确解决方案是针对给定谜题进行验证的解决方案:

    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]]
    

    【讨论】:

      猜你喜欢
      • 2017-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-10
      • 2011-12-13
      • 1970-01-01
      • 2012-10-15
      相关资源
      最近更新 更多