Search code examples
c++common-lispcode-translation

Common Lisp code for a C++ program with nested loops


I am a Common Lisp beginner, but not so in C++. There's a simple C++ program that I am trying to mirror in CL (see Pollard's Rho algorithm variant example in C++ ). The C++ program runs without errors. One requirement is that all the outputs from both the programs must match.

C++ version

int gcd(int a, int b) {
    int remainder;
    while (b != 0) {
        remainder = a % b;
        a = b;
        b = remainder;
    }
    return a;
}

int prime () {
    int n = 10403, x_fixed = 2, cycle_size = 2, x = 2, factor = 1;

    while (factor == 1) {
        for (int count=1;count <= cycle_size && factor <= 1;count++) {
            x = (x*x+1)%n;
            factor = gcd(x - x_fixed, n);
        }

        cycle_size *= 2;
        x_fixed = x;
    }
    cout << "\nThe factor is  " << factor;
return 0;
}

Common Lisp version

Here is what I've come up with. The debugging is giving me nightmares, yet I tried a lot many times and stepped through the entire code, still I have no idea where I have gone wrong :(

(defun prime () 
  (setq n 10403) 
  (setq x_fixed 2) 
  (setq cycle_size 2)
  (setq x 2) 
  (setq factor 1)
  (setq count 1) 
  (while_loop))

(defun while_loop () 
  (print
    (cond ((= factor 1) 
           (for_loop)
           (setf cycle_size (* cycle_size 2))
           (setf x_fixed x) 
           (setf count 1)
           (while_loop))

          ((/= factor 1) "The factor is : ")))
  (print factor))

(defun for_loop () 
    (cond ((and (<= count cycle_size) (<= factor 1)) 
           (setf x (rem (* x (+ x 1)) n)) 
           (setf factor (gcd (- x x_fixed) n)))
          ((or (<= count cycle_size) (<= factor 1)) 
           (setf count (+ count 1)) (for_loop))))

Notes

  • I named all variables and constants the same as in the C++ version.
  • I took half a day to decide whether or not to ask this question
  • If my Common Lisp code looks funny or silly you free to not-help

Solution

  • You really need to do more reading on Common Lisp. It has all the basic imperative constructs of C++, so there's no need to go through the contortions you have just to translate a simple algorithm. See for example Guy Steele's classic, available for free.

    Here is a more reasonable and idiomatic trans-coding:

    (defun prime-factor (n &optional (x 2))
      (let ((x-fixed x)
            (cycle-size 2)
            (factor 1))
        (loop while (= factor 1)
          do (loop for count from 1 to cycle-size
               while (<= factor 1)
               do (setq x (rem (1+ (* x x)) n)
                        factor (gcd (- x x-fixed) n)))
             (setq cycle-size (* 2 cycle-size)
                   x-fixed x)))
        factor))
    
    (defun test ()
      (prime-factor 10403))