Haskell 得到所有总和为 X 的数字

2023-11-29

我需要在 haskell 中创建一个函数,它接收一个数字并返回一个列表列表,其中该列表包含数字的所有组合,其总和是收到的数字。

很难解释,所以这是例子:

sum1 4 = [ [4], [3,1], [2,2], [1,3], [1,1,2], [1,2,1] , [2,1,1] ]

sum1 3 = [ [3], [2,1], [1,2], [1,1,1]

我需要通过递归和理解列表来做到这一点

EDIT

这是我的代码:

sum1 n = sum3 (sum2 1 (n-1) n)
sum2 x y n = if ((x+y)==n && x>0 && y>0) then [x,y]:sum2 (x+1) (y-1) n else []
sum3 [] = []
sum3 (x:xs) = sum4 x 1 : sum3 xs
sum4 [] t = []
sum4 (x:xs) t = if not (x == t) then (sum1 x) else x

是的,这是一次过度的考试,但我不知道该怎么做


我假设这是一份家庭作业(在我看来,这是一项更难的作业),所以我现在不会破坏一切。

如果您考虑一下,您应该会发现基本上有两种操作可以从列表中获取xs总和就是n到一个列表,总和为n+1:

  • 你可以添加另一个1
  • 你可以加1对某些人x in xs

因此,如果您设法实现这两项操作,您的任务就会容易得多。

第一个并不难(hint (1:)是一个在前面附加一个函数1到一些清单 - 现在你必须map这...)

第二个有点难,尽管几乎相同的分而治之的想法会帮助你。

我将这样开始:

add1Somewhere :: Num a => [a] -> [[a]]
add1Somewhere [i] = [[i+1]]
add1Somewhere (i:is) = ???

(是的,这是一个partial功能)


remarks:

  • 正如您在下面看到的,您实际上不必插入额外的1某处或选择任何x in xs- 使用第一个x in xs并放在第一位确实足够了
  • 我暗示的算法有时会产生相同的结果 - 例如,如果你有一个[1,1]那么你可以结束于[2,2]后来通过两种方式:[1,1] -> [2,1] -> [2,2] and [1,1] -> [1,2] -> [2,2]- 这些可以通过删除Data.List.nub或者如果您更改算法以生成排序/过滤结果(不生成[1,1] -> [1,2])
  • 你的例子缺少一些东西[1,1,1,1]老实说,我无法判断这个练习是否暗示了这样一个命令
  • 你可能应该看看concatMap (or concat)
  • 这与 @cirdec 暗示的算法不同(可能他的速度更快) - 但如果你在某个地方额外插入1

solution

因为已经有一段时间了,而且你说这是一个旧的考试问题,我认为破坏它是可以的(如果你不想,请不要继续阅读)

所以这是一个可能的解决方案(不关心任何性能问题):

import Data.List (nub)

sum1 :: (Eq a, Num a) => a -> [[a]]
sum1 1 = [[1]]
sum1 n = nub $ concatMap add1Somewhere ns ++ map (1:) ns
  where ns = sum1 (n-1)

add1Somewhere :: Num a => [a] -> [[a]]
add1Somewhere [i] = [[i+1]]
add1Somewhere (i:is) = ((i+1):is) : map (i:) (add1Somewhere is)

请注意,这使用concatMap and nub两者都可能适合也可能不适合。

我希望你能明白基本的想法


显然更好的解决方案

哎呀 - 我刚刚注意到你可以摆脱所有有问题的功能类似于concat and nub无论如何,因为只需在前面添加一个就足够了1或者增加第一个列表元素 - 无论如何,递归将提供所有需要的排列(我提到的不同路径正是排列) -虽然顺序有区别:

sum1 :: (Eq a, Num a) => a -> [[a]]
sum1 1 = [[1]]
sum1 n = map add1 ns ++ map prep1 ns
  where ns          = sum1 (n-1)
        prep1 is    = 1:is
        add1 (i:is) = (i+1):is

当然你可以更换map如果你愿意的话可以使用列表理解

证明这找到了所有排列

通过感应n(假设只有正自然数)

for n=1请注意[1]是唯一可能的列表

现在假设我们找到了所有排列n>0看看一些清单xs总结起来就是n+1(显然列表必须非空)

现在第一个元素x of xs = x:ys将是1 or >1

  • x=1- 在这种情况下prep1会提供xs因为ys我们的算法通过归纳法发现了(注意sum ys = sum xs - 1 = n)
  • x>1- 在这种情况下(x-1):ys我们的算法通过归纳法发现了add1将创造xs(再次因为sum ((x-1):ys) = sum xs - 1 = n)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Haskell 得到所有总和为 X 的数字 的相关文章

  • 在 Haskell 中对单位的组成(例如英寸、美元等)进行建模

    跟进自我之前的一个问题 https stackoverflow com q 73375273 222529 我问如何创建一个可以对单元进行建模的类型 例如Inch 作为 Haskell 中的一种类型 我现在面临的问题是如何对该单元和其他单元
  • 为什么 GeneralizedNewtypeDeriving 没有安全的 Haskell?

    来自 GHC 手册 第安全语言 http www haskell org ghc docs 7 6 2 html users guide safe haskell html safe language 模块边界控制 使用安全语言编译的 Ha
  • 副作用是纯函数中找不到的一切吗?

    可以肯定地说 以下二分法成立 每个给定的函数是 要么纯粹 或有副作用 如果是这样 函数的 副作用就是纯函数中找不到的任何东西 这很大程度上取决于您选择的定义 可以公平地说 函数是pure or impure 纯函数始终返回相同的结果并且不会
  • 如何在 blaze-html 中渲染 blaze-svg 标记

    我想将使用 blaze svg 生成的 svg 图直接包含在使用 blaze html 生成的 html 中 两者都基于 blaze markup 所以我希望它很容易 diagram1 Svg diagram1 try1 Html try1
  • Haskell 真的是纯粹的吗(有任何语言可以处理系统外的输入和输出)吗?

    在谈到函数式编程中的 Monad 后 该功能是否真的使语言变得纯粹 或者它只是黑板数学之外的现实世界中计算机系统推理的另一张 免狱卡 EDIT 这不是有人在这篇文章中所说的火焰诱饵 而是一个真正的问题 我希望有人能用它来击倒我并说 证明 它
  • 算法 - 如何有效删除列表中的重复元素?

    有一个list L 它包含以下元素任意类型each 如何有效删除此类列表中的所有重复元素 必须保留订单 只需要一个算法 因此不允许导入任何外部库 相关问题 在Python中 从列表中删除重复项以使所有元素都是唯一的最快算法是什么在维持秩序的
  • “反向”使用 Maybe Monad

    假设我有很多功能 f a gt Maybe a g a gt Maybe a h a gt Maybe a 我想按以下方式组合它们 如果 f 返回 Nothing 则计算 g 如果 g 返回 Nothing 则计算 h 如果其中任何一个计算
  • 计算两点之间的距离(Haskell)

    给定两个元组的输入 我希望能够使用以下公式计算两点之间的距离 距离 sqrt x1 x2 2 y1 y2 2 所以我希望函数调用和输出如下所示 gt distance 5 10 3 5 5 385 当我尝试运行下面的代码时 它告诉我输入 w
  • 列表理解:制作列表列表

    你好 我正在尝试在 haskell 中创建一个函数 该函数接受一个数字 a 使用列表 即数字 将其一部分4它会创造 1 1 1 1 1 1 2 1 3 2 2 4 我正在考虑使用列表理解来创建列表 x 然后使用 1 n 中的数字创建更多列表
  • 处理许多不相关的类型时避免样板

    我正在编写处理以下值的代码语言 扩展 注释 语法 http hackage haskell org packages archive haskell src exts 1 1 4 doc html Language Haskell Exts
  • 如何组合过滤条件

    过滤器类函数接受一个条件 a gt Bool 并在过滤时应用它 当您有多个条件时 使用过滤器的最佳方法是什么 使用了应用函数 liftA2 而不是 liftM2 因为出于某种原因我不明白 liftM2 在纯代码中如何工作 liftM2 组合
  • 带有查询参数的渲染 url

    无法找到简单问题的解决方案 答案应该是显而易见的 如何在 hamlet 模板中使用查询参数渲染 url I e ItemsR 将生成http localhost 3000 items我如何生成类似的东西http localhost 3000
  • 解析 PHOAS 表达式

    我想我理解 PHOAS 参数化高阶抽象语法 我明白了如何漂亮地打印一个表达式 参见http www reddit com r haskell comments 1mo59h phoas for free by edward kmett cc
  • 有什么方法可以在 do / while / let 块中打印出变量的类型吗?

    有没有办法打印出嵌套变量的推断类型ghci 考虑代码 let f g where g x Int x 那么 最好查询一下类型g e g t f g会打印出Int gt Int 您可以通过给出适当的错误类型注释并检查错误消息来诱骗此信息 Ma
  • 如何处理在组合下发生变化的类型?

    我最近读了一篇非常有趣的论文单调性类型 https infoscience epfl ch record 231867 files monotonicity types pdf其中描述了一种新的 HM 语言 该语言可以跟踪操作之间的单调性
  • Haskell 和 Idris 之间的区别:类型宇宙中运行时/编译时的反映

    因此 在 Idris 中 编写以下内容是完全有效的 item b Bool gt if b then Nat else List Nat item True 42 item False 1 2 3 cf https www youtube
  • Parsec 函数“parse”和类“Stream”的类型签名

    约束条件是什么 Stream s Identity t 下面的类型声明是什么意思 parse Stream s Identity t gt Parsec s a gt SourceName gt s gt Either ParseError
  • Haskell:GHC 无法推断类型。由类型签名错误绑定的刚性类型变量

    我看过几篇主题相似的帖子 但它们并不能真正帮助我解决我的问题 所以我才敢重复 现在我有一个带有签名的函数 run Expr query gt RethinkDBHandle gt query gt IO JSON 这是一个数据库查询运行函数
  • 是否有适用于 Haskell 或 Scala 等函数式语言的 LL 解析器生成器?

    我注意到明显缺乏用函数式语言创建解析器的 LL 解析器 我一直在寻找但没有成功的理想发现是为 ANTLR 风格的 LL 语法生成 Haskell 解析器 语法的模小数重新格式化 并且令我惊讶的是 每个最后一个解析器生成器都具有函数我发现的语
  • Haskell - 翻转具有两个参数的类型类的参数

    我有一个多参数类型类 它提供了一个可以交换其参数的函数 class Swappable a b where swappable a gt b gt Bool So if a and b form Swappable a b then b a

随机推荐