2013-05-07 2 views
-3

Мне нужно сделать функцию в clisp, которая добавит все нечетные числа из набора. Например, подмножество (2,8), результат будет равен 15 (3 + 5 + 7).какие-либо предложения? У меня есть что-то вроде этого, где a - начало множества, а b - его конец.Функция Lisp, добавляющая нечетные числа из подмножества

(defun add (a b) 
(if(and(< a x) (> b x)) 
    (if(even(x)) 
     ((setq (x (+a 1))) (+ x 2)) 
     ((setq(x a)) (+ x 2)) 
      ))) 

EDIT:

(defun add (a b) 
(if(and(< a x) (> b x)) 
    (if(evenp x)) 
     ((setq (x (+a 1)) 
      (loop for x from a to b do (+ x 2)))) 
     ((setq(x a)) (+ x 2) 
      (loop for x from a to b do (+ x 2))) 
       )) 
+0

Начните с первого нечетного числа на уровне или равного началу диапазона, добавьте петлю 2 и добавьте все их к общей сумме, пока не закончите конец диапазона. – Barmar

+0

Ну, я понимаю, как должен работать алгоритм, я просто не знаю, как его реализовать в lisp. – user2167174

+0

Покажите, что вы пробовали, мы не здесь, чтобы делать домашнее задание для вас. – Barmar

ответ

0

Самый простой способ я вижу это использовать аппликативного программирования.

(defun range (max &key (min 0) (step 1)) 
     (loop for n from min below max by step 
     collect n)) 

Вы можете использовать функцию диапазона, чтобы сгенерировать интервал, как это:

(range 8 :min 2) => (2 3 4 5 6 7) 

, а затем фильтр с REMOVE-IF-не:

(remove-if-not #'oddp (range 8 :min 2)) => (3 5 7) 

и применить дополнение к результату :

(apply #'+ (remove-if-not #'oddp (range 8 :min 2))) => 15 

Вы можете обернуть выше функции тоже:

(defun add (a b) 
     (apply #'+ (remove-if-not #'oddp (range b :min a)))) 
+1

Не используйте APPLY, используйте REDUCE. –

+2

Использование RANGE не так хорошо в Common Lisp, так как оно фактически создает весь список. На ленивом языке это может быть не так. –

2

Самый прямой способ сделать это с LOOP. LOOP решение очень простое:

(defun sum-odds (start end) 
    (loop for i from start to end 
     when (oddp i) sum i)) 

(sum-odds 2 8) 
=> 15 

Для итерации, вы также можете использовать DO, но вы должны быть немного более четко о том, как все работает (и у вас есть еще много вариантов):

(defun sum-odds2 (begin end) 
    (do ((sum 0) 
     (i begin (1+ i))) 
     ((= i end) sum) 
    (when (oddp i) 
     (incf sum i)))) 

(sum-odds2 2 8) 
=> 15 

Если вы используете решение, которое создает список, содержащий диапазон целых чисел (который создает кучу промежуточных списков для сбора мусора), как это предлагается в некоторых других ответах, вы должны подумать, сколько раз вы проходите этот список (есть нет причин для его прохождения более одного раза). Вы можете использовать REDUCE просуммировать элементы списка с :key аргументом, что делает нечетные числа выглядят как сами по себе, и даже цифрам выглядят как 0:

(defun sum-odds3 (list) 
    (reduce '+ list 
      :key (lambda (n) 
       (if (oddp n) 
        n 
        0)))) 

(sum-odds3 '(2 3 4 5 6 7 8)) 
=> 15 
1

Я собирался сделать мою обычную фишку и поставить на коде -review hat, но, должным образом отформатировав вашу вторую попытку, здесь слишком много проблем, чтобы принять инкрементный подход. Вам нужно сесть и объяснить, что вы намеревались сделать для этого кода.

В частности, что происходит с x? Является ли это глобальной привязкой, которую вы переустанавливаете каждый раз, или вы имели в виду определить локальное связывание и случайно забыли, что и переменная if нуждается в переменной, прежде чем вы ее обходите? Что вы пытаетесь сделать с этими setq s, и что вы пытаетесь сделать с этими loops (как написано, ничего не делать)?


[временно Доны код-обзор шляпу]

Прежде всего, любезно format your code properly. Это небольшая вещь, но она значительно улучшает читаемость.

(defun add (a b) 
    (if (and (< a x) (> b x)) 
    (if (evenp x)) 
    ((setq (x (+ a 1)) 
      (loop for x from a to b do (+ x 2)))) 
    ((setq (x a)) (+ x 2) 
     (loop for x from a to b do (+ x 2))))) 

и с надлежащим уровнем отступа, довольно много ошибок просто падают на вас сразу.

  • Во-первых, что топ if имеет три положения, в нем (в if и два setq ые по какой-то причине).
  • Во-вторых, эта вторая if не имеет предложений, просто тест. Это означает, что он ничего не делает
  • В-третьих, вы вызываете некоторые очень странно названные функции в теле if. Я готов гарантировать, что ((setq (x a)) (+ x 2) (loop for x from a to b do (+ x 2))) не то, что вы имеете в виду, потому что это вызывает функцию (setq (x a)) по аргументам (+ x 2) и (loop ...).
  • В-четвертых, вы вызываете setq двумя разными неправильными способами. (setq (x (+ a 1)) Это попытка установить результат вызова функции x на (+ a 1) на NIL. (setq (x a)) (+ x 2) это пытается установить результат вызова функции x на a на NIL, а затем на оценку и отбрасывание (+ x 2).
0

Вы еще не сталкивались с проблемой алгоритма, пока не устранили синтаксические проблемы. Вы, видимо, догадались о решении и еще не собрали свою догадку. Ваш код не будет компилироваться и не будет запущен. Вы изучаете Лиспоподобные языки именно потому, что они допускают тривиальное исследование. Так что исследуй.

Смежные вопросы