2013-05-20 7 views
1

Je vais avoir un problème de transformer un vecteur comme ceci:Scheme/Vecteur Racket dans la transformation vecteur

#(#(1 2 3)#(1 2 3)#(1 2 3)#(1 2 3)#(1 2 3))) 

Dans un comme ceci:

#(#(1 1 1 1 1) #(2 2 2 2 2) #(3 3 3 3 3)) 

J'ai écrit un morceau de code de test, mais la la sortie est erronée. Je suis allé dans le débogueur et je pense que je sais quelle ligne de code cause le problème. Je ne peux pas trouver un moyen de le faire fonctionner. Toute aide est grandement appréciée.

(define (test) 
    (let* ((table #(#(1 2 3)#(1 2 3)#(1 2 3)#(1 2 3)#(1 2 3))) 
     (counter 5) 
     (size 3) 
     (new-table (make-vector size (make-vector counter #f)))) 

    (let loop ((sc 0) 
       (cc 0)) 
     (when (not (= cc counter)) 
     (if (not (= sc size)) 
      (begin (vector-set! (vector-ref new-table sc) cc (vector-ref (vector-ref table cc) sc)) 
        (loop (+ 1 sc) cc)) 
      (loop 0 (+ 1 cc))))) 
    (display new-table))) 

> (test) 
#(#(3 3 3 3 3) #(3 3 3 3 3) #(3 3 3 3 3)) 
+2

Par ailleurs, la « transformation » que vous effectuez est le ([transposer] http://en.wikipedia.org/wiki/Transpose) d'une matrice implémentée comme un vecteur de vecteurs –

Répondre

4

Il y a un problème dans cette partie:

(make-vector size (make-vector counter #f)) 

Pourquoi? parce que vous copiez le exactement le même vecteur dans toutes les positions new-table, donc quand vous mettez à jour une valeur, cela va les changer tous en même temps. Il est facile de voir ceci:

(define new-table (make-vector 3 (make-vector 3 #f))) 
(vector-set! (vector-ref new-table 0) 0 42) ; we modify a single position ... 
new-table 
=> '#(#(42 #f #f) #(42 #f #f) #(42 #f #f)) ; ... but all of them changed! 

Vous devez initialiser le vecteur au début; une version fixe de votre code ressemblerait à ceci:

(let* ((table '#(#(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3))) 
     (counter (vector-length table)) 
     (size (vector-length (vector-ref table 0))) 
     (new-table (make-vector size))) 
    ; initialization 
    (let loop ((i 0)) 
    (when (< i size) 
     (vector-set! new-table i (make-vector counter)) 
     (loop (+ i 1)))) 
    (let loop ((sc 0) 
      (cc 0)) 
    (when (not (= cc counter)) 
     (if (not (= sc size)) 
      (begin 
      (vector-set! (vector-ref new-table sc) cc 
         (vector-ref (vector-ref table cc) sc)) 
      (loop (+ 1 sc) cc)) 
      (loop 0 (+ 1 cc)))) 
    new-table)) 

Cependant, la solution ci-dessus est difficile à comprendre. Heureusement, cela semble être un bon problème à utiliser Iterations and Comprehensions de Racket, de sorte que vous n'avez pas à vous soucier de l'utilisation explicitement récursion pour l'itération, conduisant à une solution beaucoup plus claire:

(let* ((table '#(#(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3))) 
     (counter (vector-length table)) 
     (size (vector-length (vector-ref table 0))) 
     (new-table (make-vector size))) 
    (for ([sc (in-range size)]) 
    (vector-set! new-table sc (make-vector counter)) ; initialization 
    (for ([cc (in-range counter)]) 
     (vector-set! (vector-ref new-table sc) cc 
        (vector-ref (vector-ref table cc) sc)))) 
    new-table) 

De toute façon, la sortie est comme prévu :

=> '#(#(1 1 1 1 1) #(2 2 2 2 2) #(3 3 3 3 3)) 

Note: Comme il est, c'est une solution de style de programmation procédurale, qui modifie les nouveaux vecteurs en place et a l'avantage d'être rapide et efficace (il ne crée pas plus de vecteurs ou listes au-delà du strict nécessaire), mais à vrai dire, ce n'est pas l'habituel façon de résoudre les problèmes dans Scheme. Pour une solution de style de programmation fonctionnelle, plus dans l'esprit de Scheme, voir la réponse @ Ankur.

4

Vous pouvez également utiliser vector-map pour obtenir la sortie désirée:

(define table #(#(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3))) 

(apply vector-map vector (vector->list table))