Racket two lists lambda - list

I tried to do my first steps with "lambda" in Dr Racket. (Advanced language)
Everything was fine until I tried out the following piece of code:
(map (lambda (list1 list2)
[map list (foldr + 0 (map * list1 list2 ) ) ] )
(list 1 2 3 4 5)
(list 6 7 8 9 10)
)
I tried to adapt my code according to the Racket dokumentation as good as possible.
But I just don't get what's wrong here.
http://docs.racket-lang.org/reference/pairs.html#(def._((lib._racket/private/map..rkt)._map))
It should output a single list consisting of the droduct of the 2 input list elements with the same index.
Console output says:
map: 2nd argument must be a list, given 1
whereas 1 is always the first element of list1
Subconsciousness says I just messed with ( ) anywhere.

You seem to be misunderstanding what the arguments to the lambda mean in a map. The arguments to the lambda are not the lists, they are elements of the lists.
In a normal one-argument map it's not:
(map (lambda (list1)
....)
(list 1 2 3 4 5))
But actually:
(map (lambda (elem1) ; elem1 is an element of the list
....)
(list 1 2 3 4 5))
It's the same with two-argument map. The arguments to the lambda are elements of their respective lists:
(map (lambda (elem1 elem2) ; elem1 is an element of the first list, elem2 is an element of the second list
....)
(list 1 2 3 4 5)
(list 6 7 8 9 10))
In your example, the two lists are [Listof Number], so the arguments to the lambda are Number.
(map (lambda (elem1 elem2) ; elem1 : Number, elem2 : Number
; here you have two numbers, so you can multiply them,
; but `map`-ing over the numbers doesn't make sense
(* elem1 elem2))
(list 1 2 3 4 5) ; [Listof Number]
(list 6 7 8 9 10)) ; [Listof Number]

Related

Scheme / Racket : transposing lists with map and lambda

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".

Count specific numbers in list

How do I use count for counting specific numbers in list?
(define lst '(1 1 1 1 2 2 2 3 3 3 3 3 4 4)
(count 2 lst);; what should I use at the place of '2'
But it is resulting the following error.
count: contract violation
expected: procedure?
given: 2
count counts the number of elements of the list for which the procedure returns true. In this case you want a procedure that only returns true if the element is 2: (lambda (x) (equal? x 2)).
In full, you can do
(define lst '(1 1 1 1 2 2 2 3 3 3 3 3 4 4))
(count (lambda (x) (equal? x 2)) lst)
Side note: you can shorten it by replacing the lambda expression with (curry equal? 2).

opposite of list-ref? (Racket)

Is there anything which acts as the opposite of list-ref, where instead of selecting certain values to add to a list, it'll take values away from a list?
I basically want to do the following
(list 1 2 3 4 5 6 7) (list 3 6 7) -> (list 1 2 4 5)
Where the values in list two get deleted from list one. (preferred)
Since I will always start with a list that goes from 1 to n,
the second list could also represent the location/position where a number on list 1 should be deleted. (less preferred)
I'm trying to create a code which will manipulate other functions to come up with these lists, so please be clear where each list is 'mentioned' in the code, as I sometimes get confused if people use x y and z and so forth with multiple lambda, local definitions, etc.
I have something here which does the opposite of what I want and I've been trying to alter it so instead of outputting the elements of x that are on y, it gives the elements of x which are NOT on y.
(define (selection x y)
(filter (lambda (e2)
(ormap (lambda (e1) (equal? e1 e2))
y))
x))
example:
(list 1 2 3 4 5 6 7 8 9 10)
(list 2 4 6 8 10))
-> (list 2 4 6 8 10))
Anybody have any ideas on how to change the output to what I need?
It sounds like you're using lists as sets. You could instead use Racket sets, and use the set-subtract function:
#lang racket
(set-subtract (set 1 2 3 4 5 6 7)
(set 3 6 7))
;; => (set 1 2 4 5)
remove will do the trick I guess.
> (remove* (list 1 2) (list 1 2 3 2 4 5 2))
'(3 4 5)
You can read the doc here.
Here's a simple recursive function that achieves what you want:
(define remove-list-from-list (lambda (list remlist)
(cond
[(null? list) '()]
[(member (car list) remlist) (remove-list-from-list (cdr list) remlist)]
[else (cons (car list) (remove-list-from-list (cdr list) remlist))])))
Now you can use it like so:
> (remove-list-from-list (list 1 2 3 4 5 6 7) (list 3 6 7))
'(1 2 4 5)

Using map and other high order functions

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)

Scheme remove a list

I found the contents of this thread quite useful!
How to delete an element from a list in scheme
I tested the code recommended, and it seems that it removes a single item at its first and only occurrence in the list.
Say instead I wanted to all occurrences of the item from the list. Or even further, if I wanted to specify a list of items instead of an item to remove.
For example if I had a function called removelist that took two lists as parameters
(define (removelist L M))
> (removelist '(1 2 2 3 4 5 2 2 5 6 7 8 9) '(1 2))
> '(3 4 5 5 6 7 8 9)
Hope this makes sense.
Here a simple function that uses filter and member to accomplish this:
(define (remove-list l m)
(filter (lambda (element)
(not (member element m)))
l))
Here the results:
> (remove-list '(1 2 2 3 4 5 2 2 5 6 7 8 9) '(1 2))
(3 4 5 5 6 7 8 9)
> (remove-list '(1 2 2 3 4 5 2 2 5 6 7 8 9) '(1 2 1))
(3 4 5 5 6 7 8 9)
This snippet requires srfi-1. Hope this helps.
Regards,
Matt
Using simple recursion and no built-in functions like filter or member:
(define (filter_out m l)
(cond ( (null? l) '() )
( (equal? (car l) m) (filter_out m (cdr l)) )
( else (cons (car l) (filter_out m (cdr l))) )
))
Test:
(filter_out 'jay (list 'jay 'z 'jay 'dilla 'jay 'electro))
(filter_out '(jay z) (list '(jay z) '(jay dilla) 'jay '(electro)))
If you're interested in learning this type of coding, check out "The Little Schemer." It takes only a few hours to read and you'll be a master at recursion after reading it.