Общие делители чисел - Lisp

Узнай цену своей работы

Формулировка задачи:

Помогите пожалуйста,нужно найти общие делители двух чисел.Например 64 и 32.Общими делителями будут 1 2 4 8 16 32.Но в ответе нужно проверить: если следующее число делится на предыдущее без остатка, то его не выводим. Получаемый ответ: 1 2

Решение задачи: «Общие делители чисел»

textual
Листинг программы
;; НОД
 
(defun gcd (n m)
  (cond ((> n m) (gcd m n))
        ((zerop n) m)
        (t (gcd n (- m n)))))
 
;; Реверс списка
 
(defun reverse (x &optional (r nil))
  (cond ((null x) r)
        (t (reverse (cdr x) (cons (car x) r)))))
  
==> reverse
 
(reverse '(1 2 3))
 
==> (3 2 1)
 
;; Решение
 
(defun lst-comm-div (n m &optional (g (gcd n m)) (r (list 1)) (i 2))
  (cond ((>= i g) (reverse r))
        ((and (zerop (mod n i)) (zerop (mod m i)))
         (cond ((or (= 1 (car r)) (/= 0 (rem i (car r))))
                (lst-comm-div n m g (cons i r) (+ i 1)))
               (t (lst-comm-div n m g r (+ i 1)))))
         (t (lst-comm-div n m g r (+ i 1)))))
 
==> lst-comm-div
 
(lst-comm-div 45 15)
 
==> (1 3 5)

Объяснение кода листинга программы

Код решает задачу поиска общих делителей двух чисел.

  1. Начиная с функции gcd, которая вычисляет наибольший общий делитель (НОД) двух чисел n и m. Используется рекурсивный алгоритм. Если n больше m, то функция вызывает саму себя, но уже с аргументами m и n. Если n равно нулю, то возвращается m. Иначе, функция продолжает поиск НОДа, вычитая из n частное от деления на m.
  2. Функция reverse реверсирует список. Если список пуст, то возвращается nil. Иначе, функция вызывает саму себя, но уже с аргументом cdr от первого элемента списка и списком, в который добавляется первый элемент списка (который удаляется из списка), а также возвращаемым значением.
  3. Функция lst-comm-div находит общие делители чисел n и m. Изначально, список общих делителей r инициализируется списком [1], а переменная i равна 2. Если индекс i больше или равен значению, которое хранится в переменной g (которая инициализируется значением, равным НОД n и m), то возвращается список r, перевёрнутый с помощью функции reverse. Иначе, если остаток от деления n на i равен нулю и остаток от деления m на i также равен нулю, то текущий элемент списка r (к которому добавляется i) не является общим делителем, и мы переходим к следующему элементу списка (увеличивая значение i на 1). Если текущий элемент списка r делится на i без остатка, то мы переходим к следующему элементу списка (увеличивая значение i на 1). Если текущий элемент списка r не делится на i без остатка, то мы переходим к следующему элементу списка (увеличивая значение i на 1). Если текущий элемент списка r равен nil, то мы переходим к следующему элементу списка (увеличивая значение i на 1). Если текущий элемент списка r не равен nil, то мы переходим к следующему элементу списка (увеличивая значение i на 1). Если мы дошли до конца списка r, то возвращается значение nil.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

8   голосов , оценка 4 из 5
Похожие ответы