Range finder

The RangeFinder iterator is used in our algorithm to trace hiatus in the sediment history. This iterator consumes an iterator of booleans and yields values of type UnitRange, giving all ranges for which the input sequence is true consecutively.

⪡algoritms-spec⪢≣
a = [false, true, true, false, true]
@test collect(find_ranges(a)) == [2:3, 5:5]
file:src/Algorithms/RangeFinder.jl
module RangeFinder

struct _RangeFinder{T}
	v::T
end

Base.iterate(r::_RangeFinder{T}) where {T} = iterate(r, 1)

function Base.iterate(r::_RangeFinder{T}, i::Union{Int, Nothing}) where {T}
	isnothing(i) && return nothing
	a = findnext(r.v, i)
	isnothing(a) && return nothing
	b = findnext(!, r.v, a)
	isnothing(b) && return (a:length(r.v)), nothing
	return (a:b-1), b
end

Base.eltype(r::_RangeFinder{T}) where {T} = UnitRange{Int}
Base.IteratorSize(::Type{_RangeFinder{T}}) where {T} = Base.SizeUnknown()

"""
    find_ranges(v::AbstractVector{Bool})

Take a vector of bools, returns an iterator over all ranges for
which the vector is `true`.
"""
find_ranges(v::T) where {T <: AbstractVector{Bool}} = _RangeFinder{T}(v)

export find_ranges

end