I have this code:
(define tree `(A (B (C)) (D (E)) (C (E))))
(define (prog1 graph)
(let ([seen `()])
(define (sub g)
(cond
[(member (car g) seen) `()]
[else
(set! seen (cons (car g) seen))
(cond
[(null? (cdr g)) (list (car g))]
[else
(cons (car g) (map sub (cdr g)))])]))
(delete `() (sub graph))))
(define delete
(lambda (x y)
(if (null? y )
`()
(if (eqv? (car y) x)
(delete x (cdr y))
(cons (car y) (delete x (cdr y)))))))
It prints a connected graph where all the nodes appear once.
Running (prog1 tree)
prints: (A (B (C)) (D (E)))
I have looked at various depth-first searches in lisp (something which is similar to what I'm trying to do) and they appear to be much more elegant to this, some using iterative approaches. I am aware that the program isn't very efficient (on huge trees it runs pretty slow) so how would I go about improving the efficiency of this code?
Thanks, James
The member procedure performs an O(n) lookup on lists every time it's invoked. That's not what we want for quickly testing set membership, for that you should use a data structure providing an O(1) complexity for both adding elements and testing element membership in a collection, ideally a Set data structure or in its place a Hash Table. For example, in Racket try replacing these lines (or use the default hash table implementation in your Scheme interpreter):
(let ([seen `()]) => (let ([seen (make-hash)])
[(member (car g) seen) `()] => [(hash-has-key? seen (car g)) '()]
(set! seen (cons (car g) seen)) => (hash-set! seen (car g) 'ok)
Also, in general you want to use quotes in your code: '() instead of quasiquotes: `(), see the links to understand the difference and when it's appropriate to use quasiquoting.
Finally, you can use the built-in remove procedure, there's no need to implement your own delete.
In most cases the bottleneck in this code will not be the tree traversal, but the member lookup. The complexity of your function seems to be roughly O(M*N), where M is the number of distinct nodes and N is the number of total nodes. The reason why M goes into this as a factor is because you're looking up nodes in a linear list, which takes time proportional to the length of the list (which in your case is proportional to the number of distinct nodes).
The way to get rid of the M is to use a more efficient data structure for the lookup. R6RS defines hash tables, for instance.
I have decided to learn some functional language and I hooked up with the lisp-scheme after all.
I am trying to make a function which checks if a list is sorted, either with lowest first getting higher or vice versa, and if it can be sorted it should return true else false.
This is my first code, working only if the list is increasing (or equal).
(define sorted?
(lambda (lst)
(cond ((empty? lst) #t)
(else (and (<= (car lst) (cadr lst))
(sorted? (cdr lst)))))))
clarification: something like (sorted? '(1 2 3 4 5)) and (sorted? '(5 4 3 2 1)) should return true, else if not sorted false of course.
How am I supposed to think when programming in a functional style? The syntax seems straight-forward but I'm not used to the logic.
Specific implementation
I'd take Óscar López's answer and go one step further:
(define sorted? (lambda (lst)
(letrec ((sorted-cmp
(lambda (lst cmp)
(cond ((or (empty? lst) (empty? (cdr lst)))
#t)
(else (and (cmp (car lst) (cadr lst))
(sorted-cmp (cdr lst) cmp)))))))
(or (sorted-cmp lst <=) (sorted-cmp lst >=)))))
The biggest difference between this version and his is that sorted? now defines Óscar's version as an internal helper function using letrec and calls it both ways.
Functional Thinking
You actually chose a good example for illustrating some aspects of how Scheme views the world, and your implementation was off to a very good start.
One important functional principle involved in the solution to this problem is that anything you could put (**here** more stuff '(1 2 3 4)), you can pass around as an argument to another function. That is, functions are first class in a functional programming language. So the fact that you were using <= in your comparison means that you can pass <= as a parameter to another function that makes a comparison accordingly. Óscar's answer is a great illustration of that point.
Another aspect of this problem that embodies another common functional pattern is a function that consists primarily of a (cond) block. In many functional programming languages (Haskell, ML, OCaml, F#, Mathematica), you get stronger pattern matching abilities than you get, by default in Scheme. So with (cond) in Scheme, you have to describe how to test for the pattern that you seek, but that's usually fairly straightforward (for example the (or (empty? lst) (empty? (cdr lst))) in this implementation.
One final functional programming pattern that I see as well-embodied in this problem is that many functional programming solutions are recursive. Recursion is why I had to use letrec instead of plain ol' let.
Almost anything you can do by operating on the first element (or 2 elements as in this case) and then repeating the operation on the tail (cdr) of the list you do that way. Imperative for- or while-style loops aren't impossible in Scheme (although they are pretty much impossible in pure functional languages such as Haskell), they're slightly out of place in Scheme under many circumstances. But Scheme's flexibility that allows you, as the developer, to make that decision enables important performance or maintainability optimizations in certain circumstances.
Continuing exploration
My first implementation of sorted? for my answer here was going to decide which comparison operator to pass to sorted-cmp based on what it saw in the list. I backed off on that when I spotted that a list could start with two equal numbers '(1 1 2 3 4 5). But as I think more about it, there's definitely a way to track whether you've decided a direction yet and, thus, only have one call required to sorted-cmp. You might consider exploring that next.
You almost got it right, look:
(define sorted?
(lambda (lst)
(cond ((or (empty? lst) (empty? (cdr lst)))
#t)
(else (and (<= (car lst) (cadr lst))
(sorted? (cdr lst)))))))
A little modification in the base case, and you're all set. It's necessary to stop when there's only one element left in the list, otherwise the cadr expression will throw an error.
For the second part of your question: If you want to check if it's sorted using a different criterion, simply pass the comparison function as an argument, like this:
(define sorted?
(lambda (lst cmp)
(cond ((or (empty? lst) (empty? (cdr lst)))
#t)
(else (and (cmp (car lst) (cadr lst))
(sorted? (cdr lst) cmp))))))
(sorted? '(1 2 3 4 5) <=)
> #t
(sorted? '(5 4 3 2 1) >=)
> #t
Now if you want to know if a list is sorted in either ascending order or in descending order:
(define lst '(1 2 3 4 5))
(or (sorted? lst >=) (sorted? lst <=))
> #t
As you can see, functional programming is about defining procedures as generic as possible and combining them to solve problems. The fact that you can pass functions around as parameters helps a great deal for implementing generic functions.
I'm going to take your question to mean, more specifically, "if I already program in an imperative language like C or Java, how do I adjust my thinking for functional programming?" Using your problem as an example, I'm going to spend my Saturday morning answering this question in long form. I'll trace the evolution of a functional programmer through three stages, each a successively higher plane of zen - 1) thinking iteratively; 2) thinking recursively; and 3) thinking lazily.
Part I - Thinking Iteratively
Let's say I'm programming in C and I can't or won't use recursion - perhaps the compiler does not optimize tail recursion, and a recursive solution would overflow the stack. So I start thinking about what state I need to maintain. I imagine a little machine crawling over the input. It remembers if it is searching for an increasing or a decreasing sequence. If it hasn't decided yet, it does so based on the current input, if it can. If it finds input headed in the wrong direction, it terminates with zigzag=true. If it reaches the end of the input, it terminates with zigzag=false.
int
zigzag(int *data, int n)
{
enum {unknown, increasing, decreasing} direction = unknown;
int i;
for (i = 1; i < n; ++i)
{
if (data[i] > data[i - 1]) {
if (direction == decreasing) return 1;
direction = increasing;
}
if (data[i] < data[i - 1]) {
if (direction == increasing) return 1;
direction = decreasing;
}
}
/* We've made it through the gauntlet, no zigzagging */
return 0;
}
This program is typical of C programs: it is efficient but it is difficult to prove that it will do the right thing. Even for this simple example, it's not immediately obvious that this can't get stuck in an infinite loop, or take a wrong turn in its logic somewhere. Of course, it gets worse for more complicated programs.
Part II - Thinking Recursively
I find that the key to writing readable programs in the spirit of functional languages (as opposed to just trying to morph an imperative solution into that language) is to focus on what the program should calculate rather than on how it should do it. If you can do that with enough precision - if you can write the problem out clearly - then most of the time in functional programming, you're almost at the solution!
So let's start by writing out the thing to be calculated in more detail. We want to know if a list zigzags (i.e. decreases at some point, and increases at another). Which lists meet this criterion? Well, a list zigzags if:
it is more than two elements long AND
it initially increases, but then decreases at some point OR
it initially decreases, but then increases at some point OR
its tail zigzags.
It's possible to translate the above statements, more or less directly, into a Scheme function:
(define (zigzag xs)
(and (> (length xs) 2)
(or (and (initially-increasing xs) (decreases xs))
(and (initially-decreasing xs) (increases xs))
(zigzag (cdr xs)))))
Now we need definitions of initially-increasing, initially-decreasing, decreases, and increases. The initially- functions are straightforward enough:
(define (initially-increasing xs)
(> (cadr xs) (car xs)))
(define (initially-decreasing xs)
(< (cadr xs) (car xs)))
What about decreases and increases? Well, a sequence decreases if it is of length greater than one, and the first element is greater than the second, or its tail decreases:
(define (decreases xs)
(letrec ((passes
(lambda (prev rest)
(cond ((null? rest) #f)
((< (car rest) prev)
#t)
(else (passes (car rest) (cdr rest)))))))
(passes (car xs) (cdr xs))))
We could write a similar increases function, but it's clear that only one change is needed: < must become >. Duplicating so much code should make you uneasy. Couldn't I ask the language to make me a function like decreases, but using > in that place instead? In functional languages, you can do exactly that, because functions can return other functions! So we can write a function that implements: "given a comparison operator, return a function that returns true if that comparison is true for any two successive elements of its argument."
(define (ever op)
(lambda (xs)
(letrec ((passes
(lambda (prev rest)
(cond ((null? rest) #f)
((op (car rest) prev)
#t)
(else (passes (car rest) (cdr rest)))))))
(passes (car xs) (cdr xs)))))
increases and decreases can now both be defined very simply:
(define decreases (ever <))
(define increases (ever >))
No more functions to implement - we're done. The advantage of this version over the C version is clear - it's much easier to reason that this program will do the right thing. Most of this program is quite trivial with all the complexity being pushed into the ever function, which is a quite general operation that would be useful in plenty of other contexts. I am sure by searching one could find a standard (and thus more trustworthy) implementation rather than this custom one.
Though an improvement, this program still isn't perfect. There's lots of custom recursion and it's not obvious at first that all of it is tail recursive (though it is). Also, the program retains faint echos of C in the form of multiple conditional branches and exit points. We can get an even clearer implementation with the help of lazy evaluation, and for that we're going to switch languages.
Part III - Thinking Lazily
Let's go back to the problem definition. It can actually be stated much more simply than it was in part II - "A sequence zigzags (i.e. is non-sorted) if it contains comparisons between adjacent elements that go in both directions". I can translate that sentence, more or less directly, into a line of Haskell:
zigzag xs = LT `elem` comparisons && GT `elem` comparisons
Now I need a way to derive comparisons, the list of comparisons of every member of xs with its successor. This is not hard to do and is perhaps best explained by example.
> xs
[1,1,1,2,3,4,5,3,9,9]
> zip xs (tail xs)
[(1,1),(1,1),(1,2),(2,3),(3,4),(4,5),(5,3),(3,9),(9,9)]
> map (\(x,y) -> compare x y) $ zip xs (tail xs)
[EQ,EQ,LT,LT,LT,LT,GT,LT,EQ]
That's all we need; these two lines are the complete implementation -
zigzag xs = LT `elem` comparisons && GT `elem` comparisons
where comparisons = map (\(x,y) -> compare x y) $ zip xs (tail xs)
and I'll note that this program makes just one pass through the list to test for both the increasing and decreasing cases.
By now, you have probably thought of an objection: isn't this approach wasteful? Isn't this going to search through the entire input list, when it only has to go as far as the first change of direction? Actually, no, it won't, because of lazy evaluation. In the example above, it calculated the entire comparisons list because it had to in order to print it out. But if it's going to pass the result to zigzag, it will only evaluate the comparisons list far enough to find one instance of GT and one of LT, and no further. To convince yourself of this, consider these cases:
> zigzag $ 2:[1..]
True
> zigzag 1:[9,8..]
True
The input in both cases is an infinite list ([2,1,2,3,4,5..] and [1,9,8,7,6,5...]). Try to print them out, and they will fill up the screen. But pass them to zigzag, and it will return very quickly, as soon as it finds the first change in direction.
A lot of the difficultly in reading code comes from following multiple branches of control flow. And a lot of those branches are really efforts to avoid calculating more than we need to. But much of the same thing can be achieved with lazy evaluation, allowing the program to be both shorter and truer to the original question.
Try this
(define sorted?
(lambda (l)
(cond ((null? l) #t)
(else (check-asc? (car l) (sorted? (cdr l))
(check-desc? (car l) (sorted? (cdr l))))))
(define check-asc?
(lambda (elt lst)
(cond ((null? lst) #t)
(else (or (< elt (car lst)) (= elt (car lst))) (check-asc? (car lst) (cdr lst))))))
(define check-desc?
(lambda (elt lst)
(cond ((null? lst) #t)
(else (or (< elt (car lst)) (= elt (car lst))) (check-desc? (car lst) (cdr lst))))))
I am a newbie myself. I haven't tested this code. Still struggling with recursion. Please tell me if it worked or what error it gave.
The previous answer i gave was really bad.
I ran the code in DrScheme and it gave errors.
However I have modified it. Here is a code that works:
(define sorted?
(lambda (l)
(cond ((null? l) #t)
(else (if (check-asc? (car l) (cdr l)) #t
(check-desc? (car l) (cdr l)))))))
(define check-asc?
(lambda (elt lst)
(cond ((null? lst) #t)
(else (if (or (< elt (car lst)) (= elt (car lst))) (check-asc? (car lst) (cdr lst))
#f)))))
(define check-desc?
(lambda (elt lst)
(cond ((null? lst) #t)
(else (if (or (> elt (car lst)) (= elt (car lst))) (check-desc? (car lst) (cdr lst))
#f)))))
Cases checked:
(sorted? '(5 4 3 2 1))
returns #t
(sorted? '(1 2 3 4 5))
returns #t
(sorted? '(1 2 3 5 4))
returns #f
(sorted? '())
returns #t
(sorted? '(1))
returns #t
In Exercise 30.1.1 of HtDP, I started off using local and then modified it to use lambda in order to answer the question.
(define (add-to-each2 accu a-list)
(cond
[(empty? a-list) empty]
[else (local ((define s (+ accu (first a-list))))
(cons s (add-to-each2 s (rest a-list))))]))
and
(define (add-to-each5 accu a-list)
(cond
[(empty? a-list) empty]
[else (cons ((lambda (x y)
(first (map + (list (first y))
(list x)))) accu a-list)
(add-to-each5 (+ accu (first a-list))(rest a-list)))]))
In this particular instance, to me, the local version is easier to read. Are there situations where the lambda version would be preferred? Thank you.
First off, I think you might be getting relative-2-absolute confused with add-to-each, since add-to-each just adds the same number to each element of the list, rather than incrementing an accumulator. The rest of this post assumes that's the case, and just takes out that incrementing.
I think let would be my first choice for the local binding. Your lambda example uses a common pattern that simulates let using lambda and application:
(let ([x e]) body)
Is equivalent to:
((lambda (x) body) e)
If you use this transformation from lambda to let in your example, you get:
(define (add-to-each5 n a-list)
(cond
[(empty? a-list) empty]
[else (cons (let ([x n] [y a-list])
(first (map + (list (first y))
(list x))))
(add-to-each5 n (rest a-list)))]))
A good compiler will likely generate the same code for this as for your two examples, so it mostly comes down to style. The "left-left lambda" pattern can be more difficult to read, as you note, so I prefer let.
However, Exercise 30.1.1 is trying to make you use map as a replacement for the explicit recursion that occurs in each of your examples. You are using map in your example but only for a single addition at a time, which makes map kind of painful: why bother wrapping up (list (first y)) and (list x) when you just want (+ (first y) x)?
Let's look at a simple definition of map to see how it might be helpful, rather than painful, for this problem:
(define (map f ls)
(cond
[(empty? ls) empty]
[else (cons (f (first ls)) (map f (rest ls)))]))
Right away, you should notice some similarities to add-to-each: the first line of the cond checks for empty, and the second line conses something to do with the first element onto a recursive call to map on the rest. The key, then, is to pass map an f that does what you want to do to each element.
In the case of add-to-each, you want to add a particular number to each element. Here's an example of adding 2:
> (map (lambda (n) (+ 2 n)) (list 1 2 3 4 5))
(3 4 5 6 7)
Notice that map and lambda are both here as 30.1.1 requests, and they act on an entire list without the explicit recursion of the original add-to-each: the recursion is all abstracted away in map.
This should be enough to get you to a solution; I don't want to give away the final answer, though :)
I'm working through Exercise 21.2.3 of HtDP on my own and was wondering if this is idiomatic usage of the various functions. This is what I have so far:
(define-struct ir (name price))
(define list-of-toys (list
(make-ir 'doll 10)
(make-ir 'robot 15)
(make-ir 'ty 21)
(make-ir 'cube 9)))
;; helper function
(define (price< p toy)
(cond
[(< (ir-price toy) p) toy]
[else empty]))
(define (eliminate-exp ua lot)
(cond
[(empty? lot) empty]
[else
(filter ir? (map price< (build-list (length lot)
(local ((define (f x) ua)) f)) lot))]))
To my novice eyes, that seems pretty ugly because I have to define a local function to get build-list to work, since map requires two lists of equal length. Can this be improved for readability? Thank you.
You could implement eliminate-exp with filter alone:
(define (eliminate-exp ua lot)
(define (price< toy) (< (ir-price toy) ua))
(filter price< lot))
I dont know what build-list is or does, but surely you can just do:
(lambda (x) ua)
instead of:
(local ((define (f x) ua)) f)
How to write a program in scheme that takes an arbitrary
sexpression consisting of integers and which returns an sexpression that is identical to
the original but with all the integers doubled?
We want a procedure that takes an S-expression as input, and outputs an S-expression with the same structure, but where each integer is doubled; generally, a procedure to map S-expressions:
(define (double x)
(if (number? x)
(* x 2)
x)))
(define (sexp-map op sexp)
...)
(sexp-map double some-sexpression)
The S-expression we get (SEXP) is going to be either an atom, in which case the result is (OP SEXP), or a list of S-expressions. We might think to map OP across SEXP in this case, but S-expressions nest arbitrarily deep. What we should actually do is map a procedure that will transform each element in the smaller S-expression with OP. Well would you look at that, that's just another way to describe of the goal of the procedure we're currently trying to write. So we can map SEXP-MAP across SEXP.
Well, no we can't actually, because SEXP-MAP needs to be called with two arguments, and MAP will only give it the one. To get around that, we use a helper procedure F of one argument:
(define (sexp-map op sexp)
(define (f x)
(if (list? x)
(map f x)
(op x)))
(f sexp))
F winds up doing all the real work. SEXP-MAP is reduced to being a facade that's easier to use for the programmer.
It sounds like what you want is to find each integer in the s-expression, then double it, while keeping the rest of it the same.
If you're not aware, s-expressions are just lists that may happen to contain other lists, and it makes sense to deal with them in levels. For instance, here's a way to print all the values on level one of an s-expression:
(define (print-level-one sexp)
(display (car sexp))
(print-level-one (cdr sexp)))
This will end up calling display on the car of every part of the s-expression.
You could do something similar. You'll need the functions integer? and pair? to check whether something is an integer, which should be doubled, or another list, which should be treated just like the top-level list.
(Note: I'm being deliberately vague because of the comment about homework above. If you just want the answer, rather than help figuring out the answer, say so and I'll change this.)
An Sexp of numbers is one of
-- Number
-- ListOfSexp
A ListOfSexp is one of
-- empty
-- (cons Sexp ListOfSexp)
So, you'll need one function to handle both of those data definitions. Since the data definitions cross-reference each other, the functions will do the same. Each individual function is pretty straight forward.
(define (double E)
(cond ((null? E) '())
((list? (car E)) (cons (double (car E)) (double (cdr E))))
((number? E) (list E))
(else (cons (* 2 (car E)) (double (cdr E))))
))
(map (lambda (x) (* x 2)) '(1 2 3 4 5)) => '(2 4 6 8 10)
What does it do? (lambda (x) (* x 2)) takes a number and doubles it, and map applies that function to every element of a list.
Edit: Oh, but it won't go into trees.
(define double
(lambda (x)
(cond ((null? x) (list))
((list? (car x)) (cons (double (car x)) (double (cdr x))))
(else (cons (* 2 (car x)) (double (cdr x)))))))
EDIT
Fixed this. Thanks to Nathan Sanders for pointing out my initial oversight concerning nested lists.