For a university project i have to make a game based in a matrix in the pretty big language, the matrix is being defined as a multidimensional vector.
I need to set a single element of the matrix, my code is:
(require racket/vector)
(define test (make-vector 4 (make-vector 4 0)))
(define (matrix-set matrix row column value)
(vector-set! (vector-ref matrix row) column value)
)
(display test)(newline)
(matrix-set test 0 0 1)
(display test)
And outputs this:
#(#(0 0 0 0) #(0 0 0 0) #(0 0 0 0) #(0 0 0 0))
#(#(1 0 0 0) #(1 0 0 0) #(1 0 0 0) #(1 0 0 0))
I have searched the racket documentation and only found functions that set an element by making a new matrix, this and this questions too.
Why is the function setting the whole column instead of only the element?
What can be done to resolve it?
(make-vector 4 (make-vector 4 0)) is the same as:
(let ((x (make-vector 4 0)))
(vector x x x x))
That is, (make-vector 4 0) is called only once, and its value is used for all 4 slots of the outer vector.
What you need is something like (for/vector ((i 4)) (make-vector 4 0)), which will call (make-vector 4 0) (and create a distinct vector) for each element of the outer vector.
An alternative approach is to use the vector generating iterator for/vector. I'm not sure the syntax is any cleaner than using thunks, but conceptually, I feel it is more familiar and perhaps simpler.
(define test (for/vector ([i (range 4)])(make-vector 4 0)))
(matrix-set test 0 0 1) ; '#(#(1 0 0 0) #(0 0 0 0) #(0 0 0 0) #(0 0 0 0))
A third alternative, that isn't as Racket like, would be using do.
(define test
(do ((vec (make-vector 4))
(i 0 (+ i 1)))
((= i 4) vec)
(vector-set! vec i (make-vector 4 0))))
On the other hand, sometimes it's worth knowing a bit about do because do don't require memorizing a different command for each type since do does what it does on vectors, lists, and hashes.
Related
I would like to generate a matrix (perhaps with numbers from a process, used 0 for simplification as below) in racket. I tried
(array (for/vector ((x (range 4)))
(for/vector ((y (range 4)))
0)))
which gives
(array '#(#(0 0 0 0) #(0 0 0 0) #(0 0 0 0) #(0 0 0 0)))
Silly enough though,
(matrix? (array (for/vector ((x (range 4)))
(for/vector ((y (range 4)))
0))))
gives #f, and so does (array '#(#(0 0 0 0) #(0 0 0 0) #(0 0 0 0) #(0 0 0 0))). Yet
> (matrix? (array #(#(0 0 0 0) #(0 0 0 0) #(0 0 0 0) #(0 0 0 0))))
#t
So what's going wrong with it?
EDIT: the matrix module is imported from math/array and math/matrix.
The array special form defines a new syntax, according to the docs it expects "nested rows of expressions" as its argument, which is not the same as a vector. For example:
(require math/array)
(require math/matrix)
(array #[#[1]])
=> (array #[#[1]])
(matrix? (array #[#[1]]))
=> #t
(array (vector (vector 1)))
; notice the difference, there's a quote and the brackets are not square
=> (array '#(#(1)))
(matrix? (array (vector (vector 1))))
=> #f
To summarize: you can't use a vector of vectors as a substitute for the special syntax that array requires as its argument. And it's not just a matter of removing the quote and using square brackets, they're objects of different types even though they look similar when printed.
array is some special magic thing which I don't understand but its body is not a general-purpose expression at all. If you want to make an array programmatically you want something like build-array or vector*->array:
(define nvs (for/vector ((x (range 4)))
(for/vector ((y (range 4)))
0)))
(define a (vector*->array nvs number?))
(define (pascal x y)
(cond ((or (<= x 0) (<= y 0) (< x y )) 0)
((or (= 1 y) (= x y) ) 1)
(else (+ (pascal (- x 1) y) (pascal (- x 1) (- y 1))))))
This is the function I have for a recursive pascal call that should return the number given the x and y of the triangle.
1
11
121
1331
14641
If I enter pascal 0 0, it should return 1, however it returns 0;
If I enter pascal 4 2, it should return 6, but it returns 3;
Seems like my base is off but I'm not sure how I can change it without ruining the calculation for pascals algorithm. Could someone point me to the right direction
You are very close, but your conditions aren't quite doing what you think they are. You have something like an off-by-1 error, and you haven't properly split apart your cond cases.
#lang racket/base
(for ((x (in-range 1 6)))
(for ((y (in-range (add1 x))))
(printf "~a " (pascal x y)))
(newline))
0 1
0 1 1
0 1 2 1
0 1 3 3 1
0 1 4 6 4 1
I make some small changes to your conditions and get this output:
(for ((x (in-range 6)))
(for ((y (in-range (add1 x))))
(printf "~a " (pascal x y)))
(newline))
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
If this doesn't help I can edit later and put the solution in, but this smells like homework and I don't want to just post a solution.
I'm new to scheme and having difficulty understanding vectors in scheme. I need to create a function that calculates the number of non-zero inputs in
a vector. I need to do this by not converting the vector into a list.
For exampl3.
(non-zero-dim #(3 0 2 4 0 2))
returns 4
My code so far is
(define non-zero-input
(lambda (vector)
(let ((size (vector-length vector)))
do ((position 0 (+ position 1))
(total 0
(if ((not (zero? vector-ref vector position)))
(+ total 1))
(((= position size) total)))))))
However I'm getting this error :do: bad syntax in: (do ((position 0 (+ position 1)) (total 0 (if ((not (zero? vector-ref vector position))) (+ total 1)) (((= position size) total))
How do i fix this error ?
Using the built-in procedures vector-length and vector-filter-not, you can simplify your function as:
(define (non-zero-dim vec)
(vector-length (vector-filter-not zero? vec)))
For example,
> (non-zero-dim #(3 0 2 4 0 2))
4
Some things to consider:
Keep track of your brackets. For example, (zero? vector-ref vector position) should be (zero? (vector-ref vector position)), whereby arity of zero? is one, and arity of vector-ref is two. Similarly with do ... vs. (do ... etc.
if statements must have an else clause (ie. (if condition then else)). For example, (if true 1) would fail, but (if true 1 2) would pass. Hence, (if ((not (zero? vector-ref vector position))) (+ total 1)) would fail.
The racket/vector package has vector-count, which returns the number of elements of a vector that satisfy a given predicate. This makes counting the non-zero values trivial:
#lang racket/base
(require racket/function racket/vector)
(define (non-zero-dim vec)
(vector-count (negate zero?) vec))
(println (non-zero-dim #(3 0 2 4 0 2)) ; 4
after defining the matrix :
(setq matriz '((1 0 0 0 0 0)
(1 1 0 0 0 0)
(0 1 1 1 0 0)
(0 0 0 1 0 0)
(0 0 0 1 1 0)
(0 0 0 0 1 1)))
I already made a function to get a number according to position (line and column)
But now i want to do a function to replace a number in the matrix according to the position and i am having trouble doing it.
Lets say i want to replace the position (3 3) that corresponds to the 1 in (0 0 0 1 0 0) i just don't know how to do it.
Can only use recursive functions what means no cycles . This I'm working is for maze solver
Would appreciate some help thanks :=)
:edited part this is what i have so far
(setq matriz '((1 0 0 0 0 0)(1 1 0 0 0 0)(0 1 1 1 0 0)(0 0 0 1 0 0)(0 0 0 1 1 0)(0 0 0 0 1 1)))
(defun path(i j)
(list (list (+ i 1) j)
(list (- i 1) j)
(list i (+ j 1))
(list i (- j 1))
))
(defun validsons (lf mat)
(cond
((null lf) nil)
((eq (devposmat (caar lf) (cadar lf) mat) 1) (cons (car lf) (validsons (cdr lf) mat)))
(t (validsons (cdr lf) mat))
)
)
(defun Devposicao(i lista)
(cond
((null lista) nil)
((< i 0) nil)
((= i 0) (car lista))
(t (Devposicao (- i 1) (cdr lista)))))
(defun DevPosMat(i j lista)
(Devposicao j (Devposicao i lista)))
;shows up avaiable paths (only 1s)
(defun rightpath(i j mat)
(validsons (path i j) mat)
)
;so you see the matrix correctly and not a list
(defun writematrix(Mat)
(cond
((null Mat) nil)
(t (progn
(print (car Mat))
(writematrix (cdr Mat))))
)
)
;this is what i was trying to do to replace
(defun changenumber (i j matriz)
(cond
((null matriz) nil)
((< i 0) nil)
((= i 0) (dec j (car matriz)))
(t (changenumber (- i 1) j (cdr matriz)))))
(defun dec (pos l)
(cond
((null l) nil)
((= pos 0) (cons (- (car l) 1) (cdr l)))
(t (cons (car l) (dec (- pos 1) (cdr l))))))
So i am able to use rightpath to move forward and see wich paths i have avaiable, but i just have to edit previous place i was so i dont keep going to my previous position.
Sorry if i posted something in the wrong way im not used to this.
Don't do it...
Common Lisp comes with multidimensional arrays, and it is crazy to use lists for matrices instead.
(defparameter *matrix*
(make-array '(6 6)
:element-type 'bit
:initial-contents
'((1 0 0 0 0 0)
(1 1 0 0 0 0)
(0 1 1 1 0 0)
(0 0 0 1 0 0)
(0 0 0 1 1 0)
(0 0 0 0 1 1))))
(setf (aref *matrix* 3 3) 1)
(see make-array)
...unless forced to
If you are required to use lists by a crazy professor, you can use something like
(setf (car (nthcdr (nth matrix i) j)) 1)
(see nth, nthcdr).
If you are forbidden from using those functions and are required to write your own recursive setter, please state so clearly and show your work (since we are now in the realm of crazy limitations, please also specify if your matrix is supposed to be immutable).
(defun set-matriz-ij (matriz i j val)
(setf (car (nthcdr j (nth i matriz))) val))
More generally, you ought to write a 'maze' abstraction:
(defun maze-ref (maze i j)
(nth j (nth i maze)))
(defsetf maze-ref (maze i j) (val)
`(setf (car (nthcdr ,j (nth ,i ,maze))) ,val))
(defun make-maze (n) ...)
(defun maze-path-at (i j)
`((,(+ i 1) ,j)
(,(- i 1) ,j)
...)))
;; etc
The above uses lists to implement the abstraction; matrices might be preferred but once you've made the abstraction, the implementation is a largely unimportant detail.
Common lisp newbie. Writing lisp code is quite different from writing c++/java, as I wrote them before.
I am trying to write a simple matrix class in common lisp for practice. Some codes like that:
(defun make-matrix (row col)
(make-list row :initial-element (make-list col :initial-element nil)))
(defun init-matrix (matrix init-value)
(labels ((set-element-value (lst)
(if (and lst
(listp lst))
(mapcar #'set-element-value lst)
(setf lst init-value))))
(set-element-value matrix)))
(defun matrix+ (&rest matrices)
(apply #'mapcar (lambda (&rest rows)
(apply #'mapcar #'+ rows)) matrices))
My question is can I write a matrix+ accepting different number of arguments without 'apply', or in a better way ? In a way that lisp should be?
And how about the matrix*, can somebody show me some awesome code accepting arbitrary number of arguments in matrix* ? Thanks.
Common Lisp has n-dimensional arrays. I would use those for matrix operations.
See: MAKE-ARRAY, AREF, ...
Typically I would also then write a binary (taking two arguments) matrix operation. Use then REDUCE to operate over a list of matrices.
CL-USER > (make-array '(3 5) :initial-element 0)
#2A((0 0 0 0 0) (0 0 0 0 0) (0 0 0 0 0))
Above creates a 2-dimensional array of size 3x5 with 0 as initial content.
Matrix multiplication. I can't promise this is the best example possible, but it is really straight-forward. This is given you use arrays rather than lists. Also, of course, you can optimize for square matrices, or special cases, like identity matrices etc. But this is meant only to be simple, not efficient etc.
(defun matrix* (&rest matrices)
(assert (cdr matrices) nil
"You will achieve nothing by multiplying a single matrix.")
(reduce
#'(lambda (a b)
(assert (= (array-dimension a 0) (array-dimension b 1)) nil
"The number of rows in the first matrix should be the number ~
of columns in the second matrix")
(let ((result
(make-array
(list (array-dimension a 1) (array-dimension b 0))
:initial-element 0)))
(dotimes (i (array-dimension a 1) result)
(dotimes (j (array-dimension b 0))
(dotimes (k (array-dimension a 0))
(incf (aref result i j) (* (aref a k i) (aref b j k))))))))
matrices))
(format t "result: ~s~&" (matrix* #2A((1 2) (3 4)) #2A((5 6) (7 8))))
;; #2A((23 31) (34 46)) =
;; (1 * 5 + 3 * 6 = 23) (1 * 7 + 3 * 8 = 31)
;; (2 * 5 + 4 * 6 = 34) (2 * 7 + 4 * 8 = 46)