我想将以下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部分和反部分(请参见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
答案 0 :(得分:5)
我想惯用的翻译看起来像这样:
n = 46656
tr = sqrt n
counter = length
[ ()
| i <- [1..tr]
, j <- [1..tr]
, i*i*j*j*j == n
]
答案 1 :(得分:2)
不是不可能,但是绝对不是最好的外观:
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
答案 2 :(得分:0)
翻译命令性代码的一种通用且相对简单的方法是用一个函数替换每个基本块,并为其使用的每个状态块赋予一个参数。如果是循环,它将重复使用这些参数的不同值对其自身进行尾部调用。如果您不在乎打印中间结果,则可以直接进行翻译:
主程序打印外部循环的结果,该循环以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
的增加而尾部调用,并且counter
时其counter'
(i^2 * j^3 == n
)会递增,直到j > tr
,然后它将更新的计数器返回到outer
。请注意,这位于where
的{{1}}子句中,因为它使用outer
来计算i
-您也可以将res
设为附加参数。
i