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

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

Related

how to iterate through a list in racket? if the character in the list is alphabetic, I want to add to a new string

Here is my code? Can anyone tell me how to iterate through a list? if the character in the list is alphabetic, I want to add to a new string
#lang racket
(define (conversion input)
(define s (string))
(let ((char (string->list input)))
(cond
[(char-alphabetic? (first (char)))
(string-append s first)]
[(char-alphabetic? (rest (char)))
(string-append s rest)]))
(display s))
Basic iteration is:
(define (copy-list lst)
(if (null? lst)
'()
(cons (car lst)
(copy-list (cdr lst))))
(copy-list '(1 2 3)) ; ==> (1 2 3)
This one actually makes a shallow copy of your list. Sometimes you iterate with keeping some variables to accumulate stuff:
(define (sum-list lst acc)
(if (null lst)
acc
(sum-list (cdr lst) (+ acc (car lst)))))
(sum-list '(1 2 3)) ; ==> 6
Looking at these you'll see a pattern emerges so we have made stuff like map, foldl, and foldr to abstract the iteration:
(define (copy-list-foldr lst)
(foldr cons '() lst)
(define (copy-list-map lst)
(map values lst))
(define (sum-list-foldl lst)
(foldl + 0 lst))
Looking at your challenge I bet you can fix it with a foldr.

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.

Splitting List with Racket

Given a list, and a number, n, I am trying to split a list into two separate lists: one into a list of length n, and the second list being the rest of the original list.
Here is what I have:
(define (part lst i)
(if (> i 0)
(list (append (list (first lst)) (list (part (rest lst) (- i 1)))))
(append lst)))
Where lst is the inputted list, and i is the number. When I input the list '(1 2 3 4) with the number 2, I return an output of: '((1 ((2 (3 4))))) instead of what I want which is '((1 2) (3 4)).
This is for a homework assignment, so it would be much appreciated if someone could just point me in the right direction as to where my problem lies, and because it is a hw assignment, I only am allowed to use the simple racket functions.
EDIT:
When I change the code to:
(define (part lst i)
(if (> i 0)
(append (list (first lst)) (list (part (rest lst) (- i 1))))
(append lst)))
I get an output of '(1 (2 (3 4))).
Using existing libraries
There's an easy way to solve this problem in Racket, just use the built-in split-at procedure (also available in the SRFI-1 library). This has the advantage of making a single pass across the input list:
(define (part lst i)
(let-values (((head tail) (split-at lst i)))
(list head tail)))
Another option would be to use Racket's built-in procedures take and drop (also available in SRFI-1) - but this will make two passes across the input list:
(define (part lst i)
(list (take lst i)
(drop lst i)))
Implementation from scratch
To build our own solution, we could write a procedure that makes a single pass, like this:
(define (part lst i)
(if (negative? i)
(error "index can't be negative")
(let loop ((lst lst) (acc '()) (i i))
(cond ((and (empty? lst) (positive? i))
(error "index is too large for list"))
((zero? i)
(list (reverse acc) lst))
(else
(loop (rest lst) (cons (first lst) acc) (sub1 i)))))))
Also, we could implement our own versions of take and drop - again, this will traverse the input list twice:
(define (my-take lst i)
(if (> i 0)
(cons (first lst)
(my-take (rest lst) (- i 1)))
'()))
(define (my-drop lst i)
(if (> i 0)
(my-drop (rest lst) (- i 1))
lst))
(define (part lst i)
(list (my-take lst i)
(my-drop lst i)))

Common Lisp: How to return a list without the nth element of a given list?

I've a question, how to return a list without the nth element of a given list? E.g., given list: (1 2 3 2 4 6), and given n = 4, in this case the return list should be (1 2 3 4 6).
A simple recursive solution:
(defun remove-nth (n list)
(declare
(type (integer 0) n)
(type list list))
(if (or (zerop n) (null list))
(cdr list)
(cons (car list) (remove-nth (1- n) (cdr list)))))
This will share the common tail, except in the case where the list has n or more elements, in which case it returns a new list with the same elements as the provided one.
Using remove-if:
(defun foo (n list)
(remove-if (constantly t) list :start (1- n) :count 1))
butlast/nthcdr solution (corrected):
(defun foo (n list)
(append (butlast list (1+ (- (length list) n))) (nthcdr n list)))
Or, maybe more readable:
(defun foo (n list)
(append (subseq list 0 (1- n)) (nthcdr n list)))
Using loop:
(defun foo (n list)
(loop for elt in list
for i from 1
unless (= i n) collect elt))
Here's an interesting approach. It replaces the nth element of a list with a new symbol and then removes that symbol from the list. I haven't considered how (in)efficient it is though!
(defun remove-nth (n list)
(remove (setf (nth n list) (gensym)) list))
(loop :for i :in '(1 2 3 2 4 6) ; the list
:for idx :from 0
:unless (= 3 idx) :collect i) ; except idx=3
;; => (1 2 3 4 6)
loop macro can be very useful and effective in terms of generated code by lisp compiler and macro expander.
Test run and apply macroexpand above code snippet.
A slightly more general function:
(defun remove-by-position (pred lst)
(labels ((walk-list (pred lst idx)
(if (null lst)
lst
(if (funcall pred idx)
(walk-list pred (cdr lst) (1+ idx))
(cons (car lst) (walk-list pred (cdr lst) (1+ idx)))))))
(walk-list pred lst 1)))
Which we use to implement desired remove-nth:
(defun remove-nth (n list)
(remove-by-position (lambda (i) (= i n)) list))
And the invocation:
(remove-nth 4 '(1 2 3 2 4 6))
Edit: Applied remarks from Samuel's comment.
A destructive version, the original list will be modified (except when n < 1),
(defun remove-nth (n lst)
(if (< n 1) (cdr lst)
(let* ((p (nthcdr (1- n) lst))
(right (cddr p)))
(when (consp p)
(setcdr p nil))
(nconc lst right))))
That's elisp but I think those are standard lispy functions.
For all you haskellers out there, there is no need to twist your brains :)
(defun take (n l)
(subseq l 0 (min n (length l))))
(defun drop (n l)
(subseq l n))
(defun remove-nth (n l)
(append (take (- n 1) l)
(drop n l)))
My horrible elisp solution:
(defun without-nth (list n)
(defun accum-if (list accum n)
(if (not list)
accum
(accum-if (cdr list) (if (eq n 0) accum (cons (car list) accum))
(- n 1))))
(reverse (accum-if list '() n)))
(without-nth '(1 2 3) 1)
Should be easily portable to Common Lisp.
A much simpler solution will be as follows.
(defun remove-nth (n lst)
(append (subseq lst 0 (- n 1)) (subseq lst n (length lst)))
)