Subset / Subsequence Recursive Procedure in Simply Scheme Lisp - list

I am working my way through Simply Scheme in combination with the Summer 2011 CS3 Course from Berkley. I am struggling with my understanding of the subset / subsequence procedures. I understand the basic mechanics once I'm presented with the solution code, but am struggling to grasp the concepts enough to come up with the solution on my own.
Could anyone point me in the direction of something that might help me understand it a little bit better? Or maybe explain it differently themselves?
This is the basis of what I understand so far:
So, in the following procedure, the subsequences recursive call that is an argument to prepend, is breaking down the word to its basest element, and prepend is adding the first of the word to each of those elements.
; using words and sentences
(define (subsequences wd)
(if (empty? wd)
(se "")
(se (subsequences (bf wd))
(prepend (first wd)
(subsequences (bf wd))))))
(define (prepend l wd)
(every (lambda (w) (word l w))
wd))
; using lists
(define (subsequences ls)
(if (null? ls)
(list '())
(let ((next (subsequences (cdr ls))))
(append (map (lambda (x) (cons (car ls) x))
next)
next))))
So the first one, when (subsequences 'word) is entered, would return:
("" d r rd o od or ord w wd wr wrd wo wod wor word)
The second one, when (subsequences '(1 2 3)) is entered, would return:
((1 2 3) (1 2) (1 3) (1) (2 3) (2) (3) ())
So, as I said, this code works. I understand each of the parts of the code individually and, for the most part, how they work with each other. The nested recursive call is what is giving me the trouble. I just don't completely understand it well enough to write such code on my own. Anything that might be able to help me understand it would be greatly appreciated. I think I just need a new perspective to wrap my head around it.
Thanks in advance for anyone willing to point me in the right direction.
EDIT:
So the first comment asked me to try and explain a little more about what I understand so far. Here it goes:
For the words / sentence procedure, I think that it's breaking the variable down to it's "basest" case (so to speak) via the recursive call that appears second.
Then it's essentially building on the basest case, by prepending.
I don't really understand why the recursive call that appears first needs to be there then.
In the lists one, when I was writing it on my own I got this:
(define (subseq lst)
(if (null? lst)
'()
(append (subseq (cdr lst))
(prepend (car lst)
(subseq (cdr lst))))))
(define (prepend i lst)
(map (lambda (itm) (cons i itm))
lst))
With the correct solution it looks to me like the car of the list would just drop off and not be accounted for, but obviously that's not the case. I'm not grasping how the two recursive calls are working together.

Your alternate solution is mostly good, but you've made the same mistake many people make when implementing this (power-set of a list) function for the first time: your base case is wrong.
How many ways are there to choose a subset of 0 or more items from a 0-element list? "0" may feel obvious, but in fact there is one way: choose none of the items. So instead of returning the empty list (meaning "there are no ways it can be done"), you should return (list '()) (meaning, "a list of one way to do it, which is to choose no elements"). Equivalently you could return '(()), which is the same as (list '()) - I don't know good Scheme style, so I'll leave that to you.
Once you've made that change, your solution works, demonstrating that you do in fact understand the recursion after all!
As to explaining the solution that was provided to you, I don't quite see what you think would happen to the car of the list. It's actually very nearly the exact same algorithm as the one you wrote yourself: to see how close it is, inline your definition of prepend (that is, substitute its body into your subsequences function). Then expand the let binding from the provided solution, substituting its body in the two places it appears. Finally, if you want, you can swap the order of the arguments to append - or not; it doesn't matter much. At this point, it's the same function you wrote.

Recursion is a tool which is there to help us, to make programming easier.
A recursive approach doesn't try to solve the whole problem at once. It says, what if we already had the solution code? Then we could apply it to any similar smaller part of the original problem, and get the solution for it back. Then all we'd have to do is re-combine the leftover "shell" which contained that smaller self-similar part, with the result for that smaller part; and that way we'd get our full solution for the full problem!
So if we can identify that recursive structure in our data; if we can take it apart like a Russian "matryoshka" doll which contains its own smaller copy inside its shell (which too contains the smaller copies of self inside itself, all the way down) and can put it back; then all we need to do to transform the whole "doll" is to transform the nested "matryoshka" doll contained in it (with all the nested dolls inside -- we don't care how many levels deep!) by applying to it that recursive procedure which we are seeking to create, and simply put back the result:
solution( shell <+> core ) == shell {+} solution( core )
;; -------------- ----
The two +s on the two sides of the equation are different, because the transformed doll might not be a doll at all! (also, the <+> on the left is deconstructing a given datum, while {+} on the right constructs the overall result.)
This is the recursion scheme used in your functions.
Some problems are better fit for other recursion schemes, e.g. various sorts, Voronoi diagrams, etc. are better done with divide-and-conquer:
solution( part1 <+> part2 ) == solution( part1 ) {+} solution( part2 )
;; --------------- ----- -----
As for the two -- or one -- recursive calls, since this is mathematically a function, the result of calling it with the same argument is always the same. There's no semantic difference, only an operational one.
Sometimes we prefer to calculate a result and keep it in memory for further reuse; sometimes we prefer to recalculate it every time it's needed. It does not matter as far as the end result is concerned -- the same result will be calculated, the only difference being the consumed memory and / or the time it will take to produce that result.

Related

Iterative filtering odd numbers in list

Here is a task I have to solve: Write an iterative function, that receives a list with numbers and creates a new list, which only consists of the even numbers from the received list.
I even found a few posts with similar questions and solutions, but I couldn't use them as help, because in these solution they were using the "car" and "cdr" commands, which we haven't had in our schedule yet. How can do this? I would start like this:
(define filter-odds
(lambda(x)
(if (odd? x)
...)
Terrible oversight: no one has mentioned How To Design Programs, here. This kind of program is right smack in the middle of HtDP's path. Specifically, this is a totally straightforward application of the List template from section 9.3, "Programming with Lists." Perhaps your class is already using HtDP?
Well, in the absence of car ⁄ cdr accessors, your only other choice is using reduce from SRFI1:
(define filter-odds
(lambda (lst)
(reduce-right
(lambda (e ; list's element
acc) ; accumulated results from the right
(if (odd? e)
.... ; combine e and the results-so-far
.... )) ; ignore e
'()
lst )))
But, right reduce most likely won't be iterative. Left reduce usually is. It will build the result in reverse order though, but you can reverse a list iteratively in another pass, using the same approach, without filtering at all (i.e. using the test procedure which always succeeds).
With the first ⁄ rest accessors available though, all you need to do is to write down the implementation for reduce yourself, then fuse it into the definitions above:
(define reduce
(lambda (f acc ls)
(if (null? ls)
acc
(reduce f (f acc (first ls)) .....))))
In other words, just follow the above code skeleton and add replace the call to f with some checks for odd? or something, to get the filter-odd?-reversed; then figure out the f to use so as to define the reverse-list function.

Remove a specific item in a list?

I want to preface this by saying that yes, this is a homework problem I'm working on and I don't want the actual answer, just maybe a nudge in the right direction. Anyhoo, I'm taking a class on programming languages' structures, and one of our projects is to write a variety of small programs in lisp. This one requires the user to input a list and an atom, then remove all instances of the atom from the list. I've scoured the internet and haven't found all that many good lisp resources, so I'm turning to you all.
Anyways, our professor has given us very little by way of stuff to work off of, and by very little I mean practically nothing.
This is what I have so far, and it doesn't work.
(defun removeIt (a lis)
(if (null lis) 0
(if (= a (car lis))
(delete (car lis))
(removeIt (cdr lis)))))
And when I type
(removeIt 'u '(u e u e))
as the input, it gives me an error stating it got 1 argument when it wanted 2. What errors am I making?
First, a few cosmetic changes:
(defun remove-it (it list)
(if (null list) 0
(if (= it (car list))
(delete (car list))
(remove-it (cdr list)))))
Descriptive and natural sounding identifier names are preferred in the CL community. Don't be shy to use names like list – CL has multiple namespaces, so you don't have to worry about clashes too much. Use hyphens instead of camel case or underscores. Also, read a short style guide.
You said you didn't want the answer but helpful tips, so here we go:
Check your base case – your result will be a list, so why do you return a number?
Use the appropriate comparison function – = is for numbers only.
You are building a new result list, so no need to delete anything – just don't add to it what you don't want.
But remember to add what you want – build your result list by consing what you want to keep to the result of applying your function to the rest of the list.
If you don't want to keep an element, just go on applying your function to the rest of the list.
You defined your function to take two arguments, but you're calling it with (cdr list) only. Provide the missing argument.
I've scoured the internet and haven't found all that many good lisp
resources,
Oh, come on.
Anyhow, I recommend Touretzky.
By the way, the function you're trying to implement is built-in, but your professor probably won't accept it as a solution, and doing it yourself is a good exercise. (For extra credit, try solving it for nested lists.)
This is a good case for a recursive function. Suppose there exists already a function called my-remove which takes an atom and a list as arguments and returns the list without the given atom. So (my-remove 'Y '(X Y Z)) => '(X Z)
Now, how would you use this function when instead of the list '(X Y Z) you have another list which is (A X Y Z), i.e. with an element A in front?
You would compare A to your atom and then, depending on whether the element A matches your atom, you would add this element A or not to the result of applying remove to the rest of the list.
With this recursion the function my-remove will be called successively with shorter lists. Now you only have to think about the base case, i.e. what does the function my-remove have to return when the list is empty.
This is an answer for other people looking specifically for elisp. A builtin function exists for this purpose called delq
Example
(setq my-list '(0 40 80 40 90)) ;; test list
(delq 40 my-list) ;; (0 80 90)
If you installed emacs from source you can check out how it is implemented by doing Mx find-function delq

Building a list with loops

We just covered loops today in class and I've got a few things I need to do. Put simply, I have to build a list using loops instead of recursion. I seem to be at a stumbling block here. For this example, we need to do a simple countdown. The function takes an argument and then returns a list of all the positive integers less than or equal to the initial argument. (countdown 5) => (5 4 3 2 1)
I'm having a hard time getting loops for whatever reason. The ones we talked about was Loop, Do, Dotimes, and Dolist. I've tried this with a couple loops and always end up with a similar result.
(defun countdown (num)
(cond ((= num 0) nil)
(T (let* ((list nil))
(loop
(if (= num 0) (return list)
(setf list (cons list num)))
(setf num (- num 1)))))))
My output shows up like this:
(((((NIL . 5) . 4) . 3) . 2) .1)
update: I've solved the issue. Apparently I needed to reverse the order in the cons, so num comes before list. Does anyone care to explain this? I thought you put the list first and then what you put second would be added to the end of it. At least, that's how I've been using it so far without issue.
Reverse the arguments to cons (and why)
You wrote in an answer (that, since it asks for more information, perhaps should have been a comment):
I've solved the issue. Apparently I needed to reverse the order in the
cons, so num comes before list. Does anyone care to explain this? I
thought you put the list first and then what you put second would be
added to the end of it. At least, that's how I've been using it so far
without issue.
The function is documented in the HyperSpec clearly: Function CONS. The examples in the documentation show, e.g.,
(cons 1 (cons 2 (cons 3 (cons 4 nil)))) => (1 2 3 4)
(cons 'a (cons 'b (cons 'c '()))) => (A B C)
(cons 'a '(b c d)) => (A B C D)
and even the note
If object-2 is a list, cons can be thought of as producing a new list which is like it but has object-1 prepended.
It may help to read through 14.1.2 Conses as Lists, as well, which includes:
A list is a chain of conses in which the car of each cons is an element of the list, and the cdr of each cons is either the next link in the chain or a terminating atom.
Concerning loop
Many of the answers here are pointing out to you that the loop form includes a special iteration language. That's true, but it can also be used in the way that you're using it. That way is called a simple loop:
6.1.1.1.1 Simple Loop
A simple loop form is one that has a body containing only compound
forms. Each form is evaluated in turn from left to right. When the
last form has been evaluated, then the first form is evaluated again,
and so on, in a never-ending cycle. A simple loop form establishes an
implicit block named nil. The execution of a simple loop can be
terminated by explicitly transfering control to the implicit block
(using return or return-from) or to some exit point outside of the
block (e.g., using throw, go, or return-from).
Simple loops probably aren't as common as loops using the nicer features that loop provides, but if you just covered this in class, you might not be there yet. The other answers do provide some good examples, though.
If you speaking about common lisp loop, your countdown may look like this:
(defun countdown (from-number)
(loop :for x :from from-number :downto 1 :collect x))
CL-USER> (countdown 10)
(10 9 8 7 6 5 4 3 2 1)
Using loop, which has its own "special-purpose language" that does not really look like Lisp:
(defun countdown (n)
(loop
for i from n downto 1
collect i))
Or using do:
(defun countdown (n)
(do ((i 1 (1+ i))
(res nil (cons i res)))
((> i n) res)))
See here, especially chapters 7 and 22.

Racket - output content of a list

I have defined a list (in Racket/Scheme):
(define myList (cons 'data1 (cons 'data2 (cons 'data3 (cons 'data4 empty)))))
or
(list 'data1 'data2 'data3 'data4)
And I want to write a function that cycles through the list and outputs all values of the list.
(define (outputListData list)
(cond
[(null? list) list]
[else (getListData)]))
With what function can I cycle through the content of the list? I know one can use first & rest to get list data, but I guess that's not the right way here.
BTW: Is there a good, compact racket reference like php.net? I find the official Racket docs very confusing ...
You can use a for loop. Example:
(for ([x (list 1 2 3)])
(printf "~s -> ~s\n" x (* x x)))
There are more functional ways to do this, of course, but this way works too. You'll probably want to look at a textbook like How To Design Programs to do the recursive approach. See: http://www.ccs.neu.edu/home/matthias/HtDP2e/
dyoo's solution is nice and succinct in a Scheme like Racket that has useful iteration routines built in. Just FYI, though, your 'outputListData' is not far from being the standard recursive way to do this. You just need to change a couple of lines:
(define (outputListData list)
(cond
[(null? list) #f] ; actually doesn't really matter what we return
[else (printf "~s\n" (first list)) ; display the first item ...
(outputListData (rest list))])) ; and start over with the rest
Since this is an "imperative" kind of procedure that isn't designed to return a value, it doesn't really matter what we do with an empty list so long as we stop recurring (to avoid an infinite loop). If the list isn't empty, we output the first element and start over recursively with the rest of the list.
BTW, here's another way you could write something almost identical if you just needed a "for" loop in the middle of some other function:
(let loop ((l (list 'foo 'bar 'baz 'quux))) ; or put whatever input you need
(cond ((null? l) #f)
(else
(printf "~s\n" (first l))
(loop (rest l)))))
One way to think about this "named let" is that it defines a temporary function called loop, which works just like outputListData above. Scheme has the nice property that it won't grow the stack for "tail calls" like these, so you can always write what would be an "iterative" for or while loop in this recursive style.
I highly recommend The Little Schemer by Friedman and Felleisen for a quick intro to this style of function writing! I found it through Douglas Crockford's page here.
Edit as per comments: Use for-each
(for-each display myList)
Try this:
(void (map display myList))
Breaking it down:
(void x) causes x to be ignored instead of returned to the REPL/parent expression as a value.
(map function lst): For a list '(a1 a2 ... an) returns the list '((function a1) (function a2) ... (function an)).
So we use map to display all the items, but since we only care about the side-effect and not the return value, we call void on the returned list.
Official docs:
void
map
I think the solution that is the easiest to understand it to come up with a so called "list-eater" function. This is the way my university introduced recursion and lists in Racket. Also most books on Racket (i.e. "How To Design Programs" or "Realm Of Racket") explain it this way. This is the code:
(define my-list (list 'data1 'data2 'data3 'data4))
(define (print-list a-list-of-data)
(when (not (empty? a-list-of-data))
(print (first a-list-of-data))
(print-list (rest a-list-of-data))))
If you call the function with the example list my-list, you will get the following output:
(print-list my-list)
'data1'data2'data3'data4
The function does the following: As long as the given list is not empty, it grabs the first element of that list and passes it to the function print. Then, it tells itself to do the exact same thing with the rest of the list. (It calls itself on the rest of the list.) This second part is what they call recursion.
However, you can shorten that by using a function called map:
(define (print-list a-list-of-data)
(map print a-list-of-data))
This basically says that you want the function print to be called on each element of the given list. The output is exactly the same.
Hope it helped!

LISP very simple list question

Im learning lisp and im pretty new at this so i was wondering...
if i do this:
(defparameter *list-1* (list 1 2))
(defparameter *list-2* (list 2 3))
(defparameter *list-3* (append *list-1* *list-2*))
And then
(setf (first *list-2*) 1)
*list-3*
I will get (1 2 1 4)
I know this is because the append is going to "save resources" and create a new list for the first chunk, but will actually just point to the second chunk, coz if i do:
(setf (first *list-1*) 0)
*list-3*
I will get (1 2 1 4) instade of the more logical (0 2 1 4)
So my question is, what other cases are like this in lisp, how do you black belt lispers know how to deal with this stuff that is not intuitive or consistent?
One defensive tactic is to avoid sharing structure.
(defparameter *list-3* (append *list-1* *list-2* '()))
or
(defparameter *list-3* (append *list-1* (copy-list *list-2*)))
Now the structure of the new *list-3* is all new, and modifications to *list-3* won't affect *list-2* and vice versa.
The append function has to make a copy of its first argument, to avoid modifying existing data structures. As a result, you now have two list segments that look like (1 2 ...), but they're part of different lists.
In general, any list can be the tail of any other list, but you can't have a single list object that serves as the head of multiple lists.
You have to think of lists in terms of cons cells. When you define list 1 and list 2, it is like:
(defparameter *list-1* (cons 1 (cons 2 nil)))
(defparameter *list-2* (cons 2 (cons 3 nil)))
Then, when you append:
(defparameter *list-3* (cons 1 (cons 2 *list-2*)))
Basically, a cons cell consists of two parts; a value (the car), and a pointer (the cdr). Append is defined to not change the first list, so that is copied, but then the last cdr (normally nil) is changed to point at the second list, not a copy of the second list. If you were willing to destroy the first list, you would use nconc.
Try this:
(defparameter *list-3* (nconc *list-1* *list-2*))
Then observe the value of *list-1*, it is (1 2 2 3), just like *list-3*.
The general rule is that the non-destructive functions (append) won't destroy existing data, while the destructive functions (nconc) will. What a future destructive function does ((setf cdr)), though, is not the responsibility of the first non-destructive function.
quote:
So my question is, what other cases are like this in lisp, how do you black belt lispers know how to deal with this stuff that is not intuitive or consistent?
I think that you are a bit harsh here with a subject that is quite a bit larger than you imagine. Lists are a rather elaborate concept in Lisp, and you need to understand that this is not some simple array. The standard provides a lot of functions to manipulate lists in every way. What you want in this case is:
(concatenate 'list *list-1* *list-2*)
So, why is there also append? Well, if you can omit copying the last list, and all symbols involved still return the correct data, this can be a significant performance boost in both calculating time and memory footprint. append is especially useful in a functional programming style which doesn't use side effects.
In lieu of further explanation about cons cells, destructive vs. nondestructive functions etc., I'll point you to a nice introduction: Practical Common Lisp, Ch. 12, and for a complete reference, the Common Lisp Hyperspec, look at Chapters 14 and 17.
So my question is, what other cases are like this in lisp, how do you black belt lispers know how to deal with this stuff that is not intuitive or consistent?
By reading the fine manual? Hyperpsec explicitly states:
[...] the list structure of each of lists except the last is copied. The last argument is not copied; it becomes the cdr of the final dotted pair of the concatenation of the preceding lists, or is returned directly if there are no preceding non-empty lists.
Um, primarily we learn how it works, so that what we imagine isn't consistent makes sense.
What you need to do is find some of the old-fashioned block and pointer diagrams, which I can't easily draw, but let's figure it out.
After the first defparameter, you've got list-1, which is
(1 . 2 . nil)
in dot notation; list-2 is
(2 . 3 . nil)