2017-10-19 141 views
2

请考虑,鉴于x一个C程序,将返回yz这样y + z * 2 = x,为尽可能小的y。粗略地说,我可以创建一个嵌套的循环:嵌套循环和函数式编程

for(y = 0; y < x; ++ y){ 
    for(z = 0; z < x; ++z){ 
     if(y + 2 * z == x){ 
      printf("%d + 2 * %d = %d", y, z, x); 
     } 
    } 
} 

我怎么能在功能的方式翻译这种嵌套循环?这可行吗?是合理还是我只是错误的判断方法?到目前为止,我最好的尝试:

let foo x = 
    let rec aux (y, z, q) = 
     match (y + z * 2) with 
     r when r = q -> (y, z) 
     |_  -> aux(y + 1, z + 1, q) //How to check different values of z 
    aux(0, 0, x)       //for each value of y? 

这是行不通的,因为它只会增加双方yz。如何检查z的不同值,对于y的每个值?

+0

程序语言(如C)和功能语言(如F#)在编程时代表了两种不同的范例。因此,你不能真正做他们之间的直接翻译(你*可以*,但它不会很好的翻译,很可能相反),你经常不得不*。 –

+2

至于你的功能片段的评论中的问题 - >使用第二个递归函数。假设这是关于无符号整数的,为什么不直接计算结果? –

+0

'y = x%2; z = x/2'会做....(并且可以用功能代码表示) –

回答

4

您必须在比赛中添加这些检查。

在这里看到你的代码是缺少:

let foo x = 
    let rec aux (y, z, q) = 
     match (y + z * 2) with 
     | r when r = q -> (y, z) 
     | _ when y = q -> failwith "not found !" 
     | _ when z = q -> aux (y + 1, 0, q) 
     | _   -> aux (y, z + 1, q) 
    aux (0, 0, x) 

,这里是一个不同的方法,同样的功能,但不递归:

let foo2 x = 
    let s = 
     {0 .. x} |> Seq.collect (fun y -> 
      {0 .. x} |> Seq.collect (fun z -> 
       seq [y, z])) 
    Seq.find (fun (y, z) -> y + z * 2 = x) s 

这在F#可以使用序列表达式来写:

let foo3 x = 
    let s = seq { 
     for y in {0 .. x} do 
      for z in {0 .. x} do 
       yield (y, z)} 
    Seq.find (fun (y, z) -> y + z * 2 = x) s 

它类似于你原来的C程序。

+0

您不需要括号。 “对于0 .. x做y”同样适用。 – Lars

+0

感谢Gustavo,你的例子正在帮助我澄清几个概念。我正在练习他们!我只有一个问题。在你的第一个片段中,什么是r?我不是陛下,我说得对。它有价值吗?这只是一个名字吗? – Worice

+0

@Worice其实''r''来自你的代码,而不是我的。但是,它包含评估''(y + z * 2)''的结果。如果你问我,我会重新编写这个匹配,或者使用if和elif表达式,但我只是想尽可能地将代码粘贴到你的代码中,并告诉你你错过了什么。 – Gustavo