Replace list into list of list - scheme

How can I build a function that receives a list and builds 2 lists that on the first one are all the even numbers and on the other one are all the odd numbers?
For the input: (fun '(1 2 3 4 5 6))
the output will be: ((2 4 6) (1 3 5)).

There's a built-in for that, simply use partition and provide the right predicate. The rest of the code is just for capturing the returned values and building the output list:
(define (my-partition lst)
(let-values ([(evens odds) (partition even? lst)])
(list evens odds)))
For example:
(my-partition '(1 2 3 4 5 6))
=> '((2 4 6) (1 3 5))

Related

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 can i append to a list without creating a dotted pair

how do i append (1 2 3) to the end of () to make ((1 2 3))
how do i append (4 5 6) to the end of that to make ((1 2 3) (4 5 6))
how do i append "|" to the end of that to make ((1 2 3) (4 5 6) "|")
with NO dotted pairs.
I'm working with Chicken Scheme but I'll take an answer from any scheme at this point. Note that any of these lists could also be nested lists of who knows what... i'm just writing a trivial example.
note: #sjamaan shows a solution using append that involves wrapping everything in another list to compensate for append doing things OTHER than what the name says.
(append (list 1 2 3) "|" ) ;=> (1 2 3 . "|")
;^^ didn't actually append, created a dotted pair
(append '(1 2 3) (list 4 5 6)) ;=> (1 2 3 4 5 6) ; don't want unwrapped list
;^^ didn't actually append the list i gave it but appended the contents of the list.
Basically I'm hoping for an append method that actually appends what you give it, not appends the contents of it, or takes it and makes a dotted pair. Maybe i'm just a dreamer... I can write a "no really append" method that just takes whatever params you give it and wraps them in an outer list to compensate but that's just silly... Surely scheme has some way to append without this crazyness.
Here is how append is made:
(define (append2 lst1 lst2)
(if (null? lst1)
lst2 ; the second list is unaltered
(cons (car lst1)
(append2 (cdr lst1) lst2))))
makes a pair chain consisting of all the elements in lst1 and lst2. It does not make a pair where there is nont in lst2 so:
(append2 '(1 2 3) '(4 5)) ; ==> (1 2 3 4 5)
(append2 '(1 2 3) '()) ; ==> (1 2 3) and not (1 2 3 ())
(append2 '(1 2 3) '5) ; ==> (1 2 3 . 5)
Note that every list like (1 2 3) actually is (1 2 3 . ()) or even more correctly (1 . (2 . (3 . ())))
how do i append (1 2 3) to the end of () to make ((1 2 3))
(define (insert-last e lst)
(let helper ((lst lst))
(if (pair? lst)
(cons (car lst)
(helper (cdr lst)))
(cons e '()))))
(insert-last '(1 2 3) '())
; ==> ((1 2 3))
how do i append (4 5 6) to the end of that to make ((1 2 3) (4 5
6))
(insert-last '(4 5 6) '((1 2 3)))
; ==> ((1 2 3) (4 5 6))
how do i append "|" to the end of that to make ((1 2 3) (4 5 6)
"|")
(insert-last "|" '((1 2 3) (4 5 6)))
; ==> ((1 2 3) (4 5 6) "|")
Know that this is very much like append. These are the worst way to make that list since you are making a new list every time. It's O(n) for each insert and O(n^2) for n elements. If you could do this in reverse order you get something that do this O(1) instead of O(n) for each insert. Instead of insert-last you use cons:
(cons '"|" '()) ; ==> ("|")
(cons '(4 5 6) '("|")) ; ==> ((4 5 6) "|")
(cons '(1 2 3) '((4 5 6) "|") ; ==> ((1 2 3) (4 5 6) "|")
This is O(1), O(n) for n elements processed. If you need to do it in the original order you can accumulate, then reverse..
(cons '(1 2 3) '()) ; ==> ((1 2 3))
(cons '(4 5 6) '((1 2 3))) ; ==> ((4 5 6) (1 2 3))
(cons '"|" '((4 5 6) (1 2 3))) ; ==> ("|" (4 5 6) (1 2 3))
(reverse '("|" (4 5 6) (1 2 3)) ; ==> ((1 2 3) (4 5 6) "|")
This is O(1), then O(n) for the reverse but it still is O(1) amortized. O(n) for n elements you process.
append doesn't append atoms to lists. It concatenates lists. You have to lift the atom up to a list before concatenation makes sense.
(append xs (list y))
But it makes sense to point out (reverse (cons y (reverse xs))) which has the same result. reverse suggests that you might be building up your list backwards if you need to append atoms to the end.
The procedure you're looking for is unsurprisingly called append (from SRFI-1). It appends a list of things onto another list. This does mean that if you want to add just one item, you'll need to make a list out of it:
(append '() '((1 2 3))) => ((1 2 3))
(append '((1 2 3)) '((4 5 6))) => ((1 2 3) (4 5 6))
(append '((1 2 3) (4 5 6)) '("|") ) => ((1 2 3) (4 5 6) "|")
It accepts multiple arguments, which will all be appended to eachother in that order, so you can also do:
(append '() '((1 2 3)) '((4 5 6)) '("|")) => ((1 2 3) (4 5 6) "|")
Hope this helps!
Whether you want it or not, cons cells will be created, since lists consist of cons cells.
how do i append (1 2 3) to the end of () to make ((1 2 3))
CL-USER 24 > (list '(1 2 3))
((1 2 3))
how do i append (4 5 6) to the end of that to make ((1 2 3) (4 5 6))
CL-USER 25 > (append '((1 2 3)) (list '(4 5 6)))
((1 2 3) (4 5 6))
how do i append "|" to the end of that to make ((1 2 3) (4 5 6) "|")
CL-USER 26 > (append '((1 2 3) (4 5 6)) (list "|"))
((1 2 3) (4 5 6) "|")

Adding Elements In a List Scheme

In Scheme, I am trying to iterate through a list adding each element from a portion of the list.
For example, if I had ((1 2 5) (1 2) (1 5) (1) (2 5) (2) (5) ()) for a list, I am trying to add the first part ( 1 2 5 ) and then the second part ( 1 2 ) and so on in order to see if each element adds up to a specific number.
Hope this makes sense, tried my best to explain this.
If someone could help me figure this problem out, I would really appreciate it.
To add the numbers of a (small) list you can use apply:
> (apply + '(1 2 3))
6
which is the same as
> (+ 1 2 3)
6
In order to apply this to a list of sublists, use map:
(define (f lst)
(map (lambda (sublst) (apply + sublst))
lst))
> (f '((1 2 5) (1 2) (1 5) (1) (2 5) (2) (5) ()))
'(8 3 6 1 7 2 5 0)
For larger list you might want to replace apply by foldl or equivalent.

Racket/ more than one function

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)

Resources