Skip to content

Instantly share code, notes, and snippets.

@oisdk
Last active December 5, 2015 01:07
Show Gist options
  • Save oisdk/d381e5939e33901fc797 to your computer and use it in GitHub Desktop.
Save oisdk/d381e5939e33901fc797 to your computer and use it in GitHub Desktop.
// IntervalTypes
protocol IntervalType {
typealias Value
func contains(v: Value) -> Bool
}
protocol OpenEndedIntervalType: IntervalType {
typealias Value: Comparable
var val: Value { get }
}
protocol OpenStartedIntervalTypeTo: IntervalType {
typealias Value: Comparable
var val: Value { get }
}
protocol OpenStartedIntervalTypeThrough: IntervalType {
typealias Value: Comparable
var val: Value { get }
}
// Interval Structs
struct OpenEndedInterval<C: Comparable>: OpenEndedIntervalType { internal let val: C }
struct OpenStartedIntervalTo<C: Comparable>: OpenStartedIntervalTypeTo { internal let val: C }
struct OpenStartedIntervalThrough<C: Comparable>: OpenStartedIntervalTypeTo { internal let val: C }
// Range structs
struct OpenEndedRange<I: ForwardIndexType where I: Comparable>: OpenEndedIntervalType {
var val: I
}
struct OpenStartedRangeTo<I: BidirectionalIndexType where I: Comparable>: OpenStartedIntervalTypeTo {
var val: I
}
struct OpenStartedRangeThrough<I: BidirectionalIndexType where I: Comparable>: OpenStartedIntervalTypeTo {
var val: I
}
// Generators
struct EndlessIncrement<I: ForwardIndexType>: GeneratorType {
private var i: I
mutating func next() -> I? {
defer { i = i.successor() }
return i
}
}
struct EndlessPostDecrement<I: BidirectionalIndexType>: GeneratorType {
private var i: I
mutating func next() -> I? {
defer { i = i.predecessor() }
return i
}
}
struct EndlessPrefDecrement<I: BidirectionalIndexType>: GeneratorType {
private var i: I
mutating func next() -> I? {
i = i.predecessor()
return i
}
}
// SequenceType
extension OpenEndedRange: LazySequenceType {
func generate() -> EndlessIncrement<I> {
return EndlessIncrement(i: val)
}
}
extension OpenStartedRangeTo: LazySequenceType {
func generate() -> EndlessPrefDecrement<I> {
return EndlessPrefDecrement(i: val)
}
}
extension OpenStartedRangeThrough: LazySequenceType {
func generate() -> EndlessPostDecrement<I> {
return EndlessPostDecrement(i: val)
}
}
// Operators
postfix operator ... {}
prefix operator ... {}
prefix operator ..< {}
postfix func ...<C: Comparable>(c: C) -> OpenEndedInterval<C> {
return OpenEndedInterval(val: c)
}
postfix func ...<I: ForwardIndexType>(c: I) -> OpenEndedRange<I> {
return OpenEndedRange(val: c)
}
prefix func ..<<C: Comparable>(c: C) -> OpenStartedIntervalTo<C> {
return OpenStartedIntervalTo(val: c)
}
prefix func ..<<C: BidirectionalIndexType>(c: C) -> OpenStartedRangeTo<C> {
return OpenStartedRangeTo(val: c)
}
prefix func ...<C: Comparable>(c: C) -> OpenStartedIntervalThrough<C> {
return OpenStartedIntervalThrough(val: c)
}
prefix func ...<C: BidirectionalIndexType>(c: C) -> OpenStartedRangeThrough<C> {
return OpenStartedRangeThrough(val: c)
}
// Contains
extension OpenEndedIntervalType {
func contains(e: Value) -> Bool { return val <= e }
}
extension OpenStartedIntervalTypeTo {
func contains(v: Value) -> Bool { return val > v }
}
extension OpenStartedIntervalTypeThrough {
func contains(v: Value) -> Bool { return val >= v }
}
// Pattern Matching
func ~=<I: IntervalType>(lhs: I, rhs: I.Value) -> Bool {
return lhs.contains(rhs)
}
// Indexing
extension CollectionType where Index: Comparable {
subscript(r: OpenEndedInterval<Index>) -> SubSequence {
return suffixFrom(r.val)
}
subscript(r: OpenStartedIntervalTo<Index>) -> SubSequence {
return prefixUpTo(r.val)
}
subscript(r: OpenStartedIntervalThrough<Index>) -> SubSequence {
return prefixThrough(r.val)
}
}
extension MutableCollectionType where Index: Comparable {
subscript(r: OpenEndedInterval<Index>) -> SubSequence {
get { return suffixFrom(r.val) }
set { self[r.val...endIndex] = newValue }
}
subscript(r: OpenStartedIntervalTo<Index>) -> SubSequence {
get { return prefixUpTo(r.val) }
set { self[startIndex..<r.val] = newValue }
}
subscript(r: OpenStartedIntervalThrough<Index>) -> SubSequence {
get { return prefixThrough(r.val) }
set { self[startIndex...r.val] = newValue }
}
}
extension CollectionType where Index: Comparable {
subscript(r: OpenEndedRange<Index>) -> SubSequence {
return suffixFrom(r.val)
}
}
extension CollectionType where Index: Comparable, Index: BidirectionalIndexType {
subscript(r: OpenStartedRangeTo<Index>) -> SubSequence {
return prefixUpTo(r.val)
}
subscript(r: OpenStartedRangeThrough<Index>) -> SubSequence {
return prefixThrough(r.val)
}
}
extension MutableCollectionType where Index: Comparable {
subscript(r: OpenEndedRange<Index>) -> SubSequence {
get { return suffixFrom(r.val) }
set { self[r.val...endIndex] = newValue }
}
}
extension MutableCollectionType where Index: Comparable, Index: BidirectionalIndexType {
subscript(r: OpenStartedRangeTo<Index>) -> SubSequence {
get { return prefixUpTo(r.val) }
set { self[startIndex..<r.val] = newValue }
}
subscript(r: OpenStartedRangeThrough<Index>) -> SubSequence {
get { return prefixThrough(r.val) }
set { self[startIndex...r.val] = newValue }
}
}
// Hopping
public struct RandomAccessHopCollection<
Base: CollectionType where
Base.Index : RandomAccessIndexType,
Base.Index.Distance : ForwardIndexType
> : CollectionType {
private let base: Base
private let by : Base.Index.Stride
private let fac : Base.Index.Distance
public var startIndex: Base.Index.Distance { return 0 }
public let endIndex: Base.Index.Distance
public subscript(i: Base.Index.Distance) -> Base.Generator.Element {
return base[base.startIndex.advancedBy(fac * i)]
}
private init(_ b: Base, _ by: Base.Index.Stride) {
base = b
self.by = by
fac = base.startIndex.distanceTo(base.startIndex.advancedBy(by))
endIndex = (base.startIndex.distanceTo(base.endIndex.predecessor()) / fac).successor()
}
}
extension CollectionType where Index: RandomAccessIndexType, Index.Distance: ForwardIndexType {
public subscript(by by: Index.Stride) -> RandomAccessHopCollection<Self> {
return RandomAccessHopCollection(self, by)
}
}
extension RandomAccessHopCollection: CustomStringConvertible, CustomDebugStringConvertible {
public var debugDescription: String {
return Array(self).debugDescription
}
public var description: String {
return String(Array(self))
}
}
extension CollectionType where
SubSequence: CollectionType,
Index == SubSequence.Index,
SubSequence.Index: RandomAccessIndexType,
SubSequence.Index.Distance: ForwardIndexType {
subscript(r: OpenEndedInterval<Index>, by by: Index.Stride) -> RandomAccessHopCollection<SubSequence> {
return suffixFrom(r.val)[by: by]
}
subscript(r: OpenStartedIntervalTo<Index>, by by: Index.Stride) -> RandomAccessHopCollection<SubSequence> {
return prefixUpTo(r.val)[by: by]
}
subscript(r: OpenStartedIntervalThrough<Index>, by by: Index.Stride) -> RandomAccessHopCollection<SubSequence> {
return prefixThrough(r.val)[by: by]
}
subscript(r: OpenEndedRange<Index>, by by: Index.Stride) -> RandomAccessHopCollection<SubSequence> {
return suffixFrom(r.val)[by: by]
}
subscript(r: OpenStartedRangeTo<Index>, by by: Index.Stride) -> RandomAccessHopCollection<SubSequence> {
return prefixUpTo(r.val)[by: by]
}
subscript(r: OpenStartedRangeThrough<Index>, by by: Index.Stride) -> RandomAccessHopCollection<SubSequence> {
return prefixThrough(r.val)[by: by]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment