2015-08-20 1 views
1

Я работаю над программой, связанной с дифферентом дела с четными номерами в C и сюсюкать, закончила свою гр программу, но по-прежнему возникают проблемы с LISP функциейLisp функция (кол-во номера в общей шепелявости)

isprime определена и Мне нужна помощь в:

  1. определить функцию, которая возвращает primesinlist уникальные простые числа в лилии

здесь то, что я получил до сих пор, помощи с этим, пожалуйста?

(defun comprimento (lista) 
 
    (if (null lista) 
 
     0 
 
    (1+ (comprimento (rest lista)))))

(defun primesinlist (number-list) 
 
     (let ((result())) 
 
     (dolist (number number-list) 
 
      (when (isprime number) 
 
      (number result))) 
 
     (nreverse result)))

ответ

2

Вам нужно либо flatten аргумент перед обработкой:

(defun primesinlist (number-list) 
    (let ((result())) 
    (dolist (number (flatten number-list)) 
     (when (isprime number) 
     (push number result))) 
    (delete-duplicates (nreverse result)))) 

или, если вы хотите, чтобы избежать consi нг вверх fresh список, расплющить его, как вы идете:

(defun primesinlist (number-list) 
    (let ((result())) 
    (labels ((f (l) 
       (dolist (x l) 
       (etypecase x 
        (integer (when (isprime x) 
           (push x result))) 
        (list (f x)))))) 
     (f number-list)) 
    (delete-duplicates (nreverse result)))) 

Рассчитывать различные простые числа, возьмите length из списка, возвращаемого primesinlist.

В качестве альтернативы, вы можете использовать count-if:

(count-if #'isprime (delete-duplicates (flatten number-list))) 
+0

Вы не можете использовать 'count-if', потому что вам нужны уникальные возможности. – sds

+0

@sos: см. Править. – sds

0

Похоже, у вас уже есть тест на простоту реализации, но для полноты картины, позволяет добавить очень простой, который просто пытается разделить число числа меньше, чем до его квадратного корня:

(defun primep (x) 
    "Very simple implementation of a primality test. Checks 
for each n above 1 and below (sqrt x) whether n divides x. 
Example: 
    (mapcar 'primep '(2 3 4 5 6 7 8 9 10 11 12 13)) 
    ;=> (T T NIL T NIL T NIL NIL NIL T NIL T) 
" 
    (do ((sqrt-x (sqrt x)) 
     (i 2 (1+ i))) 
     ((> i sqrt-x) t) 
    (when (zerop (mod x i)) 
     (return nil)))) 

Теперь, вам нужен способ, чтобы сгладить потенциально вложенный список списков в один список. Когда вы приближаетесь к этой проблеме, мне обычно легче думать с точки зрения деревьев, построенных из cons-cells. Вот эффективная функция сглаживания, которая возвращает совершенно новый список. То есть он не имеет никакой структуры с исходным деревом. Это может быть полезно, особенно если мы хотим позже модифицировать результирующую структуру без изменения исходного ввода.

(defun flatten-tree (x &optional (tail '())) 
    "Efficiently flatten a tree of cons cells into 
a list of all the non-NIL leafs of the tree. A completely 
fresh list is returned. 

Examples: 
    (flatten-tree nil)    ;=>() 
    (flatten-tree 1)     ;=> (1) 
    (flatten-tree '(1 (2 (3)) (4) 5)) ;=> (1 2 3 4 5) 
    (flatten-tree '(1()() 5))  ;=> (1 5) 
" 
    (cond 
    ((null x) tail) 
    ((atom x) (list* x tail)) 
    ((consp x) (flatten-tree (car x) 
          (flatten-tree (cdr x) tail))))) 

Теперь это просто вопрос матирующие список, удаляя числа, которые не являются простыми, и удаления дубликатов из этого списка. Common Lisp включает в себя функции для выполнения этих задач, а именно: remove-if-not и remove-duplicates. Это «безопасные» версии, которые не изменяют входные аргументы. Поскольку мы знаем, что сплющенный список только что сгенерирован, мы можем использовать их (потенциально) деструктивные аналоги, delete-if-not и delete-duplicates.

Существует оговорка, когда вы удаляете повторяющиеся элементы.Если у вас есть список (1 3 5 3), возможны два возможных результата (при условии, что вы сохраните все остальные элементы в порядке): (1 3 5) и (1 5 3). То есть вы можете либо удалить более поздний дубликат, либо более ранний дубликат. В общем, у вас есть вопрос о том, «какой из них следует оставить?» Common Lisp по умолчанию удаляет ранее дубликат и оставляет последнее вхождение. Это поведение можно настроить с помощью аргумента : from-end. Может быть приятно дублировать это поведение в вашем собственном API.

Итак, вот функция, которая объединяет все эти соображения.

(defun primes-in-tree (tree &key from-end) 
    "Flatten the tree, remove elements which are not prime numbers, 
using FROM-END to determine whether earlier or later occurrences 
are kept in the list. 

Examples: 
    (primes-in-list '(2 (7 4) ((3 3) 5) 6 7)) 
    ;;=> (2 3 5 7) 

    (primes-in-list '(2 (7 4) ((3 3) 5) 6 7) :from-end t) 
    ;;=> (2 7 3 5)" 

    ;; Because FLATTEN-TREE returns a fresh list, it's OK 
    ;; to use the destructive functions DELETE-IF-NOT and 
    ;; DELETE-DUPLICATES. 
    (delete-duplicates 
    (delete-if-not 'primep (flatten-tree list)) 
    :from-end from-end))