Racket/ more than one function - scheme

How could I address this problem?
Given a function of arity 1 and a list, return a list of applying the function to each element of the original list. For example:
(Mmap add1 '(1 2 3 4)) ; -> '(2 3 4 5)
(Mmap car '((1 2 3) (4 5 6) (7 8 9))) ; -> '(1 4 7)
(Mmap cdr '((1 2 3) (4 5 6) (7 September 8))) ; -> '((2 3) (5 6) (8 9))
I've tried cond and other similar functions, but I really have little idea how to solve it.

(define (myfunc f alist)
(cond
[(empty? alist) empty]
[else (cons (f (first alist)) (myfunc f (rest alist)))]
))
f is your function (e.g. add1, car) and alist is your argument. All you have to do is to construct a list where you apply f to your first argument, and append the rest of the list recursively to that.
Regarding your last example. I assume that September was defined previously as (define September 8). In that case your example won't give you your desired output. The last list will contain 'September instead of 8, because you declared your list with '(), which treats names as symbols.
Furthermore, the output should be '((2 3) (5 6) (8 8)) given that cdr returns the second and subsequent elements of a list. So you probably want (list 7 September 9) as your last list in your input, so that you get '((2 3) (5 6) (8 9)) instead.
You'd have to call the function like this: (myfunc cdr (list (list 1 2 3) (list 4 5 6) (list 7 September 9)))
Edit: Obviously it would make most sense to define September as 9, as it's the ninth month of the year, and call the function like this: (myfunc cdr (list (list 1 2 3) (list 4 5 6) (list 7 8 September)))

Mmap can be defined in terms of #lang racket's function map.
(define Mmap map)

Related

How to represent the following data structure in scheme r5rs

In Python the data structure looks like this: [([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
How would I represent the same in Scheme r5rs?
This is what I tried: (list (cons `(1 2 3) `(8 9 10)))
But running (display (list (cons `(1 2 3) `(8 9 10)))) gives (((1 2 3) 8 9 10)) whereas I want (((1 2 3) (8 9 10)))
Edit
Using only lists (as per #Will Ness answer here):
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
works.
And I can access the 2nd element of the tuple by
(cadr (car x)) which gives (8 9 10) (which is correct)
I was just thinking how would I build this up using cons since my tuple will only contain 2 elements and from what I know cons are used to represent a pair in Scheme. Any ideas on how to do this using cons?
[([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
(list ; a list of
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
Scheme is untyped, so we can just use lists for tuples. It is simpler that way -- the access is uniform. The first is car, the second cadr.
Your way is correct as well. What really determines whether it is or not is how you can access your data to retrieve its constituents back. And with your way you can indeed, too: the first element will be car and the second -- cdr.
(update to the question edit:) whether you use (cons 1 (cons 2 '())) or (list 1 2) is immaterial. the resulting structure in memory is the same.
There is an infinity of ways to represent data. You have been presented a way. Here is other way:
(define mk/data
(lambda (a b)
(lambda (?)
(cond ((eq? ? 'repr) (list (list a b)))
((eq? ? 'first) a)
((eq? ? 'second) b)))))
(define data/test (mk/data '(1 2 3) '(8 9 10)))
(data/test 'repr)
(data/test 'first)
(data/test 'second)
This is another way how the big systems actually represent data.

Is append the identity function for map?

In doing some tests I've noticed that append always gives me the same output as input when using map:
#lang sicp
(map append '(1 2 3 4 5))
(map (lambda (x) x) '(1 2 3 4 5))
; (1 2 3 4 5)
; (1 2 3 4 5)
(map append '((1 2)(3 4)))
(map (lambda (x) x) '((1 2)(3 4)))
; ((1 2) (3 4))
; ((1 2) (3 4))
That seems pretty neat/unexpected to me. Is this in fact the case? If so, how does the append work to give the identity property?
The append procedure takes zero or more list arguments, and a final argument that can be any object. When the final argument is a list, the result of appending is a proper list. When the final argument is not a list, but other list arguments have been provided, the result is an improper list. When only one argument is provided, it is just returned. This behavior with one argument is exactly the behavior of an identity procedure.
> (append '(1 2) '(3))
(1 2 3)
> (append '(1 2) 3)
(1 2 . 3)
> (append '(1 2))
(1 2)
> (append 3)
3
The call (map append '(1 2 3 4 5)) is equivalent to:
> (list (append 1)
(append 2)
(append 3)
(append 4)
(append 5))
(1 2 3 4 5)
Here, append is just acting as an identity procedure, as described above.

Matrix Manipulation in Racket

I need to write a function that produces the nth column of a matrix in Racket without using recursion. For example (list (list 1 2 3) (list 2 3 4) (list 6 7 9)) if I wanted the 2nd column I would receive (list 2 3 7).
I tried (append (map (lambda (n) (list-ref (list-ref M) n) n)) M)), but it keeps showing me an error.
The attempted solution uses list-ref twice, which is not needed, and one of those calls does not have enough arguments: (list-ref M) has the function taking only one argument, but it requires two arguments -- a list and an integer.
The list-ref function will return an indexed element from an input list, so (list-ref '(1 2 3) 1) will return 2. Consider what map will do here: the matrix is represented as a list of lists (a list of rows), i.e., as ((1 2 3) (2 3 4) (6 7 9)). The map function will act on the members of the input list, which are the lists (1 2 3), (2 3 4), and (6 7 9). By mapping the list-ref function over that input, you can take whichever element you want from the sublists. So, (map (lambda (row) (list-ref row 1)) '((1 2 3) (2 3 4) (6 7 9))) would evaluate to (2 3 7), as desired.
Here is a function that lets you take any column from a matrix:
(define (nth-column M n)
(map (lambda (row) (list-ref row n)) M))
Sample interactions:
scratch.rkt> (define M '((1 2 3)
(2 3 4)
(6 7 9)))
scratch.rkt> (nth-column M 1)
'(2 3 7)
scratch.rkt> (nth-column M 0)
'(1 2 6)
scratch.rkt> (nth-column M 2)
'(3 4 9)

How to use foldr in scheme?

When you use foldr, the procedure you use has 2 arguments, the current value of the list and the accumulator. Let's say the list you iterate over is a list of list of numbers, all the same length. Then as you iterate through them, you want to multiply the numbers of the same index and store it as the accumulator.
If you use lambda (x acc) (map * x acc) inside the foldr, this fails because acc I believe is an empty list in the beginning. How can you handle the base case like this?
This can be solved using foldr all right, the trick is to correctly initialize the accumulated value at the beginning. No need to do fancy stuff (like macros) here!
(define lst '((1 2 3) (2 3 5) (3 5 7)))
(foldr (lambda (x acc) (map * x acc))
(car lst)
(cdr lst))
=> '(6 30 105)
Of course, if the list is empty (car lst) will fail. So you might want to handle the empty list as a separate case before invoking foldr.
Say you have a list of lists as follows:
((1 2 3) (2 3 5) (3 5 7))
You want to reduce it to:
(6 30 105)
I would simple do:
(define-syntax mul
(syntax-rules ()
((_ (lists ...)) (map * 'lists ...))))
The you can use it as follows:
(mul ((1 2 3) (2 3 5) (3 5 7))) ; => (6 30 105)
The above code simply expands to:
(map * '(1 2 3) '(2 3 5) '(3 5 7))
Then you can fold the resulting list. For example:
(foldr + 0 (mul ((1 2 3) (2 3 5) (3 5 7)))) ; => 141

Scheme cons and length

I'm studying scheme and I have just encountered my first problem:
(define x (cons (list 1 2) (list 3 4)))
(length x)
3
why the output is 3 and not 2? I have displayed x
((1 2) 3 4)
why is like that and not ((1 2) . (3 4)) ?
Thanks.
Maybe it's easier to see this way.
You have:
(cons (list 1 2) (list 3 4))
If you
(define one-two (list 1 2))
you have
(cons one-two (list 3 4))
which is equivalent to
(cons one-two (cons 3 (cons 4 '())))
or
(list one-two 3 4)
which is
((1 2) 3 4)
List is the basic data structure of scheme.
Cons is used for making a pair of objects. List is the chain of cons.
eg. list (1 2 3 4) is same as (cons 1(cons 2(cons 3(cons 4 '())))).
See the block pointer representation for make it clear

Resources