LISP Programming Exam Review Q - lisp

Using the built-in map and zip functions, define a Scheme function zipadd that takes two lists of numbers and returns the a list consisting of the corresponding elements added together. You may assume that the lists are the same length. For example (zipadd '(1 2 3) '(4 5 6)) is (5 7 9). (A correct solution not using zip and map will be worth 8 points.)
I am not sure how to do this. I would really like to know the solution before my exam tomorrow. Can anyone help me please?

For starters, Racket doesn't come with a zip procedure, although it's trivial to implement one:
(define (zip lst1 lst2)
(map list lst1 lst2))
Now regarding your question - a solution using only map is the simplest way to solve this problem and it's very similar to the above procedure, just think what could be used to fill the blank:
(define (zipadd lst1 lst2)
(map <???> lst1 lst2))
Although it's a bit more contrived, you can use zip to reach the same solution (and get full marks). Try to figure out how it works - zip sticks together all pairs of elements in both lists, creating a list of two-element lists. Afterwards, map will traverse that list and apply a procedure to each element (remember: each element is a list of two elements), creating a new list with the results:
(define (zipadd lst1 lst2)
(map (lambda (x) <???>) ; x is a list with two numbers, how to add them?
(zip lst1 lst2)))
Finally and for completeness' sake, a solution without using map or zip. It's an implementation of map for the special case where the numbers on both lists must be added pair-wise:
(define (zipadd lst1 lst2)
(if <???> ; if either list is empty (*)
<???> ; then return the empty list
(cons (+ <???> <???>) ; else add the first elements of both lists
(zipadd <???> <???>)))) ; and advance the recursion over both lists
(*) Remember: both lists are assumed to have the same length.
Try to write all the variations of the solution, it'll be interesting to compare different approaches to solve the same problem. And if you have to use map and zip to get full marks then by all means use the second version above, just be aware that's not the simplest nor the most efficient way to express the solution to the problem at hand.

Related

Abstracting Lists in Dr. Racket

