Преобразование кода c в код haskell с использованием рекурсии вместо циклов (без списков) - PullRequest
0 голосов
/ 17 марта 2019

Я хочу преобразовать следующий код 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 в отношении циклов, нотолько для нахождения общей суммы.Я нахожу сложным реализацию части if и счетчика (см. Код на c) также в haskell.Любая помощь высоко ценится!Вот мой код на 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

Ответы [ 3 ]

5 голосов
/ 17 марта 2019

Я думаю, идиоматический перевод будет выглядеть так:

n = 46656
tr = sqrt n
counter = length
    [ ()
    | i <- [1..tr]
    , j <- [1..tr]
    , i*i*j*j*j == n
    ]
2 голосов
/ 17 марта 2019

Не то чтобы это невозможно, но определенно не самый красивый:

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
0 голосов
/ 20 марта 2019

Общий и относительно простой способ перевести императивный код - заменить каждый базовый блок функцией и дать ему параметр для каждого элемента состояния, который он использует. Если это цикл, он будет повторно вызывать себя с разными значениями этих параметров. Если вы не заботитесь о печати промежуточных результатов, это означает:

Основная программа печатает результат внешнего цикла, который начинается с 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 в outer, потому что оно использует 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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...