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

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

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

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

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

textual
Листинг программы
  1. ;; НОД
  2.  
  3. (defun gcd (n m)
  4.   (cond ((> n m) (gcd m n))
  5.         ((zerop n) m)
  6.         (t (gcd n (- m n)))))
  7.  
  8. ;; Реверс списка
  9.  
  10. (defun reverse (x &optional (r nil))
  11.   (cond ((null x) r)
  12.         (t (reverse (cdr x) (cons (car x) r)))))
  13.  
  14. ==> reverse
  15.  
  16. (reverse '(1 2 3))
  17.  
  18. ==> (3 2 1)
  19.  
  20. ;; Решение
  21.  
  22. (defun lst-comm-div (n m &optional (g (gcd n m)) (r (list 1)) (i 2))
  23.   (cond ((>= i g) (reverse r))
  24.         ((and (zerop (mod n i)) (zerop (mod m i)))
  25.          (cond ((or (= 1 (car r)) (/= 0 (rem i (car r))))
  26.                 (lst-comm-div n m g (cons i r) (+ i 1)))
  27.                (t (lst-comm-div n m g r (+ i 1)))))
  28.          (t (lst-comm-div n m g r (+ i 1)))))
  29.  
  30. ==> lst-comm-div
  31.  
  32. (lst-comm-div 45 15)
  33.  
  34. ==> (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

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы