What is the time complexity of this nifty function 'assoc'?
I would assume that assoc is O(n)*, assuming that equal? is O(1) in your usage of the function. This is because it's trivial to write your own version of assoc:
(define (my-assoc v lst)
(cond ((null? lst) #f)
((equal? v (caar lst)) (car lst))
(else (my-assoc v (cdr lst)))))
You can see this simply slides down the list lst until a match is found. If none is found, #f is returned.
* technically equal? is O(n) where n is the size of the smaller input, so if you're comparing huge list structures using assoc, your runtime will be O(n*m) where n is the size of the list provided to assoc and m is the size of v.
Related
In my else condition I have two statements to execute. The first one ought to append my calculation to my return-list and the second one calls my recursive procedure again.
The problem is that my append procedure is being ignored so I am just returning an empty list.
(define (calcit x lst)
(cond ((= x 0)
retlst)
(else (append (list (floor (/ x (first lst)))) retlst)
(calcit (modulo x (first lst)) (rest lst)))))
You need to do something with the data you are creating. You probably want to have the first element consed on the result of the list you get from the recursion:
(define (calcit x lst)
(if (= x 0)
'() ;; base case
(cons (floor (/ x (first lst)))
(calcit (modulo x (first lst)) (rest lst)))))
When creating lists in Scheme with recursion try to avoid append. Using append is an anti pattern. Learn how Scheme lists work and train to know it intimately. eg '((2 3) (4 5)) if I ask you how to get 5 from that you should think d a d a and answer cadadr almost right away.
I'm a newbie in LISP. I'm trying to write a bubble sort function in LISP.
This is what I've done so far.
(defun mysort (x)
(if (null x) x
(if (< (car x) (cadr x))
(cons (car x) (mysort (cdr l)))
(cons (cadr x) (mysort (cons (car x) (cddr x)))))))
I'm getting an error
NIL is not a real number
When I modified the code like (after referring several codes)-
(defun mysort (x)
(if (null (cdr x)) x
(if (< (car x) (cadr x))
(cons (car x) (mysort (cdr l)))
(cons (cadr x) (mysort (cons (car x) (cddr x)))))))
Now it works fine.
Why does replacing
(if (null x) x...)
with
(if (null (cdr x)) x...)
make a difference?
Also, I'm calling mysort from another function to run it (length x) number of times. Is it possible to achieve complete sorting in a single recursive loop, only using the basic functions?
If you want to see if the first element is smaller than the second element, then the list needs to have at least two elements.
If there is only one element, CADR returns NIL. This is not a number.
CL-USER 18 > (cadr '(1))
NIL
Your Lisp system should not only tell you the error, but also the function where it occurred. Here: the function <.
Using (null (cdr list)) is a good way to test if there is a second element. A typical error would be to call LENGTH, which is inefficient.
To do a comparison you need at least two elements so checking if x is NIL is not enough.
Checking if (cdr x) is NIL is a nice way to check that the list length is at least two because NIL is special and even if it's not a cons cell it's guaranteed that (cdr NIL) is NIL.
The error you were getting is because NIL is not a number thus you cannot compare with < a number with it and this was happening when executing (< (car x) (cadr x)) when x was a list with a single element.
About sorting in a single recursive call you could use this definition of sorting:
an empty list is sorted
a non-empty list is sorted if the first element is the minimum of the list and the rest of the list is sorted.
This leads to
(defun mysort (x)
(if x
(let ((minimum (reduce #'min x)))
(cons minimum
(mysort (remove minimum x :count 1))))))
That, by the way, is a very inefficient way to do the sorting.
(pred 'r '(p q r)) -> q
Here's my idea-
- I have tried finding the function that returns the length of a specific element, but due to my lack of syntactical knowledge, I am unable to use the function.
- By using the length function as my helper function, I am trying to find the predecessor of an element in the list.
I hope that gives you guys some idea to start with or if you guys have a better idea, please let me know and also please show the coding too..
Thank you!
Based on your current attempt, here's a corrected version (with corrected indentation, as a bonus :-)):
(defun pred (x l)
(cond ((null (cdr l)) (car l))
((eq (cadr l) x) (car l))
(t (pred x (cdr l)))))
Are you sure you want to return the last element of the list if your expected element isn't found? It seems...strange, I'd have thought nil is a better return value.
Update: the OP wanted to implement both successor and predecessor functions. Here's how I'd implement them, in Scheme. (Sorry, not doing your homework for you, but if you know how to translate Scheme into Common Lisp, your life would be easier.)
(define (succ x lst)
(cond ((memv x lst) => (lambda (mem)
(and (pair? (cdr mem))
(cadr mem))))
(else #f)))
(define (pred x lst)
(let loop ((prev #f)
(rest lst))
(cond ((null? rest) #f)
((eqv? (car rest) x) prev)
(else (loop (car rest) (cdr rest))))))
and while memv is built-in to Scheme, you could implement it yourself quite simply:
(define (memv x lst)
(let loop ((rest lst))
(cond ((null? rest) #f)
((eqv? (car rest) x) rest)
(else (loop (cdr rest))))))
In particular, note the similarity between memv and pred.
You don't particularly need a length function to do this.
The obvious classical approach would be that if the cadr of the list equals the element you want, return the car of the list. Otherwise, return the search function on the cdr of the list. Other than that, you just need to deal with the boundary conditions (e.g., list that's empty or contains only one item).
This question already has answers here:
Flatten a list using only the forms in "The Little Schemer"
(3 answers)
Closed 9 years ago.
If I have an s expression, for example '(1 2 (3) (4 (5)) 6 7), how would I convert that into a list like (1 2 3 4 5 6 7)? I basically need to extract all of the atoms from the s expression. Is there a built in function that would help me do it?
(define (convert-to-list s) ... )
My algorithm so far is, if the first element is an atom append it onto a list. If the first element is a list then get the car of that element and then call the function (convert-to-list) with that function so it catches the base case of the recursion. And append the cdr of that list being invoked on convert-to-list to car of it. I'm trying to teach myself scheme from Structure and Interpretation of Computer Programs and I'm just trying out random things. Doing this recursively is proving to be more difficult than I anticipated.
To literally answer your question, "Is there a built in function to help me do this?", in Racket yes there is. flatten does exactly this: "Flattens an arbitrary S-expression structure of pairs into a list."
Examples:
> (flatten '((a) b (c (d) . e) ()))
'(a b c d e)
> (flatten 'a)
'(a)
However it's a great exercise to think about how you would write flatten yourself.
Chris Jester-Young's comment has a link to an elegant way. If she'd posted that as an answer, instead of as a comment, I'd suggest marking her answer as accepted, not mine. :)
Your algorithm doesn't look bad, it's just missing a step or two.
(define (flatten lst) ; 'flatten' is a better name for this function IMO
(cond
((null lst) nil)
;; Don't worry that I'm calling (flatten (cdr lst)) without any checking;
;; the above case handles it
((atom (car lst)) ; The car's okay
(cons (car lst) (flatten (cdr lst))))
((cons? (car lst)) ; The car still needs flattening; note the use of
; 'append' here (the car-list may have any number of elements)
(append (flatten (car lst)) (flatten (cdr lst))))))
Between the (flatten (car lst)) calls dealing with the first element and the (flatten (cdr lst)) calls recursively dealing with the rest of the list, the input list ends up a flat list (i.e. no elements are conses).
(Warning: I'm not a Scheme guru; the above code may contain errors.)
Your cases should cover the empty list, an atom, (car s) being an atom, and (car s) being a list.
This works, though I bashed out a list append function because I didn't remember what the built-in one was. Works in Racket Advanced Student.
(define (list-glue left-list right-list)
(cond
((null? left-list) right-list)
(else (cons (car left-list) (list-glue (cdr left-list) (right-list))))))
(define (convert-to-list s)
(cond
((null? s) '())
((not (list? s)) (cons s (quote ())))
((not (list? (car s))) (cons (car s) (convert-to-list (cdr s))))
(else
(list-glue
(convert-to-list (car s))
(convert-to-list (cdr s))))))
Now, if you want a faster implementation, you don't need append at all.
The idea is to pass around what you would append onto as a parameter. I call this tail.
If you have an empty s-exp, you just return the tail, since there is nothing to add to it.
I've got the code, flat and flat2, where flat uses a match statement, things in racket, and flat2 just uses a cond, which I find a little harder to read, but I provide it in case you haven't seen match yet.
#lang racket
(define (flat s-exp tail)
(match s-exp
['() tail]
[(cons fst rst)
(let ([new-tail (flat rst tail)])
(flat fst new-tail))]
[atom
(cons atom tail)]))
(define (flat
(cond
[(empty? s-exp) tail]
[(list? s-exp)
(let* ([fst (first s-exp)]
[rst (rest s-exp)]
[new-tail (flat])
(flat fst new-tail))]
[#t
(cons s-exp tail)]))
To use them, call them like so (flat '(1 () (2 (3)) 4) '()) ===> '(1 2 3 4).
You need to supply the empty list for them to start off on.
This can be done simply by recursing on sublists and rest-lists. You can see how easily this code reads. Like such:
(define (convert-to-list list)
(if (null? list)
'()
(let ((next (car list))
(rest (cdr list)))
(if (list? next)
(append (convert-to-list next) (convert-to-list rest))
(cons next (convert-to-list rest))))))
> (convert-to-list '(a b c))
(a b c)
> (convert-to-list '((a b) (((c d) e f) g h) i j))
(a b c d e f g h i j)
>
I want to create a function in lisp that receives a number and a list of pairs and iterates through the list of pairs and removes the ones in which the result of the division between the first element of the pair, and the second element of the same pair is different from the number passed as an argument. In the end it returns a list with only the ones in which the result of the division is the same.
I have the following code so far:
(defun retira-terco(num l1)
(cond ((null l1) ())
((not (equal num (/ (car(first l1)) (cdr(first l1)))))
(retira-terco num (rest l1)))
(t (cons (first l1) (retira-terco num (rest l1))))))
When I try to run this example with a real example I get the following error:
Error: `(1)' is not of the expected type `NUMBER'
What am I doing wrong?
The problem with your code is in this line:
(/ (car(first l1)) (cdr(first l1)))
(car (first l1)) evaluates to a number, but (cdr (first l1)) evaluates to a list. You probably meant (cadr (first l1)).
That said, this code isn't that great from a lispiness point of view. You have a condition you want to filter on. Use higher order programming to express that more like this:
(defun foo (num lst)
(remove-if (lambda (item)
(equal num
(/ (car item)
(cadr item))))
lst)))