Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > LISP > Помогите создать функцию "Calculate"


Автор: donserj 23.3.2011, 23:58
Пример: >(Calculate '((2 + 4) * 3)
Результат= 18

Автор: k0rvin 24.3.2011, 19:14
ты бы хоть написал, на каком диалекте.
на CL влоб:
Код

(defparameter *operators* (make-hash-table :test #'eq))

(defun set-operator (symbol priority function)
  (setf (gethash symbol *operators*)
        (cons priority function)))

(defun get-operator-priority (symbol)
  (multiple-value-bind (op foundp) (gethash symbol *operators*)
    (when foundp (car op))))

(defun get-operator-function (symbol)
  (multiple-value-bind (op foundp) (gethash symbol *operators*)
    (when foundp (cdr op))))

(defun operator-p (symbol &optional (errorp nil))
  (multiple-value-bind (op foundp) (gethash symbol *operators*)
    (declare (ignore op))
    (if (eq errorp t)
        (or foundp (error "Unknown operator ~a" symbol))
      foundp)))



(defun eval-infix (expr)
  (do ((expr expr))
      ((atom expr) expr)
    (destructuring-bind (left &rest rest) expr
      (if (null rest)
          (setf expr left)
        (destructuring-bind (op &rest rest) rest
          (operator-p op t)
          (if (null rest)
              (error "No right operand in (~s ~s)" left op)
            (destructuring-bind (right &rest rest) rest
              (if (null rest)
                  (setf expr
                        (funcall (get-operator-function op)
                                 (eval-infix left)
                                 (eval-infix right)))
                (destructuring-bind (rest-op &rest rest) rest
                  (operator-p rest-op t)
                  (let ((p1 (get-operator-priority op))
                        (p2 (get-operator-priority rest-op)))
                    (setf expr
                          (if (> p2 p1)
                              (list left op (eval-infix (list* right rest-op rest)))
                              (list* (funcall (get-operator-function op)
                                              (eval-infix left)
                                              (eval-infix right))
                                     rest-op
                                     rest)))))))))))))

(set-operator '+ 0 #'+)
(set-operator '- 0 #'-)
(set-operator '* 2 #'*)
(set-operator '/ 2 #'/)
(set-operator '^ 4 #'expt)

(defun calculate (expr)
  (eval-infix expr))


примеры использования:
Код

CL-USER 6 > (calculate '((1 + 2) * 3))
9

CL-USER 7 > (calculate '(1 + 2 * 3))
7

CL-USER 8 > (calculate '(1 + 2 * 3 ^ 4))
163

CL-USER 9 > (calculate '(1 * 2 / 3))
2/3

CL-USER 10 > 

Автор: _sg 25.4.2014, 15:10
как вариант:
Код

(defun prefix (w)
  (if (atom w) w `(,(cadr w) ,(prefix (car w)) ,(prefix (caddr w)))))

(defun calculate (w)
  (eval (prefix w)))

> (calculate '((2 + 4) * 3))
18

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)