[英]Convert c code to haskell code using recursion instead of loops (no lists)
我想将以下 c 代码转换为 haskell 代码,而不使用列表。 它返回给定n
的两个数字出现的次数,其中n
满足n=(a*a)*(b*b*b)
。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(void) {
int n = 46656;
int i,j,counter=0,res=1;
int tr = sqrt(n);
for(i=1; i<=tr; i++) {
for(j=1; j<=tr; j++) {
res = (i*i) * (j*j*j) ;
if(res==n) {
counter=counter+1;
}
printf("%d\n",res);
}
}
printf("%d\n",counter);
}
我已经设法在 Haskell 中对循环做了类似的事情,但只是为了找到总和。 我发现在haskell 中也很难实现if 部分和counter 部分(参见c 代码)。 非常感谢任何帮助! 继承人我的haskell代码也是:
sumF :: (Int->Int)->Int->Int
sumF f 0 = 0
sumF f n = sumF f (n-1) + f n
sumF1n1n :: (Int->Int->Int)->Int->Int
sumF1n1n f 0 = 0
sumF1n1n f n = sumF1n1n f (n-1)
+sumF (\i -> f i n) (n-1)
+sumF (\j -> f n j) (n-1)
+f n n
func :: Int->Int->Int
func 0 0 = 0
func a b = res
where
res = (a^2 * b^3)
call :: Int->Int
call n = sumF1n1n func n
我想一个惯用的翻译应该是这样的:
n = 46656
tr = sqrt n
counter = length
[ ()
| i <- [1..tr]
, j <- [1..tr]
, i*i*j*j*j == n
]
并不是说不可能,但绝对不是最好看的:
counter n = go (sqrt n) (sqrt n)
where
go 0 _ = 0
go i tr = (go2 tr 0 i) + (go (i - 1) tr)
go2 0 c i = c
go2 j c i = go2 (j - 1) (if i^2 * j^3 == n then c + 1 else c) i
翻译命令式代码的一种通用且相对直接的方法是用一个函数替换每个基本块,并为它使用的每个状态块赋予一个参数。 如果它是一个循环,它将使用这些参数的不同值重复尾调用自身。 如果您不关心打印中间结果,则可以直接转换:
主程序打印外循环的结果,该结果以i
= 1 和counter
= 0 开始。
main = print (outer 1 0)
where
这些是常量,因此我们可以将它们绑定到循环之外:
n = 46656
tr = floor (sqrt n)
outer
循环随着i
增加对自身进行尾调用,并且计数器由inner
循环更新,直到i > tr
,然后它返回最终的计数器。
outer i counter
| i <= tr = outer (i + 1) (inner 1 counter)
| otherwise = counter
where
inner
循环随着j
增加对自身进行尾调用,当i^2 * j^3 == n
,它的counter
( counter'
) 增加,直到j > tr
,然后它将更新后的计数器返回给outer
。 请注意,这是在outer
的where
子句中,因为它使用i
来计算res
——您也可以将i
作为附加参数。
inner j counter'
| j <= tr = inner (j + 1) $ let
res = i ^ 2 * j ^ 3
in if res == n then counter' + 1 else counter'
| otherwise = counter'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.