Here's my shot using generators. It's probably much slower than yours
due to all the continuation jumps. This way keeps all four states in
your "state machine" in one place.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require racket/generator)
(define (list-of-ranges-of-ones v)
  (define vec (append (vector->list v) '(0)))
  (sequence->list
    (in-generator
     (for/fold ([in-ones? #f])
         ([elt (in-list vec)]
          [index (in-naturals)])
       (cond [(and (zero? elt) in-ones?) ; Stop! Yield the list
              (yield (list in-ones? (sub1 index)))
              #f]
             [(and (zero? elt) (not in-ones?)) ; Keep stopping
              #f]
             [(and (not (zero? elt)) in-ones?) ; Keep going
              in-ones?]
             [(and (not (zero? elt)) (not in-ones?)) ; Go! Save this spot.
              index])))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



On Sun, 13 May 2012 16:47:45 -0400, Harry Spier <vasishtha.sp...@gmail.com> 
wrote:
> Is there a better way to do this iin Racket (shorter, clearer, more readable)?
>
> I have vectors of 1's and 0's (each vector representing a row of black
> and white pixels.  I need to transform each vector into a list of
> pairs.  Each pair containing the start and end vector-ref's of a
> contiguous segment of black pixels.
> Examples:
> (list-of-ranges-of-ones #(0))                              ->  '()
> (list-of-ranges-of-ones #(0 0))                             ->  '()
> (list-of-ranges-of-ones #(0 0 0))                         ->  '()
> (list-of-ranges-of-ones #(1))                               ->  '((0 0))
> (list-of-ranges-of-ones #(1 1))                             ->   '((0 1))
> (list-of-ranges-of-ones #(1 1 1))                           -> '((0 2))
> (list-of-ranges-of-ones #(1 1 1 0))                        -> '((0 2))
> (list-of-ranges-of-ones #(0 1 1 1))                       -> '((1 3))
> (list-of-ranges-of-ones #(0 1 1 1 0))                    -> '((1 3))
> (list-of-ranges-of-ones #( 0 1 1 1 0 0 0 1 1 1 0))   ->  '((1 3) (7 9))
> (list-of-ranges-of-ones #( 1 1 1 1 0 0 0 1 1 1 1))  -> '((0 3) (7 10))
> (list-of-ranges-of-ones #( 0 1 0 1 0 1 0 1 0 1 0))  ->'((1 1) (3 3) (5
> 5) (7 7) (9 9))
>
> I've come up with the following but is there a better way to do this
> in Racket (shorter, clearer, more elegant?)
>
> #lang racket
> (define (list-of-ranges-of-ones vectr)
>   (let-values ([(more? get-next)(sequence-generate (in-indexed vectr))])
>
>     (define (add-a-range-of-ones current-range)
>       (define-values (current-val vectr-ref)  (get-next))
>       (cond
>         [(and (not (more?)) (= current-val 1)) (list (reverse (cons
>    vectr-ref   current-range)))]
>         [(and (not (more?)) (= current-val 0)) (list (reverse (cons
> (sub1 vectr-ref)  current-range)))]
>         [(= current-val 1) (add-a-range-of-ones current-range)]
>         [else  (cons (reverse (cons (sub1 vectr-ref) current-range))
> (skip-zeroes))]))
>
>     (define (skip-zeroes)
>       (cond
>         [(not (more?)) '()]
>         [else (define-values (current-val vectr-ref)  (get-next))
>               (cond
>                 [(= current-val 0) (skip-zeroes)]
>                 [else  (add-a-range-of-ones (list vectr-ref))])]))
>
>     (if (= 1 (vector-ref vectr 0))
>         (add-a-range-of-ones '(0))
>         (skip-zeroes))))
>
> Thanks,
> Harry
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
____________________
  Racket Users list:
  http://lists.racket-lang.org/users

Reply via email to