Общий код на Лиспе для программы на C ++ с вложенными циклами

Я новичок в Common Lisp, но не так в C ++.
Есть простая программа на C ++, которую я пытаюсь отразить в CL (см. Пример варианта алгоритма Ро Полларда в C ++
).
Программа на C ++ работает без ошибок. Одно требование состоит в том, что все выходы обеих программ должны совпадать.

Версия C ++

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

Вот что я придумала. Отладка вызывает у меня кошмары, но я много раз пробовал и перебирал весь код, до сих пор понятия не имею, где я ошибся 🙁

(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))))

Заметки

  • Я назвал все переменные и константы так же, как в версии C ++.
  • Я потратил полдня, чтобы решить, стоит ли задавать этот вопрос
  • Если мой код Common Lisp выглядит смешно или глупо, вы можете не помогать

3

Решение

Вам действительно нужно больше читать о Common Lisp. Он имеет все основные императивные конструкции C ++, поэтому вам не нужно проходить через все искажения, которые вам нужны, просто чтобы перевести простой алгоритм. Смотри например Классика Гая Стила, доступна бесплатно.

Вот более разумное и идиоматическое транскодирование:

(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))
3

Другие решения

Вам нужно определить локальные переменные.

Базовый перевод кода C будет выглядеть примерно так:

(defun my-gcd (a b)
(let ((remainder 0))
(loop while (/= b 0) do
(setf remainder (mod a b)
a b
b remainder))
a))

или с объявлениями типа:

(defun my-gcd (a b)
(declare (integer a b))
(let ((remainder 0))
(declare (integer remainder))
(loop while (/= b 0) do
(setf remainder (mod a b)
a b
b remainder))
a))

integer тип данных в Common Lisp не ограничен — в отличие от int в C ++.

5