[ create a new paste ] login | about

Project: programmingpraxis
Link: http://programmingpraxis.codepad.org/KfoIdPZG    [ raw code | output | fork ]

programmingpraxis - Scheme, pasted on May 20:
; hamming codes

; http://www2.rad.com/networks/1994/err_con/hamming.htm

(define (make-matrix rows columns . value)
  (do ((m (make-vector rows)) (i 0 (+ i 1)))
      ((= i rows) m)
    (if (null? value)
        (vector-set! m i (make-vector columns))
        (vector-set! m i (make-vector columns (car value))))))

(define (matrix-rows x) (vector-length x))

(define (matrix-cols x) (vector-length (vector-ref x 0)))

(define (matrix-ref m i j) (vector-ref (vector-ref m i) j))

(define (matrix-set! m i j x) (vector-set! (vector-ref m i) j x))

(define-syntax for
  (syntax-rules ()
    ((for (var first past step) body ...)
      (let ((ge? (if (< first past) >= <=)))
        (do ((var first (+ var step)))
            ((ge? var past))
          body ...)))
    ((for (var first past) body ...)
      (let* ((f first) (p past) (s (if (< first past) 1 -1)))
        (for (var f p s) body ...)))
    ((for (var past) body ...)
      (let* ((p past)) (for (var 0 p) body ...)))))

(define (column v k)
  (if (<= (vector-length (vector-ref v 0)) k)
      (error 'column "out of bounds")
      (let ((z (make-matrix (matrix-rows v) 1)))
        (do ((r 0 (+ r 1))) ((= r (matrix-rows v)) z)
          (matrix-set! z r 0 (matrix-ref v r k))))))

(define (vector-map f v)
  (for (i (vector-length v))
    (vector-set! v i (f (vector-ref v i))))
  v)

(define (subvector v first past)
  (let* ((len (- past first))
         (z (make-vector len)))
    (do ((from first (+ from 1)) (to 0 (+ to 1)))
        ((= from past) z)
      (vector-set! z to (vector-ref v from)))))

(define (mmul2 x y) ; matrix multiplication mod 2
  (let* ((x-rows (matrix-rows x)) (x-cols (matrix-cols x))
         (y-rows (matrix-rows y)) (y-cols (matrix-cols y))
         (z-rows x-rows) (z-cols y-cols))
    (if (not (= x-cols y-rows))
        (error 'mul2 "incompatible matrices")
        (let ((z (make-matrix z-rows z-cols 0)))
          (for (i x-rows)
            (for (j y-cols)
              (for (k x-cols)
                (matrix-set! z i j
                  (modulo
                    (+ (matrix-ref z i j)
                       (* (matrix-ref x i k)
                          (matrix-ref y k j)))
                    2)))))
          z))))

(define g #( #(1 0 0 0 1 1 1)
             #(0 1 0 0 0 1 1)
             #(0 0 1 0 1 0 1)
             #(0 0 0 1 1 1 0)))

(define h #( #(1 0 1 1 1 0 0)
             #(1 1 0 1 0 1 0)
             #(1 1 1 0 0 0 1)))

(define (encode c)
  (vector-ref (mmul2 (vector c) g) 0))

(define (decode r)
  (let* ((s (mmul2 h (vector-map vector r)))
         (len (matrix-rows g))
         (z (vector-map (lambda (v) (vector-ref v 0)) (subvector r 0 len))))
    (let loop ((c 0))
      (cond ((= c len) z)
            ((equal? s (column h c))
              (vector-set! z c (- 1 (vector-ref z c))) ; flip bit
              z)
            (else (loop (+ c 1)))))))

(display (encode #(1 0 0 1))) (newline)
(display (decode #(1 0 0 1 0 0 1))) (newline)
(display (decode #(0 0 0 1 0 0 1))) (newline)
(display (decode #(1 1 0 1 0 0 1))) (newline)
(display (decode #(1 0 1 1 0 0 1))) (newline)
(display (decode #(1 0 0 0 0 0 1))) (newline)
(display (decode #(1 0 0 1 1 0 1))) (newline)
(display (decode #(1 0 0 1 0 1 1))) (newline)
(display (decode #(1 0 0 1 0 0 0))) (newline)


Output:
1
2
3
4
5
6
7
8
9
#(1 0 0 1 0 0 1)
#(1 0 0 1)
#(1 0 0 1)
#(1 0 0 1)
#(1 0 0 1)
#(1 0 0 1)
#(1 0 0 1)
#(1 0 0 1)
#(1 0 0 1)


Create a new paste based on this one


Comments: