I'm starting scheme for Gimp script-fu and I don't find a simple way to remove item from a vector.
My only solution is to:
Convert vector to list
Remove item from the list (http://stackoverflow.com/questions/1905222/how-to-delete-an-element-from-a-list-in-scheme)
Convert list to vector
Is it a simplier way?
Here is my code:
(set! myvector (list->vector (delete item (vector->list myvector))))
(define delete
(lambda (item list)
(cond
((equal? item (car list)) (cdr list))
(else (cons (car list) (delete item (cdr list)))))))
That's the way: you need to create a new vector without the element that needs to be removed, copying all the others. But in your code, you're missing the case where the element is not present in the vector, also you don't need to create an intermediate list, go from vector to vector directly. I wrote this with Racket using standard Scheme, it should be easy enough to adapt for script-fu:
(define (vector-delete vec elt)
(let ((new-vec (if (> (vector-length vec) 0)
(make-vector (- (vector-length vec) 1))
(vector))))
(define (loop i j)
(cond ((= i (vector-length vec))
new-vec)
((equal? (vector-ref vec i) elt)
(loop (+ i 1) j))
((< j (vector-length new-vec))
(vector-set! new-vec j (vector-ref vec i))
(loop (+ i 1) (+ j 1)))
(else vec)))
(loop 0 0)))
Use it like this:
(define myvector #(1 2 3))
(set! myvector (vector-delete myvector 3))
myvector
=> '#(1 2)
Or by a more intuitive way :
(define (vector-delete v i)
(vector-append (vector-take v i) (vector-drop v (+ i 1))))
Related
I need to make a recursive function that takes an object and a vector and returns a list of all the objects that preceded my object parameter.
I did it using iteration like this:
(define (precedes obj vec)
(do ((i 1 (+ i 1))
(list '() (if (eqv? obj (vector-ref vec i))
(cons(vector-ref vec (- i 1)) list)
list)))
((= i (vector-length vec)) list))
)
but I'm having a lot of trouble trying to figure out how to do the same thing using recursion. I'm confused how I can keep incrementing through the vector as I recursively call. So far, all I have is this:
(define (precedes2 obj vec)
(define list '())
(if (eqv? obj (vector-ref vec i))
(cons(vector-ref vec(- i 1)) list)
list)))
I figured I would use the same logic I used before in terms of the if statement, but I'm not sure how to now call the same function with the updated vector. Any help would be great.
You're in the interesting position of moving from an iterative implementation to a recursive one; usually people go in the other direction. Fortunately, moving from a do-loop to recursion is pretty easy. In general, a do loop can be rewritten as follows:
(do ((i i-init i-step)
(j j-init j-step)
...)
(test result)
body)
becomes
(define f (i j ...)
(cond
(test result)
(else body (f i-step j-step ...))))
(f i-init j-init ...)
That translation is usually written using a named let, though:
(let f ((i i-init)
(j j-init)
...)
(cond
(test result)
(else body (f i-step j-step ...))))
So (and I haven't tested the code) your original function
(define (precedes obj vec)
(do ((i 1 (+ i 1))
(list '() (if (eqv? obj (vector-ref vec i))
(cons(vector-ref vec (- i 1)) list)
list)))
((= i (vector-length vec)) list))
)
would turn into
(define (precedes obj vec)
(let loop ((i 1)
(list '()))
(cond
((= i (vector-length vec)) list)
(else (loop (+ i 1)
(if (eqv? obj (vector-ref vec i))
(cons (vector-ref vec (- i 1)) list)
list))))))
I'm trying to solve the n-queens problem in scheme. I was told by my professor to use a single vector as the chess board where the ith element of the vector represents the ith column of the board. The value of that element is the row on which sits a queen, or -1 if the column is empty. So, [0 1 2 -1 -1] has two columns with no queen and three queens placed illegally.
When I run this code: (place-n-queens 0 4 #(-1 -1 -1 -1)) I get #(0 1 2 3) which obviously has all four queens placed illegally. I think the issue is that I don't check enough things in the cond in place-queen-on-n but I'm not sure what to add to solve the issue of getting queens on the same diagonal.
(define (return-row vector queen)
(vector-ref vector (return-col vector queen)))
(define (return-col vector queen)
(remainder queen (vector-length vector)))
(define (checkrow vector nq oq)
(cond
((= (vector-ref vector nq) -1) #f)
((= (vector-ref vector oq) -1) #f)
(else (= (return-row vector nq) (return-row vector oq)))))
(define (checkcol vector nq oq)
(= (return-col vector nq) (return-col vector oq)))
(define (checkdiagonal vector nq oq)
(cond
((= (vector-ref vector nq) -1) #f)
((= (vector-ref vector oq) -1) #f)
(else (= (abs (- (return-row vector nq) (return-row vector oq)))
(abs (- (return-col vector nq) (return-col vector oq)))))))
(define (checkdiagonalagain vector r c oq)
(= (abs (- r (return-row vector oq)))
(abs (- c (return-col vector oq)))) )
(define (checkrowagain vector r oq)
(= r (return-row vector oq)))
(define (checkinterference vector nq oq)
(or (checkrow vector nq oq) (checkcol vector nq oq) (checkdiagonal vector nq oq)))
(define (place-queen-on-n vector r c)
(local ((define (foo x)
(cond
((checkrowagain vector r x) -1)
((= c x) r)
((checkinterference vector c x) -1)
((map (lambda (y) (eq? (vector-ref vector x) y))
(build-list (vector-length vector) values)) (vector-ref vector x))
((eq? (vector-ref vector x) -1) -1)
(else -1))))
(build-vector (vector-length vector) foo)))
(define (place-a-queen vector)
(local ((define (place-queen collist rowlist)
(cond
((empty? collist) '())
((empty? rowlist) '())
(else (append (map (lambda (x) (place-queen-on-n vector x (car collist))) rowlist)
(try vector (cdr collist) rowlist)))
)))
(place-queen (get-possible-col vector) (get-possible-row (vector->list vector) vector))))
(define (try vector collist rowlist)
(cond
((empty? collist) '())
((empty? rowlist) '())
(else (append (map (lambda (x) (place-queen-on-n vector x (car collist))) rowlist)
(try vector (cdr collist) rowlist)))))
(define (get-possible-col vector)
(local ((define (get-ava index)
(cond
((= index (vector-length vector)) '())
((eq? (vector-ref vector index) -1)
(cons index (get-ava (add1 index))))
(else (get-ava (add1 index))))))
(get-ava 0)))
;list is just vector turned into a list
(define (get-possible-row list vector)
(filter positive? list)
(define (thislist) (build-list (vector-length vector) values))
(remove* list (build-list (vector-length vector) values))
)
(define (place-n-queens origination destination vector)
(cond
((= origination destination) vector)
(else (local ((define possible-steps
(place-n-queens/list (add1 origination)
destination
(place-a-queen vector))))
(cond
((boolean? possible-steps) #f)
(else possible-steps))))))
(define (place-n-queens/list origination destination boards)
(cond
((empty? boards) #f)
(else (local ((define possible-steps
(place-n-queens origination destination (car boards))))
(cond
((boolean? possible-steps) (place-n-queens/list origination destination (cdr boards)))
(else possible-steps))
))))
Any help is appreciated to get this working!!
That's hard to follow. Generally n-queens is done with some sort of backtracking and I'm not seeing where you backtrack. The hard part is managing the side effects when using a vector. You have to set the board the the previous state before going back.
(define (n-queens size)
(let ((board (make-vector size -1)))
(let loop ((col 0) (row 0))
(cond ((= col size) board)
((= row size) ;;dead end
(if (= col 0) ;;if first collumn
#f ;;then no solutions
(begin (vector-set! board (- col 1) -1))
#f)))
;;else undo changes made by previous level and signal the error
((safe? col row board)
(vector-set! board col row)
(or (loop (+ col 1) 0)
;;only precede to next column if a safe position is found
(loop col (+ row 1))))
;; keep going if hit a dead end.
(else (loop col (+ row 1)))))))
Writing safe? is up to you though.
Also not sure why you are moving from vector to list. It's just really clogging up the logic so I'm having trouble following. Plus you should be comfortable moving through vectors on their own. In place-queen-on-n you use build-list on a vector just so you can map over it.
Whereas a vector-fold of some sort may be more appropriate. Additionally that map will always return a list which is always not false, meaning any code after that in the cond will never get hit. Is that your problem, I don't know but it is a problem.
How would I write a vector-to-list function without using the built in (vector->list) function. Specifically I am looking to learn how to access values within vectors as I have not previously worked with them.
Is there a more straightforward implementation than this:
(define (vector-to-list vec)
(define (helper k lst)
(if (= k (vector-length vec))
lst
(helper (+ k 1) (cons (vector-ref vec k) lst))))
(reverse (helper 0 '())))
(vector-to-list #(1 2 3 4))
?
No, that is a sound implementation. One could write it a bit more idiomatically using 'named-let' as:
(define (vector-to-list vec)
(let ((len (vector-length vec)))
(let looping ((k 0) (lst '())
(if (= k len)
(reverse lst)
(looping (+ k 1)
(cons (vector-ref vec k) lst)))))
You could avoid the use of reverse by constructing the list from back to front:
(define (vector-to-list vec)
(let looping ((k (- (vector-length vec) 1)) (lst '())
(if (< k 0)
lst
(looping (- k 1)
(cons (vector-ref vec k) lst)))))
I am trying to implement a mergesort algorithm in Scheme using vectors. I am aware of other sorting methods that I could use, but I would like to finish my code on this. What I have so far is as follows.
(define (split v)
(define (helper k v1 v2)
(let ((m (floor (/ (vector-length v) 2))))
(if (>= k m)
(if (= k (vector-length v))
(cons v1 v2)
(helper (+ k 1) v1 (vector-append v2 (vector (vector-ref v k)))))
(helper (+ k 1) (vector-append v1 (vector (vector-ref v k))) v2))))
(helper 0 #() #()))
(define (merge v1 v2)
(if (< (vector-ref v1 0) (vector-ref v2 0))
(vector-append v1 v2)
(vector-append v2 v1)))
(define (mergesort v)
(if (<= (vector-length v) 1)
v
(merge (mergesort (car (split v))) (mergesort (cdr (split v))))))
I am very close to my answer, but I am missing something. Any help here?
The main stumbling block for your implementation is that your merge function didn't correctly implement the merge algorithm. In the merge algorithm:
You have two pointers, which initially point to the start of the left-hand and right-hand lists.
If both pointers are at the end of their respective lists, you're done.
If either pointer is at the end of its respective list, output the remaining elements of the other list. Done.
At this point, both pointers point to an element. If the right-hand element is less than the left-hand element, output the right-hand element, and advance the right pointer. Otherwise, output the left-hand element, and advance the left pointer. Go to step 2.
My merge-into! function below implements such an approach.
Aside from that, the other main biggie is that your split function is trying to build vectors piecemeal, and sadly, that is a slow process: it has to copy all the elements into a new vector each time. It's not like cons! With vectors, don't be hesitant to use vector-set!; any immutable update of vectors is going to be slow and inefficient, so just bite the bullet and make it mutable. :-)
For reference, I wrote a new implementation from scratch (in Racket):
(define (split-halves vec)
(vector-split-at vec (quotient (vector-length vec) 2)))
(define (merge lhs rhs)
(define result (make-vector (+ (vector-length lhs)
(vector-length rhs))))
(merge-into! result lhs rhs))
(define (merge-into! result lhs rhs)
(let loop ((i 0) (j 0) (k 0))
(define (take-left)
(vector-set! result k (vector-ref lhs i))
(loop (add1 i) j (add1 k)))
(define (take-right)
(vector-set! result k (vector-ref rhs j))
(loop i (add1 j) (add1 k)))
(cond ((= k (vector-length result)) result)
((= i (vector-length lhs))
(take-right))
((= j (vector-length rhs))
(take-left))
((< (vector-ref rhs j) (vector-ref lhs i))
(take-right))
(else
(take-left)))))
(define (mergesort vec)
(case (vector-length vec)
((0 1) vec)
(else (let-values (((lhs rhs) (split-halves vec)))
(merge (mergesort lhs) (mergesort rhs))))))
The merge-into! function allows a mutating version of mergesort to be easily written:
(define (mergesort! vec)
(case (vector-length vec)
((0 1) vec)
(else (let-values (((lhs rhs) (split-halves vec)))
(mergesort! lhs)
(mergesort! rhs)
(merge-into! vec lhs rhs)))))
If you don't use Racket, you may need these following additional definitions (which require SRFI 43; see bottom of post if you don't have that):
(define (vector-split-at vec pos)
(values (vector-copy vec 0 pos)
(vector-copy vec pos (vector-length vec))))
(define (add1 x)
(+ x 1))
let-values is defined in SRFI 11. If you don't have that, here's a version of mergesort that uses call-with-values:
(define (mergesort vec)
(case (vector-length vec)
((0 1) vec)
(else (call-with-values (lambda () (split-halves vec))
(lambda (lhs rhs)
(merge (mergesort lhs) (mergesort rhs)))))))
vector-copy is defined in SRFI 43. If you don't have that, here's a simplified version of that:
(define (vector-copy vec start end)
(define result (make-vector (- end start)))
(do ((i start (+ i 1))
(j 0 (+ j 1)))
((>= i end) result)
(vector-set! result j (vector-ref vec i))))
I am writing a function to count the number of ways to make change in scheme given a list of denominations and an amount. My code is as follows, but it does not work as intended. Should I be using cons instead of the + operator? Should the third line down's base case be the empty list?
(define (change k l)
(cond ((= k 0) 1)
((or (< k 0) (null? l)) 0)
(else (+ (change k (cdr l))
(change (- k (car l))
(cdr l))))))
Test:
(change 11 (list 1 5 10 25))
If the returned value is just a number then forget about cons and '() for building the output, and only use car, cdr, null? for processing the input. Other than that, be aware that there's a small mistake in the last line of your code, here's the fixed version:
(define (change k l)
(cond ((= k 0) 1)
((or (< k 0) (null? l)) 0)
(else
(+ (change k (cdr l))
(change (- k (car l)) l))))) ; don't do (cdr l) here
Now it works as expected:
(change 11 (list 1 5 10 25))
=> 4