Lisp S-Expressions and Lists Length/Size - list

I am trying to write a function using Common Lisp functions only that will count how many s-expressions are in an s-expression. For example:
((x = y)(z = 1)) ;; returns 2
and
((x - y)) ;; returns 1
Nested expressions are possible so:
((if x then (x = y)(z = w))) ;; returns 3
I wrote a function which finds the length and it works if no nested expressions are there. It is:
(define (length exp)
(cond
((null? exp) 0)
(#t (+ 1 (length (cdr exp))))))
Now I modified this in an attempt to support nested expressions to the following:
(define (length exp)
(cond
((null? exp) 0)
((list? (car exp)) (+ 1 (length (cdr exp))))
(#t (length (cdr exp)))))
This works for expressions with no nests, but is always 1 less than the answer for nested expressions. This is because taking the example above, ((if x then (x = y)(z = w))), this will look at if at first and which satisfies the third condition, returning the cdr (the rest of the expression as a list) into length. The same happens up until (x=y) is reached, at which point a +1 is returned. This means that the expression (if x then .... ) has not been counted.
In what ways would I be able to account for it? Adding +2 will over-count un-nested expressions.
I will need this to work in one function as nesting can happen anywhere, so:
((x = y) (if y then (z = w)))

At first sight, your code only recurses to the right (cdr-side) and not to the left (car-side), so that definitely is a problem there.
On second sight, this is even a little bit more tricky than that, because you are not exactly counting conses; you need to differentiate the case where a cons starts a proper list vs where it's the cdr of a list. If you were to recurse to the car and cdr, that information would be lost. We need to iterate over the sexp as a proper list,
(defun count-proper-list (sexp)
(cond ((atom sexp) 0)
(t (1+ (reduce #'+ (mapcar #'count-proper-list sexp))))))
But this will also count the top level list, therefor always return one more than what you seem to want. So perhaps,
(defun count-proper-sublist (sexp)
(1- (count-proper-list sexp)))

Related

Abstract List Functions in Racket/Scheme - Num of element occurrences in list

So I'm currently stuck on a "simple?" function in Racket. It's using the Intermediate Student with lambda language.
Some restrictions on this are that NO recursion is allowed, neither are local functions. It's plain and simple abstract list functions.
What this function is supposed to do is to take in a list of numbers, and output a list of pairs in which each pair has the first element as the number with the second element being the number it has occurred in the list.
Examples:
(1 1 2 3) => ((1 2) (2 1) (3 1))
(2 3 4 3) => ((2 1) (3 2) (4 1))
I have a function that produces the number of occurrences by inputting a list of numbers and a number which is:
(define (occurrences lon n)
(length (filter (lambda (x) (= x n)) lon)))
My approach, which was clearly wrong was:
(define (num-pairs-occurrences lon)
(list (lambda (x) (map (occurrences lon x) (remove x lon)) x))
I thought the above would work, but apparently my lambda isn't placed properly. Any ideas?
It's a bit trickier than you imagine. As you've probably noticed, we must remove duplicate elements in the output list. For this, is better that we define a remove-duplicates helper function (also using abstract list functions) - in fact, this is so common that is a built-in function in Racket, but not available in your current language settings:
(define (remove-duplicates lst)
(foldr (lambda (e acc)
(if (member e acc)
acc
(cons e acc)))
'()
lst))
Now it's easy to compose the solution using abstract list functions:
(define (num-pairs-occurrences lon)
(map (lambda (e) (list e (occurrences lon e)))
(remove-duplicates lon)))
The above might return and output list in a different order, but that's all right. And before you ask: yes, we do need that helper function. Please don't ask for a solution without it...
An easy, self-contained solution would be:
(define (num-pairs-occurences lst)
(foldl (lambda (e r)
(if (or (null? r) (not (= (caar r) e)))
(cons (list e 1) r)
(cons (list e (add1 (cadar r))) (cdr r))))
null
(sort lst >)))
Basically, you sort the list first, and then you fold over it. If the element (e) you get is the same as the first element of the result list (r), you increment the count, otherwise you add a new sublist to r.
If you sort by > (descending), you can actually use foldl which is more memory-efficient. If you sort by < (ascending), you need to use foldr which is less efficient.

Using recursion to getNth position for Racket

I have to write a recursive call in Racket that allows us to get the Nth position of a given list. for example (getNth 3 '(1 2 3 4)) should return back 4 and if the list is empty or if the position is non existent then return and empty list.
this is my code:
(define getNth
(lambda (ls)
(if (= ls null?) 1
(getNth ls(append '(car ls)(cdr ls))))))
getting this error:
getnth: arity mismatch;
the expected number of arguments does not match the given number
expected: 1
given: 2
arguments...:
4
()
if you need the recursive statement here it is:
base case-getNth N LS) = (), if LS = null
recursive call -(getNth N LS) = (getNth N (append '(car LS)(cdr LS))), if N >= 1
im getting stumped I dont know how to implement this one.
Assuming your getNth can revieve a "N" from a list (rather than a fixed N i.e. get3rd), your are indeed missing an argument:
(define getNth
(lambda (n list)
(cond ((null? list) '())
((= n 0) (car list))
(else (getNth (- n 1) (cdr list))))))
Which basically is until I get to the number I want, decrement the it and "pop" the first element out until the first element of the list is the one I want i.e. the rest of the list.
Your lambda only takes one argument the way you defined it which is exactly the error message you're having ;)
I think I appropriately balanced my parenthesis :)
A trick with recursion: it's generic concept is easy:
A recusrion is "if a terminal condition occurs, I'm done, return appropriate value. Else, increment the argument toward termination condition and call myself with these new arguments"
It gets complicated when the termination condition can have exceptions. Because if your can't trivially expressed it as "if this done else redo with increment" you could make mistakes...
There are several issues with you code..
You say you need a procedure that takes two arguments, but yours take only ls.
When ls is the empty list the result is 1
if list is not empty you recurse with two arguments, both lists. The first is the same as the original argument which would make a infinite recursion. The second is an append between '(car lst) which evaluates to the list (car lst) and (cdr ls) (the the list ls except the first pair)
(define get-nth
(lambda (index lst)
(if (= index 0) ; when index is zero
(car lst) ; return the first element
(get-nth (- index 1) ; else recurse with the decrement of index
(cdr lst))))) ; and all but the first element (the rest) of lst
;; test
(get-nth 0 '(a)) ; ==> a
(get-nth 1 '(a b)) ; ==> b
;; However, this won't work:
(get-nth 0 '()) ; will fail
(get-nth 10 '(a b c)) ; will fail
I kind of like the fact that it doesn't work when given wrong arguments. list-ref and car fails just as much if gived wrong parameters, but that is easy to fix:
(define get-nth
(lambda (index lst)
(cond ((not (pair? lst)) '()) ; it should always be a pair
((= index 0) (car lst)) ; when index is zero, return the first element
(else (get-nth (- index 1) ; else recurse with the decrement of index
(cdr lst)))))) ; and all but the first element (the rest) of lst
Instead of just th empty list you can have a default value or perhaps throw an error with (raise 'get-nth-error) (R6RS+)

Procedures on lists (scheme)

I am writing a procedure which returns a list with all of the negative odd and positive
even integers removed (strings can stay), by using lambda in the primitive filter procedure. I also am avoiding using recursion, but that is what's stumping me.
What I have so far is:
(define (f2b lst)
(cond ((null? lst)'()) ; if the list is empty, return the empty list
((pair? (car lst)) ; if the current element isn't a list
(filter (lambda (x) (or (even? x) (positive? x))) (car lst))
(filter (lambda (x) (or (odd? x) (negative? x))) (car lst)))
(else (string? (car lst)) ;otherwise, if the current element is a string,
(car lst) ; then return that element
(f2b (cdr lst)))))
I'm also not sure how I can apply both of the filter procedures at the same time.
It's way simpler than that. All you have to do is filter the list. You just need the appropriate predicate.
When do you want to keep an element? You phrased it in terms of what you want to remove, so let's start with that. You want to remove if it's a negative odd or a positive even integer, and leave everything else in. It's easier to break it down into smaller functions.
(define (positive-even? x) (and (positive? x) (even? x)))
(define (negative-odd? x) (and (negative? x) (odd? x)))
(define (remove-num? x) (or (positive-even? x) (negative-odd? x)))
This defines whether to keep a number. But the list element might not be a number. So we
keep it if it's not a number, or if it doesn't match remove-num?:
(define (keep-element? x) (or (not (number? x)) (not (remove-num? x))
Then your function just has to call filter:
(define (f2b lst) (filter keep-element? lst))
Seems to work:
(f2b '(-4 -3 -2 -1 0 1 2 3 4 "a string" "another"))
=> (-4 -2 0 1 3 "a string" "another")
Here's how it would look as one big honkin' function:
(define (f2b lst)
(filter
(lambda (x)
(or (not (number? x))
(not (or (and (positive? x) (even? x))
(and (negative? x) (odd? x))))))
lst)
Personally, the nested or not or and gets a bit hard to read for my taste...
Ok, apparently you have nested lists. All you have to do here is map the result of the filter with a function which:
when given a list, returns (f2b lst)
otherwise, returns the element unchanged.
I will leave it as an exercise for you since, if you thought my function could possibly work on a nested list, clearly you have a lot of learning to do...

Scheme storing the result of a function (Let)

(define [DML vara]
(cond
((atom? (car vara))
(cond
((eqan? (car vara) 'N)
(display (cdr vara)))
(else (negate vara)))
)))
I'm currently trying to save the content of a return right now for simplicity I was testing the negate function it "returns" a list and I wanted to save the result of that function to do testing. How do I actually save the list return from negate.
Kind of like (x = (negate vara)) where x is the list. I look up let on google and in stack over flow but I can't find a very simple basic assignment.
Excuse my poor syntax on scheme I'm just starting..and going from imperative language to function isn't so smooth..
edit:
I wanted to print out the result expression of (negate vara) but since scheme only prints out the last "recursive call" (pardon my bad wording). I wanted it to use the resulting list from (negate vara) but still print out that list like
say if I had
(else (test (negate vara)))
...
(define (test vara)
(display "test")
)
I wanted it to display
'(O a b)) ;list
here
As you already know, a let expression will do the trick:
(let ((x 10)
(y 20))
(+ x y))
=> 30
The above expression binds values to two variables, x and y. These bindings will exist inside the body of the let. Implicitly, all the expressions in the let form are packed inside a begin, and the end result of the whole expression is the final expression. Notice that one binding cannot refer to the others in the definition part; if one variable needs to refer to previous definitions, then use a let*:
(let* ((x 10)
(y (* x 2)))
(+ x y))
=> 30
Finally, if you need to create a recursive definition use letrec:
(letrec ((fact (lambda (x)
(if (zero? x) 1 (* x (fact (sub1 x)))))))
(fact 10))
=> 3628800
You could make a procedure like you proposed:
(define (test var)
(display var)
var)
(test (negate (test vara)))) ; prints our argument and return
Or you could use DrRacket and use the debugger. You'll miss it after using it once!

Scheme: Combining lists at a certain point

I am trying to define a procedure that takes an argument of 2 lists and a non-negative integer. Assume perfect input. I want it to construct a list of the elements in the first list UNTIL it reaches the given integer of elements at which point I want to finish it with the remainder of elements from the second list. Let me demonstrate.
~(combine '(a b c d e) '(w x y z) 2)
(a b y z)
Notice that the second list continued from the next index as if it were being made to cdr the whole time.
This is what I have. It doesn't work, of course and I think I may be using the wrong logic.
(define (combine seq1 seq2 point)
(if (null? (or seq1 seq2))
'()
(if (equal? point 0)
(cons seq2 '())
(cons (car seq1) (combine (cdr seq1) (cdr seq2) (- point 1) )))))
All help would be appreciated!
Thank you!
Well, this line doesn't do what you want:
(if (null? (or seq1 seq2))
In Scheme, the empty list is a true value; the only false value in Scheme is #f. That means that
(or '() '(a))
returns '() but
(or '(a) '())
returns '(a)
So your check for null will return #t only half of the time. (And if '() were a false value, as it is in regular Lisp, then it would never work, so I'm not sure what you are thinking).
If you want that line to return true if either of the lists is null, you will have to rethink it.
Then there's the line
(cons seq2 '())
Try testing that function on its own and see what happens - it's not what you need. If you think about it, that line should be rather simpler. What do you actually need to return at that point?