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 <[email protected]>
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