New to scheme but trying to learn the basics.
Let's say I passed a list in as a parameter and I wanted to multiply each element by -1. Right now I have this:
(define (negative b)
(* (car b) -1 )))
Which returns the first element as -1 * that element
So in this case giving it (negative '(5 1 2 3)) returns -5.
But lets say I want it to return
-5 -1 -2 -3
How would I go about making the rest of the list negative? Using cdr recursively?
Do it recursively.
(define (negative l)
(if (null? l)
'()
(cons (* (car l) -1)
(negative (cdr l)))))
If the list is empty, this just returns an empty list, as the base case.
Otherwise, it calculates -1 * the first element, the negative of the rest of the list, and combines them to produce the result.
The purpose of your exercise may be for you to code up your own map procedure, in which case that's fine. But if not, use scheme's built in 'map' procedure which is intended for just this kind of purpose.
'map' has been available at least since R4RS (that is, a long time ago) and possibly earlier.
by using map. If you want it returned as list.
It would be like this
(define negative
(lambda (b)
(map - b)))
Map is going through list b, and apply procedure "-" to each number in list
If you want to return as single numbers not in list you apply values on the list.
(define negative1
(lambda (b)
(apply values (map - b))))
Edit: I saw that you are asking for recursive solution, which would go like this
(define negative1
(lambda (b)
(if (null? b)
'()
(cons (- (car b)) (negative1 (cdr b))))))
Related
"Implement unique, which takes in a list s and returns a new list containing the same elements as s with duplicates removed."
scm> (unique '(1 2 1 3 2 3 1))
(1 2 3)
scm> (unique '(a b c a a b b c))
(a b c)
What I've tried so far is:
(define (unique s)
(cond
((null? s) nil)
(else (cons (car s)(filter ?)
This question required to use the built-in filter function. The general format of filter function is (filter predicate lst), and I was stuck on the predicate part. I am thinking it should be a lambda function. Also, what should I do to solve this question recursively?
(filter predicate list) returns a new list obtained by eliminating all the elements of the list that does not satisfy the predicate. So if you get the first element of the list, to eliminate its duplicates, if they exists, you could simply eliminate from the rest of the list all the elements equal to it, something like:
(filter
(lambda (x) (not (eqv? x (first lst)))) ; what to maintain: all the elements different from (first lst)
(rest lst)) ; the list from which to eleminate it
for instance:
(filter (lambda (x) (not (eqv? x 1))) '(2 1 3 2 1 4))
produces (2 3 2 1 4), eliminating all the occurrences of 1.
Then if you cons the first element with the list resulting from the filter, you are sure that there is only a “copy” of that element in the resulting list.
The last step needed to write your function is to repeat recursively this process. In general, when you have to apply a recursive process, you have to find a terminal case, in which the result of the function can be immediately given (as the empty list for lists), and the general case, in which you express the solution assuming that you have already available the function for a “smaller” input (for instance a list with a lesser number of elements).
Consider this definition:
define (unique s)
(if (null? s)
'()
(cons (first s)
(filter
(lambda (x) (not (eq? x (first s))))
(unique (rest s))))))
(rest s) is a list which has shorter than s. So you can apply unique to it and find a list without duplicates. If, from this list, you remove the duplicates of the first element with filter, and then cons this element at the beginning of the result, you have a list without any duplicate.
And this is a possibile solution to your problem.
I'm doing the exercises from SICP (not homework) and exercise 2.20 introduces dotted-tail notation, which is where you use (define (f a . b) ...) to pass a variable number of arguments (which end up in a list b). This problem in particular wants a procedure which takes an integer a and returns a list of all arguments with parity equal to a's. The problem is not difficult; here is my solution:
(define (same-parity a . b); a is an int, b is any number of int arguments
(let ((parity (remainder a 2)))
(define (proc li)
(cond ((null? li) null)
; If parity of the head of the list is = parity of a,
((= (remainder (car li) 2) parity)
; keep it and check the rest of the list.
(cons (car li) (proc (cdr li))))
; Otherwise ignore it and check the rest of the list.
(else (proc (cdr li)))))
(cons a (proc b))))
My question is that I don't seem to be using the dotted-tail feature at all. I might as well have just accepted exactly two arguments, a number and a list; I'm effectively wrapping the algorithm in a procedure proc which does away with the dotted-tail thing.
Before I wrote this solution, I wanted to have a recursive call resembling
(same-parity a . (cdr b))
or something spiritually similar, but no matter how I tried it, I kept passing lists of lists or extra procedures or whatever. This could be because I don't know exactly what . does, only what I want it to do (the Racket docs didn't clear anything up either). To sum up,
Is my solution what was intended for this exercise, or is there a way to actually use the dot notation (which seems to be the point of the exercise) in the algorithm?
You can't use (same-parity a . (cdr b)) (since that would be read in as (same-parity a cdr b)), but you can use (apply same-parity a (cdr b)). That's how you "splat" a list into arguments.
However, the "inner procedure" approach you had is generally more efficient, as there is less list copying going on.
How can I write a function using abstract list functions (foldr, map, and filter) without recursion that consumes a list of numbers (list a1 a2 a3 ...) and produces a new list removing the minimum number from the original list?
The recursion code is:
(define (find-min lst)
(cond
[(empty? (rest lst)) (first lst)]
[else
(local [(define min-rest (find-min (rest lst)))]
(cond
[(< (first lst) min-rest) (first lst)]
[else min-rest]))]))
A fold applies a 2-argument function against a given value and the car of a list uses the result against the successive cars or the cdrs or the list. this is what we want.
Whereas map returns a new list by doing something with each element of a list.
And filter returns a smaller or equal list based on some predicate.
Now just to formulate a function that can choose the lessor of two arguments
(define (the-lessor x y)
(if (< x y)
x
y))
From there implementation is straightforward.
(define (min L) (fold the-lessor (car L) (cdr L)))
Since this looks like a homework question, I'm not going to provide all the code, but hopefully push you in the right direction.
From the HTDP book, we see that "The Intermediate Student language adds local bindings and higher-order functions." The trick here is probably going to using "local bindings".
Some assumptions:
(remove-min-from-list '()) => not allowed: input list must be non-empty
(remove-min-from-list '(1)) => '()
(remove-min-from-list '(1 2 3 1 2 3)) => '(2 3 2 3) ; all instances of 1 were removed
Somehow, we need to find the minimum value of the list. Call this function min-of-list. What are its inputs and outputs? It's input is a list of numbers and its output is a number. Of the abstract list functions, which ones allow us to turn a list of numbers into a number? (And not another list.) This looks like foldl/foldr to me.
(define (min-of-list lst)
(foldr some-function some-base lst))
Since you already showed that you could write min-of-list recursively, let's move on. See #WorBlux's answer for hints there.
How would we use this in our next function remove-min-from-list? What are the inputs and outputs of remove-min-from-list? It takes a list of numbers and returns a list of numbers. Okay, that looks like map or filter. However, the input list is potentially shorter than that output list, so filter and not map.
(define (remove-min-from-list lst)
....
(filter some-predicate list))
What does some-predicate look like? It needs to return #f for the minimum value of the list.
Let's pull this all together and use local to write one function:
(define (remove-min-from-list lst)
(local [(define min-value ...)
(define (should-stay-in-list? number) ...min-value ...)]
(filter should-stay-in-list? lst)))
The key here, is that the definition for should-stay-in-list? can refer to min-value because min-value came before it in the local definitions block and that the filter later on can use should-stay-in-list? because it is in the body of the local.
(define (comparator n) (local [(define (compare v) (not (equal? v n)))] compare))
(define (without-min list) (filter (comparator (foldr min (foldr max 0 list) list)) list))
Ok, so I'm trying to write a function that finds the distance between two elements in a list, s and t.
For example, if s = bob and t = pizza:
(d 'bob 'pizza '(bob blah blah pizza))
it would return: 3
This is what I have so far.
(define dist
(lambda (s t line)
(cond
[(equal? s (car line))
[(equal? t (car (cdr line)))
1]]
[else (add1 (dist s t (cdr line)))])))
For some reason, it's not working. Help?
Thanks!
The proposed code in the question is not going to work, it's just checking if the two elements are contiguous in the list. Let's try a different approach altogether - split the problem in smaller subproblems, begin by defining a procedure that returns the index of an element in a list, counting indexes from zero:
(define (index-of elt lst)
<???>) ; ToDo
With the above procedure in place, and assuming that both s and t are present in the list and t appears after s, it's easy to find the solution to the question:
(define dist
(lambda (s t line)
(- (index-of t line)
(index-of s line))))
For example:
(dist 'bob 'pizza '(bob blah blah pizza))
=> 3
For extra credit, consider the cases where one or both of the elements are not present in the list (so index-of should return a value indicating this, say, #f), or when s appears after t in the list.
When you are taking (cdr line) in the last step you are throwing away bob even if bob is the first element.
You need to take care of 3 and maybe 4 cases.
Where s and t match the first two elements you do fine.
Where s matches and t doesn't you need to add 1 to a recursive call using line with the 2nd element removed. Something like (cons (car line) (cdr (cdr line))).
Where s doesn't match you need to remove the car of line and try again.
Unless you are sure s and t will both occur and in order you need a terminating condition(s) to take care of running out of line.
Here is a solution that iterates down the list looking for 's' and 't' each time. When both have been seen, the result is returned; otherwise, continue looking:
(define (dist s t line)
(let looking ((l line) (n 0) (i #f))
(and (not (null? l))
(let ((item (car l)))
(if (or (equal? item s)
(equal? item t))
(if (not i)
(looking (cdr l) (+ n 1) n) ; found first, continue
(- n i)) ; found second, done
(looking (cdr l) (+ n 1) i)))))); continue looking
Hi I am trying to write a program where given a list of lists check to see if they are equal in size and return #t if they are.
So for example if i were to write (list-counter? '((1 2 3) (4 5 6) (7 8 9))) the program would return #t, and (list-counter? '((1 2 3) (4 5 6) (7 8))) would return #f.
SO far this is what I have done:
(define list-counter?
(lambda (x)
(if (list? x)
(if (list?(car x))
(let (l (length (car x))))
(if (equal? l (length(car x))))
(list-counter?(cdr x))
) ) ) ) )
I think where I am going wrong is after I set the length of l to the length of the first list. Any help would be appreciated.
There are several ways to solve this problem. For instance, by hand and going step-by-step:
(define (all-lengths lists)
(if (null? lists)
'()
(cons (length (car lists))
(all-lengths (cdr lists)))))
(define (all-equal? head lengths)
(if (null? lengths)
true
(and (= head (car lengths))
(all-equal? head (cdr lengths)))))
(define (list-counter? lists)
(let ((lengths (all-lengths lists)))
(all-equal? (car lengths) (cdr lengths))))
Let me explain the above procedures. I'm dividing the problem in two steps, first create a new list with the lengths of each sublist - that's what all-lengths does. Then, compare the first element in a list with the rest of the elements, and see if they're all equal - that's what all-equal? does. Finally, list-counter? wraps it all together, calling both of the previous procedures with the right parameters.
Or even simpler (and shorter), by using list procedures (higher-order procedures):
(define (list-counter? lists)
(apply = (map length lists)))
For understanding the second solution, observe that all-lengths and all-equal? represent special cases of more general procedures. When we need to create a new list with the result of applying a procedure to each of the elements of another list, we use map. And when we need to apply a procedure (= in this case) to all of the elements of a list at the same time, we use apply. And that's exactly what the second version of list-counter? is doing.
You could write an all-equal? function like so:
(define (all-equal? list)
;; (all-equal? '()) -> #t
;; (all-equal? '(35)) -> #t
;; (all-equal? '(2 3 2)) -> #f
(if (or (null? list) (null? (cdr list)))
#t
(reduce equal? list)
))
then do:
(all-equal? (map length listOfLists))
Alternatively you can do:
(define (lists-same-size? list-of-lists)
(if (== (length listOfLists) 0)
#t
(let*
(( firstLength
(length (car listOfLists)) )
( length-equal-to-first?
(lambda (x) (== (length x) firstLength)) )
)
(reduce and #t (map length-equal-to-first? listOfLists))
)
)))
What this says is: if the list length is 0, our statement is vacuously true, otherwise we capture the first element of the list's length (in the 'else' part of the if-clause), put it in the closure defined by let's syntactic sugar (actually a lambda), and use that to define an length-equal-to-first? function.
Unfortunately reduce is not lazy. What we'd really like is to avoid calculating lengths of lists if we find that just one is not equal. Thus to be more efficient we could do:
...
(let*
...
( all-match? ;; lazy
(lambda (pred list)
(if (null? list)
#t
(and (pred (first list)) (all-match? (cdr list)))
;;^^^^^^^^^^^^^^^^^^^ stops recursion if this is false
)) )
)
(all-match? length-equal-to-first? listOfLists)
)
)))
Note that all-match? is already effectively defined for you with MIT scheme's (list-search-positive list pred) or (for-all? list pred), or in Racket as andmap.
Why does it take so long to write?
You are forced to write a base-case because your reduction has no canonical element since it relies on the first element, and list manipulation in most languages is not very powerful. You'd even have the same issue in other languages like Python. In case this helps:
second method:
if len(listOfLists)==0:
return True
else:
firstLength = len(listOfLists[0])
return all(len(x)==firstLength for x in listOfLists)
However the first method is much simpler to write in any language, because it skirts this issue by ignoring the base-cases.
first method:
if len(listOfLists)<2:
return True
else:
return reduce(lambda a,b: a==b, listOfLists)
This might sound a bit weird, but I think it is easy.
Run down the list, building a new list containing the length of each (contained) list, i.e. map length.
Run down the constructed list of lengths, comparing the head to the rest, return #t if they are all the same as the head. Return false as soon as it fails to match the head.