Matrix Operations? - matrix

As I am a SCHEME beginner, I am having a tough time figuring out how to work with matrices.
I am unsure on how to do the following:
A) Given a matrix, return the dimensions of said matrix
EX:// '(2 3 4)
(1 0 6)
should return (2.3) for 2 rows, three columns
B) Reverse the order of rows in a given matrix
EX:// given '((1 2)
(3 5)
(9 0))
the reverse should be
'((9 0)(3 5)(1 2))
C) Same as part B but reverse order of columns instead
D) Reverse order of columns and rows
Thanks in advance! This would really mean a lot if someone could give any help at all!

Standard R6RS Scheme doesn't provide matrices, though some implementations may provide them. The usual trick when implementing them yourself is to use a vector of vectors, rather than a list of lists as you showed above, because you generally don't want to access the elements of the matrix in order, and vectors provide constant-time access to each of their elements whereas lists provide linear-time access to each of their elements.
I have a small library of matrix operations at my blog; you can find uses of that library with the search function on the blog.

This is very simple to implement in terms of lists operations - given that your matrix representation is nothing more than a list of sublists! This is obviously a homework, so you better try to solve it by your own means. But I can give you some hints and test cases:
(define (dimensions m)
(cons <???> <???>)) ; length of m and length of m's first row
(dimensions '((2 3 4) (1 0 6)))
; => (2 . 3)
(define (reverse-rows m)
<???>) ; just reverse the list
(reverse-rows '((1 2) (3 5) (9 0)))
; => '((9 0)(3 5)(1 2))
(define (reverse-columns m)
<???>) ; reverse each of the sublists. Hint: use `map`
(reverse-columns '((1 2) (3 5) (9 0)))
; => '((2 1) (5 3) (0 9))
(define (reverse-columns-rows m)
<???>) ; call previous procedures, the ouput of one is the input of the other
(reverse-columns-rows '((1 2) (3 5) (9 0)))
; => '((0 9) (5 3) (2 1))

(define dimensions
(λ (mat)
(cons (length mat) (length (car mat)))))
This works because the matrix is represented as a list of rows, where each row is a list. So, (length mat) is the number of rows. Since each row is represented as a list of all the items in its columns, you can find out how many columns there are just by finding out how many elements are in one of the rows. For simplicity, you can just look at the first row: (length (car mat)).
(define reverse-rows reverse)
This works because the matrix is just a list of rows. So, you can just bind reverse-rows to the standard procedure for reversing any list.
(define reverse-columns
(λ (mat)
(map reverse mat)))
This works because each row is just a list of items. The map applies reverse to each item in mat (that is, each row) and returns a new list, containing the new rows.
(define reverse-rows-columns
(λ (mat)
(reverse-rows (reverse-columns mat))))
This works because up above, we've already defined a way to reverse rows and a way to reverse columns. If you want to do both, you can just combine them.

Related

Alternating Sum Using Foldr/Foldl (Racket)

Back again with another Racket question. New to higher order functions in general, so give me some leeway.
Currently trying to find the alternating sum using the foldr/foldl functions and not recursion.
e.g. (altsum '(1 3 5 7)) should equal 1 - 3 + 5 - 7, which totals to -4.
I've thought about a few possible ways to tackle this problem:
Get the numbers to add in one list and the numbers to subtract in another list and fold them together.
Somehow use the list length to determine whether to subtract or add.
Maybe generate some sort of '(1 -1 1 -1) mask, multiply respectively, then fold add everything.
However, I have no clue where to start with foldl/foldr when every operation is not the same for every item in the list, so I'm having trouble implementing any of my ideas. Additionally, whenever I try to add more than 2 variables in my foldl's anonymous class, I have no idea what variables afterward refer to what variables in the anonymous class either.
Any help or pointers would be greatly appreciated.
We can leverage two higher-order procedures here: foldr for processing the list and build-list for generating a list of alternating operations to perform. Notice that foldr can accept more than one input list, in this case we take a list of numbers and a list of operations and iterate over them element-wise, accumulating the result:
(define (altsum lst)
(foldr (lambda (ele op acc) (op acc ele))
0
lst
(build-list (length lst)
(lambda (i) (if (even? i) + -)))))
It works as expected:
(altsum '(1 3 5 7))
=> -4
Your idea is OK. You can use range to make a list of number 0 to length-1 and use the oddness of each to determine + or -:
(define (alt-sum lst)
(foldl (lambda (index e acc)
(define op (if (even? index) + -))
(op acc e))
0
(range (length lst))
lst))
As an alternative one can use SRFI-1 List Library that has fold that allows different length lists as well as infinite lists and together with circular-list you can have it alterate between + and - for the duration of lst.
(require srfi/1) ; For R6RS you import (srfi :1)
(define (alt-sum lst)
(fold (lambda (op n result)
(op result n))
0
(circular-list + -)
lst))
(alt-sum '(1 3 5 7))
; ==> -4

Diagonal of a matrix in racket [duplicate]

This question already has answers here:
Find main diagonal in matrix - Scheme
(3 answers)
Closed 4 years ago.
I have a list of lists(matrix) and i would like to access using (map or apply) the main diagonal.
The problem is larger, to make a matrix of a list of images removing the duplicates but i did that part.
(make-list (length (filter (lambda (x) (<= (image-height x) max-height)) L))
(filter (lambda (x) (<= (image-height x) max-height)) L)) )
I don't have a clue how to access using map or apply the elements of the main diagonal..
Remember that map requires a procedure that takes as many arguments as you have lists to map. In this case we want to access the ith element of a list, this is the built-in procedure list-ref which takes a list L and an index i and returns the ith element of L. So then we just need the indexes of the diagonal elements. This is (list 0 1 2 ...) which we can generate using build-list.
(define (diagonal M)
(define indexes (build-list (length M) values))
(map list-ref M indexes))
You don't have to build the second list if you use recursion. In this case you build the diagonal in a recursive function where we take the leading element of the first row, then recur on the rest of the elements in the rest of the rows:
(define (diagonal M)
(if (null? M)
'()
(cons (caar M)
(diagonal (map cdr (cdr M))))))
It's going to take basically the same amount of operations in terms of building the diagonal, but the second one doesn't require a new list be generated up front and doesn't require determining the size of the matrix, so it's a little better.

Sum of rows in a matrix with lisp

I'm doing some LISP exercises using functions mapcar and apply. I'm dealing with matrixes, and I have to sum its rows and columns. For column I have:
(apply #'mapcar #'+ matrix)
That works. Since I know how to transpose a matrix, I can do the exact same thing for the rows right? Right, that would be:
(apply #'mapcar #'+ (apply #'mapcar #'list matrix))
But I'm not happy with that. I want to sum the row directly, so I did a mapcar of apply:
(mapcar #'apply #'+ matrix)
that doesn't work and I don't know why. The error is
The value #(FUNCTION +) is not of type LIST.
[Condition of type TYPE-ERROR]
For me, that would get every list inside matrix, and apply the sum in each one. I cannot make a mapcar of apply? If no, why not? Is there another way to sum the rows of a matrix using just mapcar and apply?
PS: I'm using lispstick to compile and the matrix is a list of lists. Example
((1 1 1) (2 2 2) (3 3 3))
for a 3x3 matrix.
Your error
The error you got is from mapcar which expects lists as its arguments after the 1st one, and finds the function + instead.
Solution
What you need is a partial application of apply to +, i.e.,
(defparameter matrix '((1 1 1) (2 2 2) (3 3 3)))
(mapcar (lambda (l) (apply #'+ l)) matrix)
==> (3 6 9)
You can even define a function for that:
(defun partial-application (f &rest some-args)
(lambda (&rest more-args)
(apply f (append some-args more-args))))
(funcall (partial-application #'+ 4) 5)
==> 9
(funcall (partial-application #'+ 1 2) 3 4 5)
==> 15
Now you can use it instead of the lambda:
(mapcar (partial-application #'apply #'+) matrix)
==> (3 6 9)
Notes:
(lambda (l) (apply #'+ l)) and (partial-application #'apply #'+) merely compute the sum of a list, and can be defined in many different ways as discussed elsewhere.
append cannot be safely replaced with the non-consing verson nconc because some-args is not guaranteed to be fresh:
The value of a rest parameter is permitted, but not required, to share structure with the last argument to apply.

Finding the largest list in a definition of lists in lists?

I have a question regarding finding the largest list in a group of lists in scheme.
For example, we define:
(define manylsts (list (list 9 (list 8 7)) 6 (list 5 (list 4 3 2) 1)))
How would I go about finding the largest list in manylsts?
Thank you
You make a procedure that evaluates to zero if it's argument is not a list. (eg. 9), then if its a list you foldl over the elements using length of the argument as accumulator with a lambda that does max between the recursion of the first argument with the accumulator. It would look something like this:
(define (max-children tree)
(if <??>
(foldl (λ (x acc)
(max <??> (max-children <??>)))
(length <??>)
<??>)
0))
Of course there are many ways of doing this, including explicit recursion, but this was the first thing I though of.
I will answer this question as you asked it.
You said you want to
finding the largest list in manylsts
Since you included a non-listed element inside manylsts you want to have a definition that tells you how big is an element (if is a list).
So I wrote the function elemenlen that returns the length of a list if the given element is a list and 0 otherwise.
(define elemenlen
(λ (a)
(if (list? a) (length a) 0)
))
Then I decided I was going to sort them in order of length and then return the first element. So I need a function that returns a boolean value to use it with sort function included in racket/base.
(define list<
(λ (listA listB)
(< (elemenlen listA) (elemenlen listB))))
(define list>
(λ (listA listB)
(not (list< listA listB))))
The first function returns #t if listA is smaller than listB. The second function returns #t if listA is bigger than listB.
Lastly, biggestElement does the whole trick, sorts the elements in list L in descending order (based on length) and returns the first element.
(define biggestElement
(λ (L)
(car (sort L list>)
)))
The function is used like this:
>(biggestElement '((3 2 1) 1 (1 (2 3) 3))
'(1 (2 3) 3)
That is just one way of doing it, there are other ways of doing it, keep it up and tell us if it helped you.
As you see, I decomposed the big problem into little problems. This is a very handy way of doing your DrRacket homework.

List length comparison

I wanted to write the code for comparing the size of two lists. I made use of the length and wrote this down.
(define (same-size-matrix? mtrx1 mtrx2)
(equal? (length mtrx1) (length mtrx2))).
I thought this was going to work for me, but I found out it only checks the overall length, not the sublist. For example it returns true when it compares for. '((1 2 3 4) (4 5 6 6) (6 7 8 9)) and '(( 5 4) (3 2) (7 1)), but it's supposed to return false, because the first has 4 values within the list and the second has only two even though they both overally have same length. How do I go about this. Any help would be appreciated.
Try this instead:
(define (same-size-matrix? mtrx1 mtrx2)
(equal? (map length mtrx1) (map length mtrx2)))
Notice that in your solution you're comparing the total length of each list (the number of rows in the matrix), but ignoring the length of each sublist (the number of columns for each row in the matrix). In my soultion, first we calculate the length of each sublist and after that we check if all the lengths are equal. For example, take this input:
(define mtrx1 '((1 2 3 4) (4 5 6 6) (6 7 8 9)))
(define mtrx2 '((5 4) (3 2) (7 1)))
(same-size-matrix? mtrx1 mtrx2)
First the same-size-matrix? evaluates this expression, which finds the length of each sublist in mtrx1. It's necessary to check all the lengths, not just the first one, in case we're dealing with a jagged array:
(map length mtrx1)
; evaluates to '(4 4 4)
And then we have this expression, which performs the same operation for mtrx2:
(map length mtrx2)
; evaluates to '(2 2 2)
Finally, we compare the two lists of lengths (in fact: the number of columns per row), returning the expected result:
(equal? '(4 4 4) '(2 2 2))
> #f
Notice that the last comparison will also detect if the lists are of different size, in case the matrices have a different number of rows.
is it scheme?
(define m1 `((1 2 3 4) (4 5 6 6 ) (6 7 8 9)))
(define m2 `((5 4) (3 2) (7 1)))
(define (same-size-matrix? m1 m2) (equal? (map length m1) (map length m2)))
(same-size-matrix? m1 m2) ; => #f
(same-size-matrix? m1 m1) ; => #t
Here is a simple definition of same-size?.
#lang racket
; A MATRIX is a list of ROWs.
; A ROW is a list of numbers.
; In a matrix all rows are of the same length.
(define (row-size list-of-rows)
(length list-of-rows))
(define (column-size matrix)
(define first-row (first matrix))
(length first-row))
(define (same-size? matrix1 matrix2)
(and (= (row-size matrix1) (row-size matrix2))
(= (column-size matrix1) (column-size matrix2))))
As a bonus here is a predicate that test whether an object
is a matrix or not. Compare it to the data definitions.
(define (row? object)
(and (list? object)
(andmap number? object)))
(define (matrix? object)
(and (list? object)
(andmap row? object)
(apply = (map row-size object))))
You need to clarify if you want to check 1) the exact shape of the matrix or 2) the overall 'flattened' length.
what should be the result for (same-size-matrix? '((1 2) (3 4) (5 6)) '((1 2 3) (4 5 6)))?
1) => #f
2) => #t
Óscar López's answer is for 1.
If your requirement is 2, based on Óscar's answer:
(define (same-size-matrix? mtrx1 mtrx2)
(equal? (apply + (map length mtrx1)) (apply + (map length mtrx2))))

Resources