I am trying to create a function prime-factors that returns the prime factors of a number. To do so, I created is-prime function, and prime-factors-helper that will do a recursive check of the prime factors.
(defun is-prime (n &optional (d (- n 1)))
(if (/= n 1) (or (= d 1)
(and (/= (rem n d) 0)
(is-prime n (- d 1)))) ()))
(defun prime-factors-helper (x n)
(if (is-prime x) (list x)
(if (is-prime n)
(if (AND (= (mod x n) 0) (< n (/ x 2)))
(append (list n) (prime-factors-helper (/ x n) (+ 1 n)))
(prime-factors-helper x (+ 1 n)))
(prime-factors-helper x (+ 1 n)))))
(defun prime-factors (x)
(prime-factors-helper x 2))
The main function which is prime-factors seem to work for some numbers. However for big numbers it returns "Stack overflow (deep)".
CL-USER 44 : 5 > (prime-factors 66)
(2 3 11)
CL-USER 49 : 5 > (prime-factors 512)
"Stack overflow (deep)"
Can you please tell me why is it returning this error? is there something wrong with the recursive call?
[UPDATE]
I redefined the is-prime function but apparently it is not the problem.
(defun is-prime (x &optional (i 2))
(if (= x 1) nil
(if (or (= x 2) (= x 3)) t
(if (<= i (sqrt x))
(if (= (mod x i ) 0) nil
(is-prime x (+ i 1)))
t))))
(defun prime-factors-helper (x n)
(if (is-prime x)
(list x)
(if (is-prime n)
(if (AND (= (mod x n) 0) (<= n (/ x 2)))
(cons n (prime-factors-helper (/ x n) n))
(prime-factors-helper x (+ 1 n)))
(prime-factors-helper x (+ 1 n)))))
Optimisation question
I have another problem of optimisation. When I have a big number such as 123456789, I get this error message Stack overflow (stack size 261120). I believe because since the correct answer is (3 3 3607 3803), my program once it constructs the list with the two first elements (3 3), it will take so long to find the next prime factor. How can I optimise my code?
is-primeto make sure it's correct?is-primefunction. I defined it differently but still I have the exact same problem. Please check the new update where I put the new definition of theis-primefunction(prime-factors 512)could also just be "too big" of a problem to solve using unoptimized recursion.(if (AND (= (mod x n) 0) (< n (/ x 2)))if the number is multiple of 2 it will never enter this condition even though it has to. The reason is that I put<. It should be<=. So(if (AND (= (mod x n) 0) (<= n (/ x 2))). Thanks for your help