Use lisp to output something while in cond - lisp

(define length1
(lambda (lat)
(cond
((null? lat) 0)
(else (+ 1 (length1 (cdr lat)))))))
for example: display the number (or anything else) when call length1 in cond

for common lisp you can use (progn (...) (...) ...) to group together multiple expressions into one.
the equivalent in scheme is (begin (...) (...) ...).
so:
(define length1
(lambda (lat)
(cond
((null? lat) 0)
(else (begin (display "hello world") (+ 1 (length1 (cdr lat))))))))
or maybe you want:
(define length1
(lambda (lat)
(cond
((null? lat) 0)
(else (let ((or-anything-else (+ 1 (length1 (cdr lat)))))
(display or-anything-else)
or-anything-else)))
and that's about exhausted my patience.

Related

Syntax error when using parentheses instead of brackets

I thought that brackets and parentheses were interchangeable in Racket.
However, when I run the following code, I get the syntax error, else: not allowed as an expression in: (else (cons (car lat) (rember a (cdr lat))))
#lang racket
(define rember
(lambda (a lat)
(cond
((null? lat) (quote ()))
((eq? a (car lat) (cdr lat))
(else
(cons (car lat) (rember a (cdr lat))))))))
The error goes away when I replace the parentheses in cond with brackets:
#lang racket
(define rember
(lambda (a lat)
(cond
[(null? lat) (quote ())]
[(eq? a (car lat)) (cdr lat)]
[else
(cons (car lat) (rember a (cdr lat)))])))
So it appears that there is a syntactic difference between parentheses and brackets. Is this the case or am I missing something?
You forgot one parenthesis in ((eq? a (car lat) (cdr lat)). If you rewrite that correctly, both versions will work:
(define rember
(lambda (a lat)
(cond
((null? lat) (quote ()))
((eq? a (car lat)) (cdr lat))
(else
(cons (car lat) (rember a (cdr lat)))))))

Don't know how to solve this error [Racket]: "car: contract violation expected: pair? given: '()"

I'm trying to get a list with the average of the following n elements. I'm reading a csv file that has 7 columns im just using the 6th one that has number values in order to get the average.
This is the code
;Function that returns a list containing the values of the desired column
(define (get-column col)
(let loop
([file (cdr(all-rows csv-path read-csv))]
[result empty])
(if (empty? file)
result
(loop (cdr file)
(cond
[(equal? col 1) (append result (list (caar file)))]
[(equal? col 2) (append result (list (string->number(cadar file))))]
[(equal? col 3) (append result (list (string->number(caddar file))))]
[(equal? col 4) (append result (list (string->number(car (cdddar file)))))]
[(equal? col 5) (append result (list (string->number(cadr (cdddar file)))))]
[(equal? col 6) (append result (list (string->number(caddr (cdddar file)))))]
[(equal? col 7) (append result (list (string->number(car (cdddr (cdddar file))))))]
)))))
(define (suma-SMA col n)
(let loop
([n n]
[res 0]
[col col])
(if (zero? n)
res
(loop (sub1 n) (+ res (car col)) (cdr col)))))
(define (get-SMA days)
(let loop
([col (get-column 6)]
[result empty])
(if (empty? col)
result
(loop (cdr col)(append result (list (suma-SMA col days)))))))
Here's a function that does what you asked for in the comments, e.g. given (1 2 3 4) it produces ((1+2)/2 (2+3)/2 (3+4)/2).
(define (sum list)
(cond
((null? list)
'()) ;; error?
((null? (cdr list))
'())
(else
(cons (/ (+ (car list) (cadr list)) 2) (sum (cdr list))))))
I'm still a bit confused because even the combination of get-SMA and suma-SMA does nothing like this. It's completely unclear what the days variable is doing, as you can see I didn't need it in my code above.
So I may have misunderstood what you are trying to do, but the function above does what you actually asked for so hopefully it will be helpful.
Here is the answer that I found useful for my problem.
(define (sum list n)
(cond
((null? list)
'()) ;; error?
((null? (cdr list))
'())
(else
(cons (suma-SMA list n) (sum (cdr list) n)))))

Racket Nested-Lists and applying functions to them

I'm trying to teach myself Racket. I'm currently trying to write a function to help understand nested lists. The function takes a nested list and a procedure and applies the procedure to each element to produce a new list. An example:
(map-tree even? '(1 2 3 4)) => '(#f #t #f #t)
Here's what I've got so far:
(define (map-tree proc tree)
(map-tree-aux tree proc '() ))
(define (map-tree-aux tree proc lst)
(if (null? tree)
lst
(if (list? tree)
(if (null? (cdr tree))
(if (number? (car tree))
(map-tree-aux (car tree) proc (append-end (proc (car tree)) lst))
(map-tree-aux (car tree) proc lst))
(if (number? (car tree))
(map-tree-aux (cdr tree) proc (append-end (proc (car tree)) (map-tree-aux (car tree) proc lst)))
(map-tree-aux (cdr tree) proc lst)))
lst)))
(define (append-end elem lst)
(append lst (list elem)))
While this works with the original example I supplied, a more complex example comes out incorrectly:
(map-tree even? '(1 (2 (3 (4))))) should be '(#f (#t (#f (#t)))), but is currently (#f #t #f #t).
I know it's just a matter is "listing" somewhere, but I'm having an issue finding out how to do it.
My first thought was to apply the list procedure to the lst if the tree is null and (car tree) is not a number, but I get the opposite of what I want (the resultant list is nested in the opposite direction). I'd really appreciate your help.
Thanks!
When iterating over list of lists, the general idea for the cases to check is:
if list is empty (null? lst), do something ...
if the first item in list is atomic (not (pair? (car lst))), do something else ...
if the first item in list is a list itself (pair? (car lst)), else ...
Choosing the right construct is also important, ie. instead of nesting if statements, using cond or match etc. is preferred.
Also try and avoid using non-constant time procedures (such as append) in your recursive steps to improve efficiency.
With these in mind, one approach to create the function in question is by simply using cons to build a new list while preserving the structure of the old, as follows:
(define (my-map pred lst)
(cond
((null? lst) '())
((not (pair? (car lst)))
(cons (pred (car lst))
(my-map pred (cdr lst))))
(else
(cons (my-map pred (car lst))
(my-map pred (cdr lst))))))
You can write the same function using match instead of cond:
(define (my-map pred lst)
(match lst
['() '()]
[(cons (? pair?) b)
(cons (my-map pred (car lst))
(my-map pred (cdr lst)))]
[(cons a b)
(cons (pred (car lst))
(my-map pred (cdr lst)))]))
You can also build a tail-recursive function that does this:
(define (my-map pred lst)
(let loop ((lst lst)
(acc '()))
(cond
((null? lst)
(reverse acc))
((not (pair? (car lst)))
(loop (cdr lst) (cons (pred (car lst)) acc)))
(else
(loop (cdr lst) (cons (loop (car lst) '()) acc))))))
Notice that (reverse acc) is returned in the base case because the list being built in the accumulator acc is in reverse order from the original list lst. To avoid this, we can modify this function to accumulate a continuation instead:
(define (my-map pred lst)
(let loop ((lst lst)
(acc identity))
(cond
((null? lst)
(acc '()))
((not (pair? (car lst)))
(loop (cdr lst) (lambda (r)
(acc (cons (pred (car lst)) r)))))
(else
(loop (cdr lst)
(lambda (r)
(acc (cons (loop (car lst) identity) r))))))))
For all cases, you will have:
(my-map even? '(1 2 3 4 5 7))
=> '(#f #t #f #t #f #f)
(my-map even? '(1 (2 (3 (4 (5 (7)))))))
=> '(#f (#t (#f (#t (#f (#f))))))

racket postfix to prefix

I have a series of expressions to convert from postfix to prefix and I thought that I would try to write a program to do it for me in DrRacket. I am getting stuck with some of the more complex ones such as (10 (1 2 3 +) ^).
I have the very simple case down for (1 2 \*) → (\* 1 2). I have set these expressions up as a list and I know that you have to use cdr/car and recursion to do it but that is where I get stuck.
My inputs will be something along the lines of '(1 2 +).
I have for simple things such as '(1 2 +):
(define ans '())
(define (post-pre lst)
(set! ans (list (last lst) (first lst) (second lst))))
For the more complex stuff I have this (which fails to work correctly):
(define ans '())
(define (post-pre-comp lst)
(cond [(pair? (car lst)) (post-pre-comp (car lst))]
[(pair? (cdr lst)) (post-pre-comp (cdr lst))]
[else (set! ans (list (last lst) (first lst) (second lst)))]))
Obviously I am getting tripped up because (cdr lst) will return a pair most of the time. I'm guessing my structure of the else statement is wrong and I need it to be cons instead of list, but I'm not sure how to get that to work properly in this case.
Were you thinking of something like this?
(define (pp sxp)
(cond
((null? sxp) sxp)
((list? sxp) (let-values (((args op) (split-at-right sxp 1)))
(cons (car op) (map pp args))))
(else sxp)))
then
> (pp '(1 2 *))
'(* 1 2)
> (pp '(10 (1 2 3 +) ^))
'(^ 10 (+ 1 2 3))
Try something like this:
(define (postfix->prefix expr)
(cond
[(and (list? expr) (not (null? expr)))
(define op (last expr))
(define args (drop-right expr 1))
(cons op (map postfix->prefix args))]
[else expr]))
This operates on the structure recursively by using map to call itself on the arguments to each call.

lisp simplify polynomials

I'm writting a program that simplifies polynimials, only addition and multiplication for now.
I've been slamming my head agains the keyboard for hours now and figure it was time to ask for some help.
(defun simplify (lis)
(if (eq (car lis) '+)
(cons '+ (simplify-addition (cdr lis)))
(if (eq (car lis) '*)
(cons '* (simplify-multiplication (cdr lis)))
)
)
)
(defun simplify-addition (lis)
(if (not (null lis))
(if (listp (car lis))
(list (simplify (car lis)) (simplify-addition (cdr lis)))
(if (numberp (car lis))
(if (eq (car lis) 0)
(simplify-addition (cdr lis))
(if (null (cdr lis))
lis
(cons (car lis) (simplify-addition (cdr lis)))
)
)
(if (eq (car lis) '+)
(list (car lis) (simplify-addition (cdr lis)))
(if (eq (car lis) '*)
(list (car lis) (simplify-addition (cdr lis)))
lis
)
)
)
)
)
)
(defun simplify-multiplication (lis)
(if (not (null lis))
(if (listp (car lis))
(if (find 0 (car lis))
0
(list (simplify (car lis)) (simplify-multiplication (cdr lis)))
)
(if (numberp (car lis))
(if (null (cdr lis))
lis
(cons (car lis) (simplify-multiplication (cdr lis)))
)
(if (eq (car lis) '+)
(list (car lis) (simplify-multiplication (cdr lis)))
(if (eq (car lis) '*)
(list (car lis) (simplify-multiplication (cdr lis)))
lis
)
)
)
)
)
)
This is what should happen:
(simplify ‘(+ x ( + 0 3 ) ( * 1 5 ) ( * ( * x y z ) 0 ) )) --> ( + x 3 5 )
(simplify ‘(* (+ 6 0) (* 1 6 2))) --------------------------------> (* 6 (* 6 2))
but instead i either get the same polynomial i sent in, or something completely off
EDIT:
The simplification that i need is to remove 0 from additions, so that:
(+ 3 0) --> 3
(+ 4 0 6) --> (+ 4 6)
and the multiplication with zero are removed
(* 6 0 7) --> 0
First you might want to improve your coding style a bit to make it readable.
don't put parentheses on their own lines. This just wastes space and doesn't help at all.
don't use CAR and CDR in domain specific code. The domain is mathematics. You use expressions (operator arg1 arg2). Instead using CAR and CDR define functions OPERATOR and ARGUMENTS and use them.
use CASE, COND and other multiway conditional expressions, instead of nested IF - where useful.
try to extract the traversal of data structures from domain code. Use higher order functions instead of recursion (MAP, REDUCE, ...).
Example:
Some basic domain functions:
(defun operator (expression)
(first expression))
(defun arguments (expression)
(rest expression))
(defun make-expression (operator arguments)
(if (= (length arguments) 1)
(first arguments)
(cons operator arguments)))
(defun is-zero? (expression)
(and (numberp expression)
(= expression 0)))
Now the simplifications:
(defun simplify (expression)
(if (atom expression)
expression
(case (operator expression)
(+ (make-expression '+ (simplify-addition (arguments expression))))
(* (make-expression '* (simplify-multiplication (arguments expression)))))))
(defun simplify-addition (expressions)
(remove-if #'is-zero?
(mapcar #'simplify
(remove-if #'is-zero? expressions))))
(defun simplify-multiplication (expressions)
(if (member-if #'is-zero? expressions)
(list 0)
(let ((expressions1 (mapcar #'simplify expressions)))
(if (member-if #'is-zero? expressions1)
(list 0)
expressions1))))
See, how much more readable the code is? No more CAR, LIS, CDR. The intention of the recursive invocations is also much clearer to understand.
It still not optimal, but it should get you going.
I've only looked at simplify-multiplication but there are a number of issues here.
On a general note, you want to recursively simplify first, then check for specific constants afterwards. (A post-order traversal, I guess.)
Second, I don't see you checking for 1 anywhere so I don't see how (* 1 5) ==> 5 is supposed to work.
Third, let's step through (simplify '(* (+ 2 0) 3)) for a bit:
(defun simplify-multiplication (lis)
; lis = '((+ 2 0) 3)
(if (not (null lis))
; ==> t
(if (listp (car lis))
; (car lis) = '(+ 2 0), so (listp '(+ 2 0)) ==> t
(if (find 0 (car lis))
; succeeds because '(+ 2 0) contains 0
; this is completely wrong! you're not supposed to check sublists of lis
0
; ... yeah, you just returned 0 just because there was a 0 *somewhere*
(list (simplify (car lis)) (simplify-multiplication (cdr lis)))
)
...
Or (simplify '(* 0 2)):
(defun simplify-multiplication (lis)
; lis = '(0 2)
(if (not (null lis))
; ==> t
(if (listp (car lis))
; (car lis) = 0, so (listp 0) ==> nil
(if (find 0 (car lis))
0
(list (simplify (car lis)) (simplify-multiplication (cdr lis)))
)
(if (numberp (car lis))
; (numberp 0) ==> t
(if (null (cdr lis))
; (cdr lis) = '(2), so (null '(2)) ==> nil
lis
(cons (car lis) (simplify-multiplication (cdr lis)))
; ... wait, what?
; you're just recursively walking through the list without
; checking what numbers you actually got. this won't simplify
; anything.
)
(if (eq (car lis) '+)
; what is this branch for? it can only succeed if you have code of the form
; (* 1 + 2)
; which is a syntax error
(list (car lis) (simplify-multiplication (cdr lis)))
(if (eq (car lis) '*)
; this branch is for code like (* * *). huh???
(list (car lis) (simplify-multiplication (cdr lis)))
lis
)
)
)
)
)
)