Write a Scheme function (sumList) - racket

Write a Scheme function (sumList) that returns the sum of all the numbers in a list which should be passed as a parameter. The list can have numbers, non-numeric symbols, and other lists. Your function should select all the number in the sublists and add them to the total. You can assume that the total is 0 if the list is empty. Example Usage:
(sumList '((1 2 3) 5 a (10) ())
21

(define (sumList lst)
(cond
([empty? lst]
0)
([list? (car lst)]
(+ (sumList (car lst)) (sumList (cdr lst))))
((not(number? (car lst)))
(sumList (cdr lst)))
(else
(+ (car lst)(sumList (cdr lst))))))

Related

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)))))

How to fix contract violation for lists of list in racket?

I am learning Racket for understanding principles of programming languages. What I am doing is to add only second elements in pairs of a list. In my understanding, I think I am doing correctly. However, the error message shows up. Please provide me any advise to understand what I am doing wrong.
(define pairs
'((1 5)(6 4)(7 8)(15 10)))
(define (secondSum lst)
(if (null? lst) 0
(+ (cdr (car lst)) (secondSum (cdr lst)))
)
)
>(secondSum pairs)
+: contract violation
expected: number?
given: '()
argument position: 2nd
other arguments...:
10
What I am looking for is
(5 + 4 + 8 + 10)
(cdr (car lst)) should be (car (cdr (car lst))) also (cadr (car lst)) or in racket preferred (second (first lst)) that is if lst is '((1 5)) the result should be 5.
I had to be sure this was right so I ran the program with the fix and verified the result:
(define pairs '((1 5)(6 4)(7 8)(15 10)))
(define (secondSum lst)
(if (null? lst) 0
(+ (car (cdr (car lst))) (secondSum (cdr lst)))
)
)
(secondSum pairs)
(+ 5 4 8 10)
The last two expressions both have the value 27.

Write a function COUNT-NUMBERS that counts the number of numbers in a list

I'm begginer at LISP, and I have a question need your help.
Write a function COUNT-NUMBERS that counts the number of numbers in a list,and return " NO NUMBER" if there is no number in the list
For example, for a list: (A 2.3 B C 4 5), it returns 3.
I've tried with the following code, but it doesn't work . Could you help me to figure out? Moreover, I don't know how to return "NO NUMBER" if there is no number in the list.
(defun count-numbers (x)
(cond ((null x) 0)
((numberp x) 1)
(t (+(count-numbers (car x))(count-numbers (cdr x))))))
Thanks in advance,
You could to define a inner helper function to do the counting, and check the result to decide what to return in the main function:
(defun number-counter (lst)
(labels ((do-count (l)
(cond ((null l) 0)
((numberp (car l)) (+ 1 (do-count (cdr l))))
(t (do-count (cdr l))))))
(let ((r (do-count lst)))
(if (= r 0) 'NO-NUMBER r))))
This would be a tail-recursive version. Somehow you have to check what to return.
(defun count-numbers (list &optional (n 'no-number))
(cond ((null list) n)
((numberp (first list))
(count-numbers (rest list)
(if (eq n 'no-number)
1
(1+ n))))
(t (count-numbers (rest list) n))))
With a LOOP you can write that this way:
(defun count-numbers (list)
(loop for element in list
count (numberp element) into n
finally (return (if (zerop n) 'no-number n))))

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.

Scheme Function to reverse elements of list of 2-list

This is an exercise from EOPL.
Procedure (invert lst) takes lst which is a list of 2-lists and returns a list with each 2-list reversed.
(define invert
(lambda (lst)
(cond((null? lst )
'())
((= 2 (rtn-len (car lst)))
( cons(swap-elem (car lst))
(invert (cdr lst))))
("List is not a 2-List"))))
;; Auxiliry Procedure swap-elements of 2 element list
(define swap-elem
(lambda (lst)
(cons (car (cdr lst))
(car lst))))
;; returns lengh of the list by calling
(define rtn-len
(lambda (lst)
(calc-len lst 0)))
;; calculate length of the list
(define calc-len
(lambda (lst n)
(if (null? lst)
n
(calc-len (cdr lst) (+ n 1)))))
This seems to work however looks very verbose. Can this be shortened or written in more elegant way ?
How I can halt the processing in any of the individual element is not a 2-list?
At the moment execution proceed to next member and replacing current member with "List is not a 2-List" if current member is not a 2-list.
The EOPL language provides the eopl:error procedure to exit early with an error message. It is introduced on page 15 of the book (3rd ed.).
The EOPL language does also include the map procedure from standard Scheme. Though it may not be used in the book, you can still use it to get a much shorter solution than one with explicit recursion. Also you can use Scheme's standard length procedure.
#lang eopl
(define invert
(lambda (lst)
(map swap-elem lst)))
;; Auxiliary Procedure swap-elements of 2 element list
(define swap-elem
(lambda (lst)
(if (= 2 (length lst))
(list (cadr lst)
(car lst))
(eopl:error 'swap-elem
"List ~s is not a 2-List~%" lst))))
So it seems that your version of invert actually returns a list of different topology. If you execute (invert ...) on '((1 2) (3 4)), you'll get back '((2 . 1) (4 . 3)), which is a list of conses, not of lists.
I wrote a version of invert that maintains list topology, but it is not tail-recursive so it will end up maintaining a call stack while it's recursing.
(define (invert lst)
(if (null? lst)
lst
(cons (list (cadar lst) (caar lst))
(invert (cdr lst)))))
If you want a version that mimics your invert behavior, replace list with cons in second to last line.
If you want it to exit early on failure, try call/cc.
(call-with-current-continuation
(lambda (exit)
(for-each (lambda (x)
(if (negative? x)
(exit x)))
'(54 0 37 -3 245 19))
#t))
===> -3
(Taken from http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_idx_566)
What call-with-current-continuation (or call/cc, for short) does is pass the point where the function was called in into the function, which provides a way to have something analogous to a return statement in C. It can also do much more, as you can store continuations, or pass more than one into a function, with a different one being called for success and for failure.
Reverse list containing any number or order of sub-lists inside.
(define (reverse! lst)
(if (null? lst) lst
(if (list? (car lst))
(append (reverse! (cdr lst)) (cons (reverse! (car lst)) '()))
(append (reverse! (cdr lst)) (list (car lst))))))