0

I have a working function that finds the derivative of a given function with respect to a given variable. I also have a simplify function (define (simplify expr) that takes the output of the differentiation function (define (diff x expr) and simplifies it into an easy to read form. I am trying to implement a system that allows the user to enter an expression that they would like to find the derivative for and return the simplified derivative. What do I need to change in the 6th line of code to make this work?

#racket   
(display "Please enter an expression that you would like to differntiate: ")
(define expr (read))
(display expr)
(display " the derivative is ")
(display (simplify (diff 'x expr)))
(newline) 

My simplify and diff functions

#lang racket/base

(define (diff x expr)
  ; differentiation function which gives derivative given a variable
  (cond ((not (list? expr)) (if (equal? x expr) 1 0)) ; d/dx(x) = 1, d/dx(c) = 0
        (else
         (let ((operation (car expr))                  ; expr is (operation u v)
               (u (cadr expr))
               (v (caddr expr)))
           (case operation
             ((+) (list '+ (diff x u) (diff x v)))    ; d/dx (u+v) = d/dx(u) + d/dx(v)
             ((-) (list '- (diff x u) (diff x v)))    ; d/dx (u-v) = d/dx(u) - d/dx(v)
             ((*) (list '+                            ; d/dx (u*v) = u * d/dxuv) + v * d/dx(u)
                        (list '* u (diff x v))
                        (list '* v (diff x u))))
             ((/) (list '/ (list '-                   ; power rule
                                 (list '* v (diff x u))
                                 (list '* u (diff x v)))))
             ((^) (list '* v (list '*
                                   (list '^ u (- v 1))
                                   (diff x u)))))))))



(define (simplify expr)
  (if (not (list? expr))
      expr
      (let ((operation (car expr))
            (a (simplify (cadr expr)))
            (b (simplify (caddr expr))))
        (case operation
          ((+) (cond ((and (number? a) (number? b)) (+ a b)) ;; use Racket's ability to add
                     ((number? a)
                      (cond ((zero? a) (simplify b))
                            (else (list operation (simplify a) (simplify b)))))
                     ((number? b)
                      (cond ((zero? b) (simplify a))
                            (else (list operation (simplify a) (simplify b)))))
                     (else (list operation (simplify a) (simplify b)))))
          ((-) (cond ((and (number? a) (number? b)) (- a b)) ;; use Racket's ability to subtract
                     ((number? a)
                      (cond ((zero? a) (- (simplify b)))
                            (else (list operation (simplify a) (simplify b)))))
                     ((number? b)
                      (cond ((zero? b) (simplify a))
                            (else (list operation (simplify a) (simplify b)))))
                     (else (list operation (simplify a) (simplify b)))))
          ((*) (cond ((and (number? a) (number? b)) (* a b)) ;; use Racket's ability to mulitpy
                     ((number? a)
                      (cond ((zero? a) 0)
                            ((= a 1) (simplify b))
                            (else (list operation (simplify a) (simplify b)))))
                     ((number? b)
                      (cond ((zero? b) 0)
                            ((= b 1) (simplify a))
                            (else (list operation (simplify a)(simplify b)))))
                     (else (list operation (simplify a) (simplify b)))))
          ((/) (cond ((and (number? a) (number? b)) (/ a b)) ;; use Racket's ability to divide
                     ((number? a)
                      (cond ((zero? a) 0)
                            (else (list operation (simplify a) (simplify b)))))
                     ((number? b)
                      (cond ((zero? b) (error "Divison by 0, statement undefined!"))
                            ((= b 1) (simplify a))
                            (else (list operation (simplify a) (simplify b)))))
                     (else
                      (list operation (simplify a) (simplify b)))))
          ((^) (cond ((and (number? a) (number? b)) (expt a b)) ;; use Racket's ability to exponentiate
                     ((number? a)
                      (cond ((= a 1) 1)  ;; ((zero? a) 0) ;; depends on b [b < 0 then undefined]
                            (else (list operation (simplify a) (simplify b)))))
                     ((number? b)
                      (cond ((zero? b) 1) ;; depends on a [a = 0 then undefined]
                            ((= b 1) (simplify a))
                            (else (list operation (simplify a) (simplify b)))))
                     (else (list operation (simplify a) (simplify b)))))))))
Royale_w_cheese
  • 297
  • 2
  • 9
  • I don't understand - it works well - it just prints it on screen. You want to save the result somewhere? – Gwang-Jin Kim Oct 23 '18 at 00:47
  • It’s doesn’t print the derivative. For example, If you input 2x + 1, I want it to print 2. (The derivative of 2x + 1) – Royale_w_cheese Oct 23 '18 at 01:17
  • But `(read)` reads one expression. `"2x + 1"` passed to stdin is 3 expressions. `(read)` will only get **the symbol** `2x`. What exactly does `diff` take as argument? – Sylwester Oct 23 '18 at 01:25
  • I think you are the one that helped me the other day. So I assume you still have the differentiation function and the simplify function? – Royale_w_cheese Oct 23 '18 at 01:26
  • Even if it only gets the 2x, the derivative of that is 2 and that’s not the result I’m getting. – Royale_w_cheese Oct 23 '18 at 01:27
  • 1
    But in the other question the right way to write `2x` is `(2 * x)` so surely between reading `2x` and calling `diff` you need to process `2x` to `(2 * x)` or else `diff` won't work? – Sylwester Oct 23 '18 at 01:29
  • The function is (define (diff x expr) so the parameters are x and expr – Royale_w_cheese Oct 23 '18 at 01:29
  • 1
    Yes so the answer to `2x` would be the result of `(diff 'x '(2 * x))` no? – Sylwester Oct 23 '18 at 01:31
  • Ok so that would be 1of the two required arguments. How would I write the the input to the question “please enter an expression you would like to differentiate to correctly find the derivative of 2x+1. Do I need to change line 6 in my code? – Royale_w_cheese Oct 23 '18 at 01:34
  • Yes it would but I’m also calling simplify – Royale_w_cheese Oct 23 '18 at 01:35
  • But more importantly than this implementation, since you helped me with the simplify code a few days ago, could you please comment out the shorter version in a very detailed manner so I know what exactly is happening in each line. It will allow me to understand and learn this language much better. Thank you very much. – Royale_w_cheese Oct 23 '18 at 03:07
  • 1
    Yes, I will - but I am all day at work and cannot do it during working time. So in the evening time (middle european time), I can comment it. And @Sylwester the diff function is normal lisp syntax, so you give in '(* 2 x) for the function - not infix notation. – Gwang-Jin Kim Oct 23 '18 at 08:05
  • 1
    Did I understood correctly - you want to input `"2x + 1"` instead `(+ (* 2 x) 1)`? If I input last expression, then it correctly shows `2`. You didn't program it in a way that it can read `"2x + 1"` nor `(2 * x + 1)` which is infix notation. You can only input in prefix notation with your `diff` function and `simplify` function. To be able to read infix, you have to write a reader macro, that translates infix string to lisp's prefix notation. – Gwang-Jin Kim Oct 23 '18 at 08:41
  • 1
    In your case, you would need a whole new `read` function. – Gwang-Jin Kim Oct 23 '18 at 08:46
  • 2
    @Gwang-JinKim I'm pretty sure we are on the same page. Either user need to input the format that `diff` takes, eg. a s-expression, or there must be a parser of the format the user will use. If so I suggest you use `read-line` to get the input and and parse the string to the format `diff` needs. – Sylwester Oct 23 '18 at 09:01
  • 1
    @Sylwester: Yes, I was just explaining the OP that more work is needed if he wants that. Did you wrote often such kind of reader macros? – Gwang-Jin Kim Oct 23 '18 at 09:11
  • 1
    @Gwang-JinKim It cannot be a macro since it needs to parse a string that comes in from runtime. I have done some parsers, but not mathematical ones. I think mathematical notation gets hard very quickly, especially if you need to do [operator precedence](https://youtu.be/9e_oEE72d3U?t=313). Lisp syntax avoids this by design. – Sylwester Oct 23 '18 at 10:34
  • Thanks you guys very much. I understand what the problem was. I should’ve seen that all along. Especially @Gwang-JinKim thanks for all the help the past few days. And the commented code will give me a more complete understanding so I appreciate you doing that today after work. – Royale_w_cheese Oct 23 '18 at 11:10
  • 1
    @Royale_w_cheese I'll comment it in the evening! Welcome! :) – Gwang-Jin Kim Oct 23 '18 at 11:18
  • 1
    @Sylwester True, it would be just a parsing function for the string input. – Gwang-Jin Kim Oct 23 '18 at 11:25
  • 1
    I added now explanations in the previous post and even improved a little bit the simplify function. Now it can handle `(((((* 1 3))))))` extraparantheses -> `3` or `(- 1)` -> `-1` or also removes superfluous `(+ ((((* 3 1)))))` -> `3`. – Gwang-Jin Kim Oct 23 '18 at 19:13
  • Awesome @Gwang-Jin Kim. Thank you so much for your help. You really went out of your way to make sure I understand everything happening in the code. This will help me tremendously on my test and in becoming a better coder in general. It is very difficult to find people who know Lisp and even harder to find someone who genuinely cares about helping another human being learn. – Royale_w_cheese Oct 23 '18 at 19:24
  • 1
    Welcome! I'm happy that it helped you! Let's keep contact! I am happy about anyone learning Lisp. It was really hard for me and still is. We have to stick together and and help each other. Because this is the best computer language ever existing!) @Royale_w_cheese just ask whenever you have questions! Ah and a link to the comments https://stackoverflow.com/questions/52880911/how-to-fix-my-simplification-function-for-power-rule-to-make-results-easier-to/52899465?noredirect=1#comment92780913_52899465 – Gwang-Jin Kim Oct 23 '18 at 19:37
  • 1
    @Royale_w_cheese: by the way - I learned recursion by solving the questions and checking the answers in https://7chan.org/pr/src/The_Little_Schemer_4th_2.pdf - it is a super book - teaching you literally recursive thinking. Every minute spent in this book was worth it! – Gwang-Jin Kim Oct 23 '18 at 19:43

0 Answers0