racket - calculate polynomial function - racket

I'm trying to wite a function eval/x that consumes a polynomial expression ex and a Num val that represents the current value of x, and produces the result of evaluating the expression when the value is used for x . For example:
(eval/x (make-pnode '+ 11 12) 159) => 23
(eval/x 'x 66) => 66
(eval/x (make-pnode '+ (make-pnode '* 'x -7) 3) -2) => 17
(eval/x (make-pnode '* 'x (make-pnode '+ 'x 1)) 5) => 30
I know how to evaluate an expression but I don't know how to put the value of x in the expression. Can anyone help? Thanks a lot
(define-struct pnode (op arg1 arg2))
(define (eval ex val)
(cond
[(number? ex) ex]
[else (local
[(define operation (pnode-op ex))
(define left (eval (pnode-arg1 ex)))]
(define right (eval (pnode-arg2 ex)))]
(cond
[(symbol=? operation '+) (+ left right)]
[(symbol=? operation '-) (- left right)]
[(symbol=? operation '*) (* left right)]
[(symbol=? operation '/) (/ left right)]))]))

You almost had it there. Simply add an additional case, if you find a symbol then return the value - and make sure to pass it along in the recursion:
(define (eval/x ex val)
(cond
[(number? ex) ex]
[(symbol? ex) val] ; add this line
[else (local
[(define operation (pnode-op ex))
(define left (eval/x (pnode-arg1 ex) val))
(define right (eval/x (pnode-arg2 ex) val))]
(cond
[(symbol=? operation '+) (+ left right)]
[(symbol=? operation '-) (- left right)]
[(symbol=? operation '*) (* left right)]
[(symbol=? operation '/) (/ left right)]))]))
It works as expected:
(eval/x (make-pnode '+ 11 12) 159)
=> 23
(eval/x 'x 66)
=> 66
(eval/x (make-pnode '+ (make-pnode '* 'x -7) 3) -2)
=> 17
(eval/x (make-pnode '* 'x (make-pnode '+ 'x 1)) 5)
=> 30

Related

Why we can't use (values) like this?

(define (avg . l)
(/ (apply + l) (length l)))
(define (delist ls)
(apply values ls))
(avg (delist '(1 2 3))) ;;error
(avg 1 2 3) ;; return 2
without call-with-values, can I bind the value returned by values to each parameter in other ways?
can I bind the value returned by values to each parameter in other ways?
Here are most of the ways I know of to bind variables to returned values in Racket:
#lang racket/base
(define (list->values lst) (apply values lst))
(define-values (a b c) (list->values '(1 2 3)))
(displayln (+ a b c))
(let-values ([(d e f) (list->values '(4 5 6))])
(displayln (+ d e f)))
(require racket/match)
(match/values (list->values '(7 8 9))
([x y z] (displayln (+ x y z))))
(require srfi/8)
(receive (i j k) (list->values '(10 11 12)) (displayln (+ i j k)))
(displayln (call-with-values (lambda () (list->values '(13 14 15))) +))

Never called Lisp function

(defun func (in s f l)
(cond
((null in) (append l (list (list 'end (+ 1 f)))))
((eq (car in) 'foo) (foo-asd (cdr in) s f l))
((atom (car in))(atom-asd in (+ 1 s) (+ 1 f) l))
))
.
(defun atom-asd (in s f l)
(cond ((eql in nil) ())
(append l (list (list 'frob s (car in) (+ 1 f))))))
.
(defun foo-asd (in s f l)
(cond
((eql in nil) (append l (list (list 'frob s 'myst f))))
((func in s f (append l (list (list 'frob s 'myst (+ 1 f))))))
((foo-asd (cdr in) s f l))
))
.
Regarding this code if call (func '(foo x y) 0 0 ()) the function foo-asd will be called, then func is called again and it will enter the function atom-asd, when atom-asd ends it execution, all the program ends, without calling the recursive call foo-asd. I need foo-asd to be called, but i do not understand why it isn't called after atom-asd ends.
[4]> (trace func)
;; Tracing function func.
(func)
[5]> (trace atom-asd)
;; Tracing function atom-asd.
(atom-asd)
[6]> (trace foo-asd)
;; Tracing function foo-asd.
(foo-asd)
[7]> (func '(foo x y) 0 0 ())
1. Trace: (func '(foo x y) '0 '0 'nil)
2. Trace: (foo-asd '(x y) '0 '0 'nil)
3. Trace: (func '(x y) '0 '0 '((frob 0 myst 1)))
4. Trace: (atom-asd '(x y) '1 '1 '((frob 0 myst 1)))
*** - cond: variable append has no value
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead of append.
STORE-VALUE :R2 Input a new value for append.
ABORT :R3 Abort main loop
Break 1 [8]>
So in atom-asd:
(defun atom-asd (in s f l)
(cond
((eql in nil)
())
(append
l (list (list 'frob s (car in) (+ 1 f))))))
You have two predicates. one tests (eql in nil) which obviously is nil, then it checks if the variable append has a non nil value. Problem is append is not a bound variable. It is a binding in the function namespace, but here every term is inclused in one set of parentheses so append is by itself th eexpression that gets tested. You might have meant that it should do (append ...) when the first term didn't kick in and you should have written it like this:
(defun atom-asd (in s f l)
(cond
((eql in nil)
())
(t
(append l (list (list 'frob s (car in) (+ 1 f)))))))
With this version we get a result:
[8]> (func '(foo x y) 0 0 ())
5. Trace: (func '(foo x y) '0 '0 'nil)
6. Trace: (foo-asd '(x y) '0 '0 'nil)
7. Trace: (func '(x y) '0 '0 '((frob 0 myst 1)))
8. Trace: (atom-asd '(x y) '1 '1 '((frob 0 myst 1)))
8. Trace: atom-asd ==> ((frob 0 myst 1) (frob 1 x 2))
7. Trace: func ==> ((frob 0 myst 1) (frob 1 x 2))
6. Trace: foo-asd ==> ((frob 0 myst 1) (frob 1 x 2))
5. Trace: func ==> ((frob 0 myst 1) (frob 1 x 2))
((frob 0 myst 1) (frob 1 x 2))

Racket: simplify arithmetic expressions with variables

I am trying to implement a function
; (simplify expr)
;
; where expr is one of the following
; - a number
; - a symbol
; - a list of the form '(a operator b) where a and b are arithmetic expressions
The function is NOT supposed to simplify the arithmetic expression as far as possible, I just need it to simplify the subexpressions without variables:
examples:
(simplify '(3 + a)) => '(3 + a)
(simplify '(((2 + (3 * 4)) * a) + 2) => '((14 * a) + 2)
(simplify '((2 + (3 - a)) * 2) => '((2 + (3 - a)) * 2)
I already implemented a function that evaluates an arithmetic expression:
(define (eval t)
(cond
[(number? t) t]
[else ((cond
[(equal? (second t) '+) +]
[(equal? (second t) '-) -]
[(equal? (second t) '*) *]
[(equal? (second t) '/) /])
(eval (first t)) (eval (third t)))]))
This is what I have so far, but aside from the fact that it does not even work properly, I guess that there is a much better way.
(define (simplify t)
(cond
[(number? t) t]
[(equal? 'a (first t)) `(,(first t) ,(second t) ,(simplify (third t))) ]
[(equal? 'a (third t)) `(,(simplify (first t)) ,(second t) ,(third t)) ]
[else ((cond
[(equal? (second t) '+) +]
[(equal? (second t) '-) -]
[(equal? (second t) '*) *]
[(equal? (second t) '/) /])
(simplify (first t)) (simplify (third t)))]))
Any help is greatly appreciated!
The key insight is that
(number operation number)
can be simplified to
the result of evaluating (number operation number)
So add a clause in simplify that checks for the pattern (number operation number) then use your eval function to find the result.

number of sub-lists in a list, having an even sum, from odd levels in Lisp

I have a non-linear list. I need to find out the number of sub-lists at any level in the initial list, for which the sum of the numerical atoms at the odd levels, is an even number. The superficial level is counted as 1. I wrote something like:
(defun numbering (l level)
;counts the levels that verify the initial conditions
(cond
((null l) l)
((and (verify (sumlist l)) (not (verify level))) (+ 1 (apply '+ (mapcar#' (lambda (a) (numbering a (+ 1 level))) l))))
(T (apply '+ (mapcar#' (lambda (a) (numbering a (+ 1 level))) l )))
)
)
(defun verify (n)
;returns true if the parameter "n" is even, or NIL, otherwise
(cond
((numberp n)(= (mod n 2) 0))
(T f)
)
)
(defun sumlist (l)
;returns the sum of the numerical atoms from a list, at its superficial level
(cond
((null l) 0)
((numberp (car l)) (+ (car l) (sumlist(cdr l))))
(T (sumlist(cdr l)))
)
)
(defun mainNumbering (l)
; main function, for initializing the level with 1
(numbering l 1)
)
If I run "(mainnum '(1 2 (a b 4) 8 (6 g)))" I get the error: " Undefined function MAPCAR# called with arguments ((LAMBDA (A) (NUMEROTARE A #)) (1 2 (A B 4) 8 (6 G)))."
Does anyone know, what am I missing? Thanks in advance!
Well, that's true, there is no such function as mapcar#, it's just a typo, you missing space in this line:
(T (apply '+ (mapcar#' (lambda (a) (numbering a (+ 1 level))) l )))
It should be:
(T (apply '+ (mapcar #'(lambda (a) (numbering a (+ 1 level))) l )))
Here is a possible solution, if I have interpreted correctly your specification:
(defun sum(l)
(loop for x in l when (numberp x) sum x))
(defun test(l &optional (level 1))
(+ (if (and (oddp level) (evenp (sum l))) 1 0)
(loop for x in l when (listp x) sum (test x (1+ level)))))
(test '(1 2 (a b 4) 7 (6 2 g) (7 1 (2 (3) (4 4) 2) 1 a))) ; => 2
The function sum applied to a list returns the sum of all its numbers (without entering in its sublists).
The function test, for a list with an odd level, sum its numbers, and, if the result is even, add 1 to the sum of the results of the function applied to the sublists of l, 0 otherwise.
in numbering you should add the case when l is a number,so
(defun numbering (l level)
;counts the levels that verify the initial conditions
(cond
((null l) l)
((atom l)0)
((and (verify (sumlist l)) (not (verify level))) (+ 1 (apply '+ (mapcar #' (lambda (a) (numbering a (+ 1 level))) l))))
(T (apply '+ (mapcar #'(lambda (a) (numbering a (+ 1 level))) l )))
)
)
will resolve the problem

Looping over a list and generate serial statements in a lambda

I have a macro called compare-and-swap!:
(define-macro (compare-and-swap! l x y)
`(if (> (vector-ref ,l ,x) (vector-ref ,l ,y))
(vector-swap! ,l ,x ,y)))
It works, I'm testing it like this:
(define v (list->vector '(5 4 3 2 1)))
(print v)
(compare-and-swap! v 1 2)
(print v)
I have a function that returns a list of pairs that I can call compare-and-swap! on serially to sort the whole list:
(batcher 8) → ((0 1) (2 3) (0 2) (1 3) (1 2) (4 5) (6 7) (4 6) (5 7) (5 6) (0 4) (2 6) (2 4) (1 5) (3 7) (3 5) (1 2) (3 4) (5 6))
Now I wish to create a macro that generates a lambda that sorts an N element list by calling batcher and doing the compare-and-swap! for each pair.
For example,
(generate-sorter 8)
→
(lambda (l) (begin (compare-and-swap! l 0 1) (compare-and-swap! l 2 3) ...))
→
(lambda (l) (begin (if (> (vector-ref l 0) (vector-ref l 1)) (vector-swap! 0 1)) (if (> (vector-ref l 2) (vector-ref l 3)) (vector-swap! 2 3))) ... )
I made a function that generates the necessary code:
(define generate-sorter (lambda (len)
(list 'lambda '( li ) 'begin (map (lambda (pair) (list 'compare-and-swap! 'li (first pair) (second pair))) (batcher len)))
))
But I don't now how to make it into a macro.
You don't need a macro for this and, in particular, for the 'generate' part. I suspect that you were thinking macro because the result of generate-sorter can vary from call to call and you hoped to encode the result through macro expansion. An alternative is to capture the result in the lexical environment as such:
(define-syntax compare-and-swap!
(syntax-rules ()
((_ l x y)
(when (> (vector-ref l x) (vector-ref l y))
(vector-swap! l x y)))))
(define (generate-sorter n)
(let ((sorters (generate-sorter n)))
(lambda (l)
(for-each (lambda (sorter)
(compare-and-swap! l (car sorter) (card sorter)))
sorters))))
(define sorter-8 (generate-sorter 8))
(sorter-8 <l-thingy>)
-> <sorted-l-thingy>