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)))))
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 was asked to write a procedure that computes elements of Pascal's triangle by means of a recursive process. I may create a procedure that returns a single row in the triangle or a number within a particular row.
Here is my solution:
(define (f n)
(cond ((= n 1) '(1))
(else
(define (func i n l)
(if (> i n)
l
(func (+ i 1) n (cons (+ (convert (find (- i 1) (f (- n 1))))
(convert (find i (f (- n 1)))))
l))))
(func 1 n '()))))
(define (find n l)
(define (find i n a)
(if (or (null? a) (<= n 0))
'()
(if (>= i n)
(car a)
(find (+ i 1) n (cdr a)))))
(find 1 n l))
(define (convert l)
(if (null? l)
0
(+ l 0)))
This seems to work fine but it gets really inefficient to find elements of a larger row starting with (f 8). Is there a better procedure that solves this problem by means of a recursive process?
Also, how would I write it, if I want to use an iterative process (tail-recursion)?
There are several ways to optimize the algorithm, one of the best would be to use dynamic programming to efficiently calculate each value. Here is my own solution to a similar problem, which includes references to better understand this approach - it's a tail-recursive, iterative process. The key point is that it uses mutation operations for updating a vector of precomputed values, and it's a simple matter to adapt the implementation to print a list for a given row:
(define (f n)
(let ([table (make-vector n 1)])
(let outer ([i 1])
(when (< i n)
(let inner ([j 1] [previous 1])
(when (< j i)
(let ([current (vector-ref table j)])
(vector-set! table j (+ current previous))
(inner (add1 j) current))))
(outer (add1 i))))
(vector->list table)))
Alternatively, and borrowing from #Sylwester's solution we can write a purely functional tail-recursive iterative version that uses lists for storing the precomputed values; in my tests this is slower than the previous version:
(define (f n)
(define (aux tr tc prev acc)
(cond ((> tr n) '())
((and (= tc 1) (= tr n))
prev)
((= tc tr)
(aux (add1 tr) 1 (cons 1 acc) '(1)))
(else
(aux tr
(add1 tc)
(cdr prev)
(cons (+ (car prev) (cadr prev)) acc)))))
(if (= n 1)
'(1)
(aux 2 1 '(1 1) '(1))))
Either way it works as expected for larger inputs, it'll be fast for n values in the order of a couple of thousands:
(f 10)
=> '(1 9 36 84 126 126 84 36 9 1)
There are a number of soluitons presented already, and they do point out that usign dynamic programming is a good option here. I think that this can be written a bit more simply though. Here's what I'd do as a straightforward list-based solution. It's based on the observation that if row n is (a b c d e), then row n+1 is (a (+ a b) (+ b c) (+ c d) (+ d e) e). An easy easy to compute that is to iterate over the tails of (0 a b c d e) collecting ((+ 0 a) (+ a b) ... (+ d e) e).
(define (pascal n)
(let pascal ((n n) (row '(1)))
(if (= n 0) row
(pascal (- n 1)
(maplist (lambda (tail)
(if (null? (cdr tail)) 1
(+ (car tail)
(cadr tail))))
(cons 0 row))))))
(pascal 0) ;=> (1)
(pascal 1) ;=> (1 1)
(pascal 2) ;=> (1 2 1)
(pascal 3) ;=> (1 3 3 1)
(pascal 4) ;=> (1 4 6 4 1)
This made use of an auxiliary function maplist:
(define (maplist function list)
(if (null? list) list
(cons (function list)
(maplist function (cdr list)))))
(maplist reverse '(1 2 3))
;=> ((3 2 1) (3 2) (3))
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
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))))