Currently, I have a function item counts that is meant to count the number of elements in a string and order them into pairs if it occurs once or more.
(check-expect
(item-counts
(cons "hello"
(cons "hey"
(cons "hello" '())))
equal?)
(cons "hello" 2
(cons "hey" 1) '()))
(check-expect
(item-counts
(cons #true
(cons #false
(cons #true '())))
equal?)
(cons #true 2
(cons #false 1 '())))
(define (item-counts lop ef)
(cond
[(empty? (rest lop))
(first lop)]
[(cons? (rest lop))
(if
(ef (first lop) (item-counts (rest lop) ef))) ... ???
As shown by the tests, I wish to add a number to the existing list if one of the elements of this list occurs more than once. I used the equal? function to identify the number of times an element occurs, but I am lost on how to add the number to the existing list as well as condense the repeating elements when producing a new list. I have tried using the append function but it creates a list in a different format ( (list (list) ).
I don't know if this is self-learning, for a class, etc. I know there are standard HtDP ways to do this, recipes, etc. But I don't know these things, sorry. What I will say is that Racket is quite easy to prototype things. You can just describe your problem and don't think too much about the details. I usually like to start in the middle.
For example:
At some point in the middle of execution you will have strings yet to examine and an association list of the strings examined so far. Then your task is 1) if there are no more strings to get, we're done, otherwise 2) get the next string, add it to the table, and continue because we're not done.
(define (build-assoc from-string current-assoc)
(if (done? from-string)
current-assoc
(let ((first-string (get-first-string from-string)))
(let ((result-table (add-string first-string current-assoc))
(result-string (drop-first-string from-string)))
(build-assoc result-string
result-table)))))
Maybe you don't use this procedure in the end. But it's a picture of what you're doing, and it suggests what sort of helper procedures you will need to finish your quest. Give yourself a fighting chance and just use DrRacket to outline your problem. When you see it, then maybe it gives you some ideas how to answer the questions. DrRacket helpfully points out all your unanswered questions like "done?: unbound identifier in: done?" Ah yes, how do we know we're done, good question DrRacket. Well you see, I was given this list of strings, so...

Make a sublist from list using LiSP

I have difficulty creating a sublist: '(((3)2)1)' from the list '(3 2 1)'.
I don't know where to start, any help would be greatly appreciated.
Take a careful look at the input. You'll see that every list in the result is two elements long - except the first. Since we need to handle the first cons in one way, and all of the others another, we'll split the work between two functions, the second of which will be a loop:
(defun nest-left (list)
(if (null list)
nil
(nest-aux <?> (cdr list))))
(defun nest-aux (acc list)
(if (null list)
<?>
<?>))
I'll leave you to fill in the <?>s.

How do I do anything with multiple return values in racket?

It seems like in order to use multiple return values in Racket, I have to either use define-values or collect them into a list with (call-with-values (thunk (values-expr)) list). In the latter case, why would someone to choose to return multiple values instead of a list, if just have to collect them into a list anyway? Additionally, both of these are very wordy and awkward to work into most code. I feel like I must be misunderstanding something very basic about multiple-return-values. For that matter, how do I write a procedure accepting multiple return values?
Although I may be missing some of the Scheme history and other nuances, I'll give you my practical answer.
First, one rule of thumb is if you need to return more than 2 or 3 values, don't use multiple values and don't use a list. Use a struct. That will usually be easier to read and maintain.
Racket's match forms make it much easier to destructure a list return value -- as easy as define-values:
(define (f)
(list 1 2))
(match-define (list a b) (f))
(do-something-with a b)
;; or
(match (f)
[(list a b) (do-something-with a b)])
If you have some other function, g, that takes a (list/c a b), and you want to compose it with f, it's simpler if f returns a list. It's also simpler if both use a two-element struct. Whereas call-with-values is kind of an awkward hot mess, I think.
Allowing multiple return value is an elegant idea, because it makes return values symmetric with arguments. Using multiple values is also faster than lists or structs (in the current implementation of Racket, although it could work otherwise).
However when readability is a higher priority than performance, then in modern Racket it can be more practical to use a list or a struct, IMHO. Having said that I do use multiple values for one-off private helper functions.
Finally, there's a long, interesting discussion on the Racket mailing list.
Racket doc gives us the quintessential example why, in disguise:
> (let-values ([(q r) (quotient/remainder 10 3)])
(if (zero? r)
q
"3 does *not* divide 10 evenly"))
"3 does *not* divide 10 evenly"
We get two values directly, and use them separately in a computation that follows.
update: In Common Lisp, with its decidedly practical, down-to-the-metal, non-functional approach (where they concern themselves with each extra cons cell allocation), it makes much more sense, especially as it allows one to call such procedures in a "normal" way as well, automatically ignoring the "extra" results, kind of like
(let ([q (quotient/remainder 10 3)])
(list q))
But in Racket this is invalid code. So yeah, it looks like an extraneous feature, better to be avoided altogether.
Using list as the consumer defeats the purpose of multiple values so in that case you could just have used lists to begin with. Multiple values is actually a way of optimization.
Semanticly returning a list and several values are similar, but where you return many values in a list effort goes into creation of cons cells to make the list and destructuring accessors to get the values at the other end. In many cases however, you wouldn't notice the difference in performance.
With multiple values the values are on the stack and (call-with-values (lambda () ... (values x y z)) (lambda (x y z) ...) only checks the number to see if it's correct.. If it's ok you just apply the next procedure since the stack has it's arguments all set from the previous call.
You can make syntactic sugar around this and some popular ones are let-values and SRFI-8 receive is a slightly simpler one. Both uses call-with-values as primitive.
values is handy because it
checks that the number of elements returned is correct
destructures
For example, using
(define (out a b) (printf "a=~a b=~a\n" a b))
then
(let ((lst (list 1 2 3)))
(let ((a (first lst)) (b (second lst))) ; destructure
(out a b)))
will work even though lst has 3 elements, but
(let-values (((a b) (values 1 2 3)))
(out a b))
will not.
If you want the same control and destructuring with a list, you can however use match:
(let ((lst (list 1 2)))
(match lst ((list a b) (out a b))))
Note that he creation of the structure, e.g. (list 1 2) vs (values 1 2) is equivalent.

Counting numbers in a list

Is there anyone who can help me to write a function in common LISP that counts the numbers in a list?
The code that I have written is below, but it does not work!
(defun count-numbers(lst)
(let(result()))
(dolist(number lst)
(push number result))
(length result))
For example, when I enter this query "(count'(r 4 f d w 2 3 4 1 z))", I must get 5.
Since it's homework, I'll just give some pointers. First: simplicity. If you are new to Common-Lisp, just use its basic features. For example: recursion. In pure functional style. Think about something like this:
(defun count (list counter)
;; something
)
we first check list. If it's empty, we already checked all the elements, so we return counter. If list is not empty, we
take its first element
we check if it's a number
it's a number! We recursively call count on the rest of the list and with counter = counter + 1
it's not a number! We recursively call count on the rest of the list with counter the same as before
Use (numberp n). It returns T if n is a number, NIL if not.
(defun count-numbers (lst)
(let (result ()))
(dolist (number lst)
(push number result))
(length result))
Check the indentation. Is that what you wanted? Maybe not.
Then you also push all elements to the result list? Is that what you want?
Here is a list of functions on numbers. http://www.lispworks.com/documentation/HyperSpec/Body/c_number.htm
Maybe there is one you need?
This is a good introductory Lisp book for download: http://www.cs.cmu.edu/~dst/LispBook/
I'd say there are a variety of ways to solve this, one would be an imperative loop, like the mostly correct solution already written, a recursive counting function (which is probably the worst way since there's no guarantee in CL that you won't blow the stack), or the functional approach you would probably actually use in production. The last one would be this:
(defun count-numbers (list) (count-if #'numberp list))

CLISP - Reversing a simple list

I have to reverse the elements of a simple (single-dimension) list. I know there's a built-in reverse function but I can't use it for this.
Here's my attempt:
(defun LISTREVERSE (LISTR)
(cond
((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
(t (cons (LISTREVERSE (cdr LISTR)) (car LISTR))) ; move first to the end
)
)
Output pretty close, but is wrong.
[88]> (LISTREVERSE '(0 1 2 3))
((((3) . 2) . 1) . 0)
So I tried to use append instead of cons:
(t (append (LISTREVERSE (cdr LISTR)) (car LISTR)))
But got this error:
*** - APPEND: A proper list must not end with 2
Any help?
I can give you a couple of pointers, because this looks like homework:
The base case of the recursion is when the list is empty (null), and not when there are less than two elements in the list
Consider defining a helper function with an extra parameter, an "accumulator" initialized in the empty list. For each element in the original list, cons it at the head of the accumulator. When the input list is empty, return the accumulator
As an aside note, the above solution is tail-recursive.
As a follow-up to Óscar López (and fighting the temptation to just write a different solution down):
Using both append and length makes the posted solution just about the least efficient way of reversing a list. Check out the documentation on cons and null for some better ideas on how to implement this.
Please, please indent properly.
Tail recursion really is both more efficient and reasonably simple in this case. Try it if you haven't already. labels is the form you want to use to define local recursive functions.
It may be worth your while to flip through The Little Schemer. It'll give you a better feel for recursion in general.
It's ok what you did. You only missed the composition of the result list.
Think about it: You have to append the 1-element list of the CAR to the end of the list of the reversed CDR:
(defun LISTREVERSE (LISTR)
(cons
((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
(t (append (LISTREVERSE (cdr LISTR)) (list (car LISTR))))))
(defun listreverse (list)
(let (result)
(dolist (item list result)
(push item result))))
Don't use recursion in Common Lisp when there is a simple iterative way to reach the same goal. Common Lisp does not make any guarantees about tail recursion, and your tail recursive function invocation may not be optimized to a jump at the discretion of the compiler.
push prepends the item to the result
dolist has an optional third argument which is the value returned. It is evaluated when the loop is exited.