从1到20的所有数字均可被整除的最小正数是多少?
我可以通过循环轻松地用强制性编程语言强制解决方案。但是我想在Haskell中做到这一点而不是让循环变得更难。我在考虑做这样的事情:
[n | n <- [1..], d <- [1..20], n `mod` d == 0] !! 0
但是我知道这不起作用,因为“d”会使条件在d = 1时等于True。我需要提示如何设置它以便为[1]计算n mod
d。 .20]并且可以验证所有20个号码。
再次,请不要给我一个解决方案。谢谢。
答案 0 :(得分:8)
与许多Project Euler问题一样,这至少与数学和编程一样重要。
您正在寻找的是一组数字中最不常见的倍数,它们恰好是从1开始的序列。
函数式语言中的一种可能的策略是试图使其递归,这是基于找出所有[1..n]
可被整除的最小数字与[1..n+1]
所有可被整除的最小数字之间的关系。用一些小于20的数字来玩这个,并尝试理解数学关系或者可能辨别出一种模式。
答案 1 :(得分:5)
在找到这样的数字之前,不要进行搜索,而是考虑一种建设性的算法,在给定一组数字的情况下,构造所有这些数字的smallest (or least) positive number that is evenly divisible by (aka "is a common multiple of")。查看那里的算法,并考虑Euclid's algorithm(他们提到的)可能适用的方式。
你能想到两个数字之间在最大公约数和最小公数之间的关系吗?一组数字怎么样?
答案 2 :(得分:4)
如果你看一下,它似乎是一个列表过滤操作。无限数列表,根据是否可以从1到20的所有数字整除的情况进行过滤。
所以我们得到的是我们需要一个函数,它接受一个整数和一个整数列表,并告诉它是否可以被列表中的所有数字整除
isDivisible :: [Int] -> Int -> Bool
然后在List过滤器中将其用作
filter (isDivisible [1..20]) [1..]
现在因为Haskell是一种懒惰的语言,你只需要从上面的过滤结果中获取所需数量的项目(在你的情况下你只需要一个,因此List.head方法听起来不错)。
我希望这会对你有所帮助。这是一个简单的解决方案,并且还有许多其他单线解决方案:)
答案 3 :(得分:1)
备选答案:您可以利用Prelude中提供的lcm功能。
答案 4 :(得分:0)
为了有效地解决这个问题,请选择Don Roby的答案。如果您只想对蛮力方法稍作提示,请将您写回的内容翻译成英文,并查看它与问题描述的区别。
你写了类似“过滤积极自然和积极自然的产物从1到20”
你想要的更像是“通过从1到20的正面自然的某些功能来过滤积极的自然”
答案 5 :(得分:0)
在这种情况下你必须得到Mathy。从累加器foldl
开始,您将执行[1..20]
到n = 1
。对于该列表的每个数字p
,只有在p
为素数时才会继续。现在,对于上一个素数p
,您希望找到q
这样的最大整数p^q <= 20
。乘以n *= (p^q)
。完成foldl
后,n
就是您想要的数字。
答案 6 :(得分:0)
可能的暴力实施将是
head [n|n <- [1..], all ((==0).(n `mod`)) [1..20]]
但在这种情况下,它会花费太长时间。 all
函数测试谓词是否适用于列表的所有元素。 lambda是(\d -> mod n d == 0)
的缩写。
那你怎么能加快计算速度呢?让我们将我们的除数归结为素数因子,并搜索每个素数因子的最高幂:
2 = 2
3 = 3
4 = 2^2
5 = 5
6 = 2 * 3
7 = 7
8 = 2^3
9 = 3^2
10 = 2 * 5
11 = 11
12 = 2^2*3
13 = 13
14 = 2 *7
15 = 3 * 5
16 = 2^4
17 = 17
18 = 2 * 3^2
19 = 19
20 = 2^2 * 5
--------------------------------
max= 2^4*3^2*5*7*11*13*17*19
使用此号码我们有:
all ((==0).(2^4*3^2*5*7*11*13*17*19 `mod`)) [1..20]
--True
嘿,它可以从1到20的所有数字整除。不是很令人惊讶。例如。它可以被15整除,因为它“包含”因子3和5,它可以被16整除,因为它“包含”因子2 ^ 4。但这是最小的数字吗?想一想......