Reputation: 153
I want to convert the following c code to haskell code, without using lists. It returns the number of occurrences of two numbers for a given n
, where n
satisfies 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);
}
I've managed to do something similar in haskell in regarding to loops, but only for finding the overall sum. I find difficult implementing the if part and counter part(see on c code) in haskell also. Any help much appreciated! Heres my haskell code also:
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
Upvotes: 0
Views: 144
Reputation: 54971
A general and relatively straightforward way to translate imperative code is to replace each basic block with a function, and give it a parameter for every piece of state it uses. If it’s a loop, it will repeatedly tail-call itself with different values of those parameters. If you don’t care about printing the intermediate results, this translates straightforwardly:
The main program prints the result of the outer loop, which begins with i
= 1 and counter
= 0.
main = print (outer 1 0)
where
These are constants, so we can just bind them outside the loops:
n = 46656
tr = floor (sqrt n)
The outer
loop tail-calls itself with increasing i
, and counter updated by the inner
loop, until i > tr
, then it returns the final counter.
outer i counter
| i <= tr = outer (i + 1) (inner 1 counter)
| otherwise = counter
where
The inner
loop tail-calls itself with increasing j
, and its counter
(counter'
) incremented when i^2 * j^3 == n
, until j > tr
, then it returns the updated counter back to outer
. Note that this is inside the where
clause of outer
because it uses i
to calculate res
—you could alternatively make i
an additional parameter.
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'
Upvotes: 0
Reputation: 135
Not that it isn't possible, but definitely not the best looking:
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
Upvotes: 2
Reputation: 152697
I guess an idiomatic translation would look like this:
n = 46656
tr = sqrt n
counter = length
[ ()
| i <- [1..tr]
, j <- [1..tr]
, i*i*j*j*j == n
]
Upvotes: 4