I am still learning about high order functions and going to be quizzed on it soon. I am trying to write a program that takes 2 lists of the same length and subtracts the first from second, item by item, until you get 0 in the first position.
(check-expect (min (list 1 1 1) (list 2 4 6)) (list 2 4))
(check-expect (min (list 1 1) (list 2 3)) (list 1))
I can easily do this without map, but Is there any way I can use map here?
(map - 1 (list ...))
or when I pass it on to the first of a list, or rest.
wont work. I know it takes in a function and passes on to each element of a list. I am confused.
This is not a good example to start learning about map. The map higher-order procedure takes a list as input, and returns another list of the same length as output, where a function was applied to each of the elements in the input. See why this is not such a clear-cut case for using map? the output lists are smaller than the inputs!
Of course, it can be done, but it's not that elegant, and obscures the true purpose of map:
(define (min lst1 lst2)
(if (zero? (first lst2)) ; if the first position in lst2 is zero
(rest lst2) ; then return the rest of it.
(min lst1 ; otherwise advance recursion
(map - lst2 lst1)))) ; ok, here `map` was useful
To understand what's happening in the last line, imagine that the input lists are one on top of the other:
'(2 4 6)
'(1 1 1)
Then, map applies the - function element-wise:
(- 2 1)
(- 4 1)
(- 6 1)
And the result of each operation is collected in a new list:
'(1 3 5)
This is a special case of map: when there's more than one list after the function, it applies the function to the first element of each list before advancing to the next - hence the function must accept as many arguments as there are lists. The usual case with map is that you simply apply the function to each of the elements in a single list, and but the way this is a good place to use lambda:
(map (lambda (x) (* x x))
'(1 2 3 4 5))
=> '(1 4 9 16 25)
Related
I'm currently trying to code a procedure which gets a list of lists and returns a list of lists, which contains each first item of the input lists. For example I'll provide you with a Input and Output.
Input:
(list (list 1 5) (list 2 6) (list 3 7) (list 4 8)))
Output:
(list (list 1 2 3 4) (list 5 6 7 8))
My idea was to build a somewhat map procedure using lambda for function. I'm currently struggling on mapping any function on combined list elements, since map only processes a single item on the list (to my understanding).
Could anyone provide me with helpful insights?
Thank you so much in advance.
This can be done in Scheme / Racket with
(apply map list (list (list 1 5) (list 2 6) (list 3 7) (list 4 8)))
which in DrRacket returns
'((1 2 3 4) (5 6 7 8))
Basically, calling (apply map list [a b c ... n]) (in pseudocode), is the same as calling
(map list a b c ... n)
The argument list is "opened up", so to speak.
cf. Matrix multiplication in scheme, List of lists
(lambda x x) could be used instead of list, too:
(apply map (lambda x x) (list ....... ))
This is because map can be used with several lists as its inputs, not just one. In such a case the number of arguments to the lambda function must match the number of input lists.
A special case is (lambda x ...) where x is not enclosed in parentheses. This means such a lambda function can be applied to any number of arguments, which will all be collected and passed in as a list. So (lambda x x) will act just the same as the built-in list does, and can be seen as its implementation.
And by the way, this isn't "merging", it is "transposition".
What's the difference between using cons to combine an element to a list and using cons to combine a list to an element in scheme?
Furthermore, how exactly does cons work? Does it add element to the end of the list or the beginning?
Thanks!
The primitive cons simply sticks together two things, the fact that some of those things are considered lists is incidental. For instance, this works and creates a pair (also known as a cons cell):
(cons 1 2)
=> '(1 . 2) ; a pair
Now, if the second argument to cons happens to be a list, then the result will be a new list, and the first argument to cons will be added at the head of the old list. In other words: to create a list you need a list, even if it's empty:
(cons 1 '(2 3))
=> '(1 2 3) ; a list
(cons 1 (cons 2 '()))
=> '(1 2) ; a list
(cons 1 '())
=> '(1) ; a list
But if the second argument to cons is not a list, then the result will be just a pair, or an improper list, meaning that it doesn't end in '() as it should to be considered a list:
(cons '(1 2) 3)
=> '((1 2) . 3) ; a pair, not a list
(cons 1 (cons 2 3))
=> '(1 2 . 3) ; an improper list
Just to clarify, you can't use cons to add elements at the end of a list. The usual way to build a list is going from right-to-left, adding elements in reverse at the head position - say you want to build the list '(1 2 3), then you have to cons the elements in the order 3 2 1:
(cons 3 '()) ; list is '(3)
(cons 2 (cons 3 '())) ; list is '(2 3)
(cons 1 (cons 2 (cons 3 '()))) ; list is '(1 2 3)
For those rare occasions where you need to add one element at the end (and believe me, doing so generally means that you're thinking the algorithm wrong) you can use append, which receives two lists as arguments:
(append '(1 2 3) '(4))
=> '(1 2 3 4)
I want to write a function which outputs a list.
The function gets a list and outputs a new one. For example:
(0 0 1 2 2 1) -> (3 4 4 5 5 6)).
What it does is: the index+1 in the initial list is a value in the new list. And the that value is placed x times in the new list dependent on the value in the initial list.
(1 2) -> (1 2 2)
(0 3 0 3) -> (2 2 2 4 4 4)
So 3 is on the second position, the value is three so 2(2nd position) is placed 3 times in the new list.
I came up with this, which does not work
(defun change-list (list)
(setq newlist '(1 2 3))
(setq i 0)
(while (<= i (length list))
(if (= (nth i list) 0)
(concatenate 'list '0 'newlist)
(concatenate 'list '(i) 'newlist))
(+ i 1)
(remove 0 newlist)))
The problem is mainly the fact that it does not recognize new variables. It gave me these errors:
functions.lisp:27:26:
warning: Undefined function referenced: while
functions.lisp:31:2:
warning: Free reference to undeclared variable newlist assumed special.
warning: Free reference to undeclared variable i assumed special.
Is there someone who understands this?
We were able to solve it ourselves:
(defun change-list (a)
(loop for j from 1 to (length a) by 1 append
(loop for i from 1 to (nth (- j 1) a) by 1
collect j )))
It is part of a larger assignment, and we did not get much education on lisp, more like: do it in lisp.
Let's assume this is Common Lisp, I'll then list some problems in your code:
(defun change-list (list)
(setq newlist '(1 2 3))
SETQ does not declare variables, it just sets them.
(setq i 0)
(while (<= i (length list))
WHILE does not exist in Common Lisp.
(if (= (nth i list) 0)
(concatenate 'list '0 'newlist)
0 is not a list. Thus you can't concatenate it.
CONCATENATE does not have a side effect. What ever you do here is lost.
NEWLIST here is a symbol, not a list. Does not work.
(concatenate 'list '(i) 'newlist))
i is not a variable here. Putting it into a list will have no.
CONCATENATE does not have a side effect. What ever you do here is lost.
NEWLIST here is a symbol, not a list. Does not work.
(+ i 1)
The effect of the above is lost.
(remove 0 newlist)
The effect of the above is lost.
))
You can simplify your answer to this:
(defun change-list (list)
(loop for i in list and j from 1
append (loop repeat i collect j)))
Basically, just another way to do the same thing:
(defun change-list (x)
(let ((index 0))
(mapcon
#'(lambda (y)
(incf index)
(let ((z (car y)))
(unless (zerop z)
(make-list z :initial-element index)))) x)))
But may be useful for the purpose of learning / who knows what your professor expects.
How would you define a function which takes one argument, which should be a list, and returns the elements in the
list which are themselves lists?
(check-expect (find-sublists ’(1 2 () (3) (a b c) a b c))
’(() (3) (a b c)))
Do you have experience designing functions that can filter through a list?
A simpler problem with the same flavor as the original is something like this: design a function that takes a list of numbers and keeps only the even numbers. Would you be able to do that function?
Looking at http://www.ccs.neu.edu/home/matthias/HtDP2e/htdp2e-part2.html and going through its guided exercises may also help.
Two useful tools which should start you on your way:
1) Traversing through a list:
; traverse: takes a list of numbers
; Goes through each element, one-by-one, and alters it
(define traverse
(lambda (the_list)
(if (empty? the_list)
empty
(cons (+ 1 (first the_list))
(traverse (rest the_list))))))
(traverse (cons 3 (cons 4 empty))) returns (cons 4 (cons 5 empty))
2) list?:
(list? (list 1 2 3)) returns #t
(list? 5) returns #f
I'm trying to write a function in scheme that takes a list and squares every item on the list, then returns the list in the form (list x y z). However, I'm not sure how to write a code that will do that. So far, I have
(define (square=list list)
(cond
[(empty? list) false]
[else (list (sqr (first a-list))(square-list (rest a-list)))]))
but it returns the list in the form
(cons x (cons y (cons z empty)))
What can I do to make it return the list just in the form (list x y z)? Thanks!
You're almost there -- make sure you understand the difference between cons and list (the textbook How to Design Programs explains this in Section 13. You can find the online copy here).
cons will take an item as its first element and (usually) a (possibly empty) list for the 'rest' part. As an example, (cons 1 empty) has the number 1 as its first element and the empty list as the 'rest'. (cons 1 (cons 2 empty)) has the number 1 as the first element, and (cons 2 empty) as the 'rest'.
list is just an easy shorthand for making lists, taking an arbitrary number of items. Thus:
(list 1 2 3 4 5)
is the same as...
'(1 2 3 4 5)
which is the same as
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 empty))))).
But be careful. (list 1 (list 2 (list 3))) is not the same as (cons 1 (cons 2 (cons 3 empty))). In fact, it is (cons 1 (cons 2 (cons 3 empty) empty) empty).
If you're still confused, feel free to post a comment.
The problem is that you're using list in the else statement. You are saying build me a list with this value as the first entry, and a list as the second entry.
You want to cons the first entry onto the list created by recursive call.
(list 'a '(b c d))
; gives you
'(a (b c d))
(cons 'a '(b c d))
; gives you
'(a b c d)
This is probably not what your TA is looking for, but I'll throw it in anyway because it may help you grok a tiny bit more of Scheme. The idiomatic (in Scheme) way to write what you are trying to do is to use map:
> (map (lambda (x) (* x x)) '(1 2 3 66 102 10403))
(1 4 9 4356 10404 108222409)
map applies a function (here, (lambda (x) (* x x)) - a nameless function that returns the square of its input) to each element of a list and returns a new list containing all of the results. Scheme's map basically does the same iteration you are doing in your code, the advantage being that by using map you never have to explicitly write such iterations (and, nominally at least, a Scheme implementation might optimize map in some special way, though that's not really that important in most cases). The important thing about map is that it reduces your code to the important parts - this code squares each element of the list, this other code takes the square root of each element, this code adds one to it, etc, without having to repeat the same basic loop iteration code again and again.