简体   繁体   English

f# 连接对象列表

[英]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'

I am trying to solve this problem -> https://projecteuler.net/problem=56 |我正在尝试解决这个问题-> https://projecteuler.net/problem=56 | but for this I need to generate powers below n < 100. When I try to concatenate [{ number=n; power=p; result=n**p}]@acc但为此我需要生成低于 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 these lists I get the error above. [{ number=n; power=p; result=n**p}]@acc这些列表我得到了上面的错误。 Explain please why error says 'Googol list -> Googol list' is in the function, does I plug a function as a parameter to the function or I plug the actual list when just after concatenation.请解释为什么错误显示'Googol list -> Googol list'在 function 中,我是否将 function 作为参数插入 ZC1C425268E68385D1AB4074C17A94 或实际插入列表之后。 Is @ a function? @是function吗?

You're missing a parameter here:您在这里缺少一个参数:

| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])@acc)
                                         ^^^^^^^^^^^^^^^
                                               here

powerInner is defined with three parameters, but you're only passing two. powerInner用三个参数定义,但你只传递了两个。

In F# it is not technically illegal to pass fewer parameters than defined.在 F# 中,传递比定义少的参数在技术上并不违法。 If you do that, the result will be a function that "expects" the remaining parameters.如果这样做,结果将是“预期”剩余参数的 function。 For example:例如:

let f : int -> int -> string

let x = f 42
// Here, x : int -> string

let y = x 5
// Here, y : string

So in your case omitting the last parameter makes the resulting type Googol list -> Googol list , which then turns out to be incompatible with the type Googol list expected by operator @ .因此,在您的情况下,省略最后一个参数会使结果类型Googol list -> Googol list ,然后结果与 operator @预期的类型Googol list不兼容。 Which is what the compiler is telling you in the error message.这是编译器在错误消息中告诉您的内容。

This looks like homework or practice, so first I'll give some hints to move on.这看起来像是家庭作业或练习,所以首先我会给出一些提示以继续前进。 Finally I'll show a version that seems to work, and then tell how I would approach the problem.最后,我将展示一个似乎可以工作的版本,然后告诉我将如何解决这个问题。

The task is to find the number a ** b , for a and b less than 100, that has the highest sum of its own digits.任务是找到数字a ** b ,对于ab小于 100,其自身数字的总和最大。

The first problem is that float won't give us all the digits of a ** b , so that type is useless to solve the problem.第一个问题是 float 不会给我们a ** b的所有数字,所以这种类型对解决问题没有用处。 To fix that, we turn to the BigInteger type, and the BigInteger.Pow function.为了解决这个问题,我们转向 BigInteger 类型和 BigInteger.Pow function。 Then we get a 1 followed by 200 zeroes if we run the following snippet, just like it says in the problem description.然后如果我们运行以下代码段,我们会得到一个 1 后跟 200 个零,就像它在问题描述中所说的那样。

let x: bigint = BigInteger.Pow (100I, 100)
let x: string = string x
printfn "s=%s" x

To get useful results, change the Googol type so that it uses bigint , except for power that should be an int .要获得有用的结果,请更改 Googol 类型,使其使用bigint ,但power应该是int

Why are the functions powerInner and numberInner inside the function generatePowers ?为什么 function generatePowers里面的函数powerInnernumberInner This doesn't seem to have a specific purpose, so I suggest moving them out to make this clearer.这似乎没有特定目的,因此我建议将它们移出以使其更清楚。

The function powerInner do a match on n , but then goes on to name the results p , which shadows the p parameter so that it is unused. function powerInnern进行匹配,但随后将结果命名为p ,这会隐藏p参数,使其未被使用。 Ok, the intention here is probably to match on p rather than n , so just fix that, and then the shadowing of the p parameter is perfectly fine.好的,这里的意图可能是匹配p而不是n ,所以只需修复它,然后p参数的阴影就很好了。

The tests first on <= 1 and then on > 1 causes incomplete matches.首先在<= 1上然后在> 1上的测试会导致不完整的匹配。 If the first line checks that the number is less or equal to one, then it must the greater than one in the next line.如果第一行检查数字是否小于或等于 1,则在下一行中它必须大于 1。 So just use n -> without the when to fix that.因此,只需使用n ->而无需when修复它。 I also suspect you want to test <= 0 instead of 1.我还怀疑您想测试<= 0而不是 1。

This这个

[{ number=n; power=p; result=n**p}]@acc

can be just可以只是

{ number=n; power=p; result=n**p } :: acc

and here和这里

(powerInner n [])

I suspect you just need a starting value for the power, which would be 99我怀疑你只需要一个功率的起始值,即 99

(powerInner n 99 [])

SPOILER WARNING剧透警告

After a bit of tinkering, this is what I ended up with, and it seems to print out a useful list of numbers.经过一番修补,这就是我最终得到的,它似乎打印出一个有用的数字列表。 Note that in order to not run through all 99 by 99 results with printouts, I've used low starting numbers 3 and 5 for the countdowns here, so we get some simple printout we can study for analysis.请注意,为了不通过打印输出运行所有 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

I'm not sure if this solution is correct.我不确定这个解决方案是否正确。 I'd do it differently anyway.无论如何,我会做不同的事情。

I would simply loop through a and b in two loops, one inside the other.我会简单地在两个循环中循环 a 和 b,一个在另一个循环中。 For each a ** b I would convert the result to a string, and then sum the digits of the string.对于每个a ** b我会将结果转换为字符串,然后对字符串的数字求和。 Then I'd simply use a mutable to hold on to whichever result is the highest.然后我会简单地使用一个可变的来保持最高的结果。 The same could be achieved in a more functional way with one of those fancy List functions.使用其中一个花哨的 List 函数可以以更实用的方式实现相同的目的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM