[英]f# concatenate list of objects
type Googol = {
number : float
power : float
result : float
}
let generatePowers (n:float) : list<Googol> =
let rec powerInner (n:float) (p:float) (acc : list<Googol>) =
match n with
| p when p <= 1.0 -> acc
| p when p > 1.0 -> powerInner n (p-1.0) ([{ number=n; power=p; result=n**p}]@acc)
let rec numberInner (n:float) (acc : list<Googol>) =
match n with
| n when n <=1.0 -> acc
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])@acc)
numberInner n []
ProjectEuler.fsx(311,50): error FS0001: This expression was expected to have type
'Googol list'
but here has type
'Googol list -> Googol list'
我正在尝试解决这个问题-> https://projecteuler.net/problem=56 | 但为此我需要生成低于 n < 100 的幂。当我尝试连接[{ number=n; power=p; result=n**p}]@acc
[{ number=n; power=p; result=n**p}]@acc
[{ number=n; power=p; result=n**p}]@acc
这些列表我得到了上面的错误。 请解释为什么错误显示'Googol list -> Googol list'
在 function 中,我是否将 function 作为参数插入 ZC1C425268E68385D1AB4074C17A94 或实际插入列表之后。 @
是function吗?
您在这里缺少一个参数:
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])@acc)
^^^^^^^^^^^^^^^
here
powerInner
用三个参数定义,但你只传递了两个。
在 F# 中,传递比定义少的参数在技术上并不违法。 如果这样做,结果将是“预期”剩余参数的 function。 例如:
let f : int -> int -> string
let x = f 42
// Here, x : int -> string
let y = x 5
// Here, y : string
因此,在您的情况下,省略最后一个参数会使结果类型Googol list -> Googol list
,然后结果与 operator @
预期的类型Googol list
不兼容。 这是编译器在错误消息中告诉您的内容。
这看起来像是家庭作业或练习,所以首先我会给出一些提示以继续前进。 最后,我将展示一个似乎可以工作的版本,然后告诉我将如何解决这个问题。
任务是找到数字a ** b
,对于a
和b
小于 100,其自身数字的总和最大。
第一个问题是 float 不会给我们a ** b
的所有数字,所以这种类型对解决问题没有用处。 为了解决这个问题,我们转向 BigInteger 类型和 BigInteger.Pow function。 然后如果我们运行以下代码段,我们会得到一个 1 后跟 200 个零,就像它在问题描述中所说的那样。
let x: bigint = BigInteger.Pow (100I, 100)
let x: string = string x
printfn "s=%s" x
要获得有用的结果,请更改 Googol 类型,使其使用bigint
,但power
应该是int
。
为什么 function generatePowers
里面的函数powerInner
和numberInner
? 这似乎没有特定目的,因此我建议将它们移出以使其更清楚。
function powerInner
对n
进行匹配,但随后将结果命名为p
,这会隐藏p
参数,使其未被使用。 好的,这里的意图可能是匹配p
而不是n
,所以只需修复它,然后p
参数的阴影就很好了。
首先在<= 1
上然后在> 1
上的测试会导致不完整的匹配。 如果第一行检查数字是否小于或等于 1,则在下一行中它必须大于 1。 因此,只需使用n ->
而无需when
修复它。 我还怀疑您想测试<= 0
而不是 1。
这个
[{ number=n; power=p; result=n**p}]@acc
可以只是
{ number=n; power=p; result=n**p } :: acc
和这里
(powerInner n [])
我怀疑你只需要一个功率的起始值,即 99
(powerInner n 99 [])
剧透警告
经过一番修补,这就是我最终得到的,它似乎打印出一个有用的数字列表。 请注意,为了不通过打印输出运行所有 99 x 99 结果,我在这里使用低起始数字 3 和 5 进行倒计时,所以我们得到一些简单的打印输出,我们可以研究分析。
type Googol = { number: bigint; power: int; result: bigint }
let rec powerInner (n: bigint) (p: int) (acc: Googol list) =
match p with
| p when p <= 0 -> acc
| p ->
let newNumber = { number = n; power = p; result = n ** p }
printfn "newNumber=%0A" newNumber
powerInner n (p - 1) (newNumber :: acc)
let rec numberInner (n: bigint) (acc: Googol list) =
match n with
| n when n <= 0I -> acc
| n -> numberInner (n - 1I) ((powerInner n 5 []) @ acc)
let generatePowers (n: bigint) : Googol list =
numberInner n []
let powers = generatePowers 3I
我不确定这个解决方案是否正确。 无论如何,我会做不同的事情。
我会简单地在两个循环中循环 a 和 b,一个在另一个循环中。 对于每个a ** b
我会将结果转换为字符串,然后对字符串的数字求和。 然后我会简单地使用一个可变的来保持最高的结果。 使用其中一个花哨的 List 函数可以以更实用的方式实现相同的目的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.