Created
June 16, 2015 13:11
-
-
Save oisdk/80113243e23989c313b2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol SeqInterp : SequenceType {} | |
struct ContGen<G : GeneratorType where G.Element : Strideable> : GeneratorType { | |
typealias Element = G.Element | |
private var g: G? | |
private var a: Element? | |
private var b: Element? | |
private var cur: Element? | |
private var strd: Element.Stride? | |
mutating func next() -> Element? { | |
return | |
g?.next().map{ | |
(a, b) = (b, $0) | |
return $0 | |
} ?? strd.map{ | |
cur = cur!.advancedBy($0) | |
return cur! | |
} ?? a.map{ | |
g = nil | |
strd = $0.distanceTo(b!) | |
cur = b!.advancedBy(strd!) | |
return cur! | |
} | |
} | |
private init(_ g: G) { | |
self.g = g | |
self.a = nil | |
self.b = nil | |
self.cur = nil | |
self.strd = nil | |
} | |
} | |
struct ContToGen<G : GeneratorType where G.Element : Strideable> : GeneratorType { | |
typealias Element = G.Element | |
private var g: G? | |
private var a: Element? | |
private var b: Element? | |
private let lim: Element | |
private var sG: StrideToGenerator<Element>? | |
mutating func next() -> Element? { | |
return | |
g?.next().map{ | |
(a, b) = (b, $0) | |
return $0 | |
} ?? { | |
guard sG == nil else {return sG!.next()} | |
guard let a = a, b = b else {return nil} | |
g = nil | |
sG = stride(from: b, to: lim, by: a.distanceTo(b)).generate() | |
sG!.next() | |
return sG!.next() | |
}() | |
} | |
private init(_ g: G, lim: Element) { | |
self.g = g | |
self.lim = lim | |
self.a = nil | |
self.b = nil | |
self.sG = nil | |
} | |
} | |
struct ContThroughGen<G : GeneratorType where G.Element : Strideable> : GeneratorType { | |
typealias Element = G.Element | |
private var g: G? | |
private var a: Element? | |
private var b: Element? | |
private let lim: Element | |
private var sG: StrideThroughGenerator<Element>? | |
mutating func next() -> Element? { | |
return | |
g?.next().map{ | |
(a, b) = (b, $0) | |
return $0 | |
} ?? { | |
guard sG == nil else {return sG!.next()} | |
guard let a = a, b = b else {return nil} | |
g = nil | |
sG = stride(from: b, through: lim, by: a.distanceTo(b)).generate() | |
sG!.next() | |
return sG!.next() | |
}() | |
} | |
private init(_ g: G, lim: Element) { | |
self.g = g | |
self.lim = lim | |
self.a = nil | |
self.b = nil | |
self.sG = nil | |
} | |
} | |
struct ContSeq<S : SequenceType where S.Generator.Element : Strideable> : SeqInterp { | |
typealias Generator = ContGen<S.Generator> | |
private let seq: S | |
func generate() -> Generator { | |
return ContGen(seq.generate()) | |
} | |
} | |
struct ContToSeq<S : SequenceType where S.Generator.Element : Strideable> : SeqInterp { | |
typealias Generator = ContToGen<S.Generator> | |
private let seq: S | |
private let lim: Generator.Element | |
func generate() -> Generator { | |
return ContToGen(seq.generate(), lim: lim) | |
} | |
} | |
struct ContThroughSeq<S : SequenceType where S.Generator.Element : Strideable> : SeqInterp { | |
typealias Generator = ContThroughGen<S.Generator> | |
private let seq: S | |
private let lim: Generator.Element | |
func generate() -> Generator { | |
return ContThroughGen(seq.generate(), lim: lim) | |
} | |
} | |
struct UnlimGen<T : ForwardIndexType> : GeneratorType { | |
typealias Element = T | |
private var cur: T | |
mutating func next() -> Element? { | |
defer { cur = cur.successor() } | |
return cur | |
} | |
} | |
struct UnlimSeq<T : ForwardIndexType> : SeqInterp { | |
typealias Generator = UnlimGen<T> | |
private let start: T | |
func generate() -> Generator { | |
return UnlimGen(cur: start) | |
} | |
} | |
struct UnlimJumpGen<T : Strideable> : GeneratorType { | |
typealias Element = T | |
private let strd: T.Stride | |
private var cur: T | |
mutating func next() -> Element? { | |
defer { cur = cur.advancedBy(strd) } | |
return cur | |
} | |
} | |
struct UnlimJumpSeq<T : Strideable> : SeqInterp { | |
typealias Generator = UnlimJumpGen<T> | |
private let strd: T.Stride | |
private let strt: T | |
func generate() -> Generator { return UnlimJumpGen(strd: strd, cur: strt) } | |
} | |
extension SequenceType where Generator.Element : Strideable { | |
func cont() -> ContSeq<Self> { | |
return ContSeq(seq: self) | |
} | |
func cont(to to: Self.Generator.Element) -> ContToSeq<Self> { | |
return ContToSeq(seq: self, lim: to) | |
} | |
func cont(through through: Self.Generator.Element) -> ContThroughSeq<Self> { | |
return ContThroughSeq(seq: self, lim: through) | |
} | |
} | |
postfix operator ... {} | |
struct _ContSeq<S : SequenceType where S.Generator.Element : Strideable> { | |
private let seq: S | |
} | |
postfix func ... | |
<S : SequenceType where S.Generator.Element : Strideable> | |
(from: S) -> _ContSeq<S> { | |
return _ContSeq(seq: from) | |
} | |
struct _ContToSeq<S : SequenceType where S.Generator.Element : Strideable> { | |
private let from: S | |
private let to: S.Generator.Element | |
} | |
func ..< | |
<S : SequenceType where S.Generator.Element : Strideable> | |
(from: S, to: S.Generator.Element) -> _ContToSeq<S> { | |
return _ContToSeq(from: from, to: to) | |
} | |
struct _ContThroughSeq<S : SequenceType where S.Generator.Element : Strideable> { | |
private let from: S | |
private let through: S.Generator.Element | |
} | |
func ... | |
<S : SequenceType where S.Generator.Element : Strideable> | |
(from: S, to: S.Generator.Element) -> _ContThroughSeq<S> { | |
return _ContThroughSeq(from: from, through: to) | |
} | |
struct _UnlimSeq<T : ForwardIndexType> { | |
private let start: T | |
} | |
postfix func ... <T : ForwardIndexType>(f: T) -> _UnlimSeq<T> { | |
return _UnlimSeq(start: f) | |
} | |
func seqFrom | |
<T : ForwardIndexType where T : Strideable> | |
(f: T, _ r: Range<T>) -> StrideTo<T> { | |
return stride(from: f, to: r.endIndex, by: f.distanceTo(r.startIndex)) | |
} | |
extension StrideTo : SeqInterp {} | |
extension StrideThrough : SeqInterp {} | |
extension SeqInterp { var array: [Generator.Element] { return Array(self) } } | |
func seqFrom | |
<T : ForwardIndexType where T : Strideable> | |
(f: T, _ r: _UnlimSeq<T>) -> UnlimJumpSeq<T> { | |
return UnlimJumpSeq(strd: f.distanceTo(r.start), strt: f) | |
} | |
func seqFrom<T>(f: _UnlimSeq<T>) -> UnlimSeq<T> { | |
return UnlimSeq(start: f.start) | |
} | |
func seqFrom<T>(f: _ContSeq<T>) -> ContSeq<T> { | |
return ContSeq(seq: f.seq) | |
} | |
func seqFrom<T>(f: _ContThroughSeq<T>) -> ContThroughSeq<T> { | |
return ContThroughSeq(seq: f.from, lim: f.through) | |
} | |
func seqFrom<T>(f: _ContToSeq<T>) -> ContToSeq<T> { | |
return ContToSeq(seq: f.from, lim: f.to) | |
} | |
seqFrom(3...) // 3, 4, 5, 6, 7, 8, 9... | |
seqFrom(1, 3...) // 1, 3, 5, 7, 9, 11... | |
seqFrom(1, 3...11) // 1, 3, 5, 7, 9, 11 | |
seqFrom(1, 3..<11) // 1, 3, 5, 7, 9 | |
seqFrom([1, 4]...) // 1, 7, 10, 13, 16... | |
seqFrom([1, 4]...10) // 1, 7, 10 | |
seqFrom([1, 4]..<10) // 1, 7 | |
seqFrom([1, 2, 4]...) // 1, 2, 4, 6, 8, 10... | |
seqFrom([1, 2, 4]...8) // 1, 2, 4, 6, 8 | |
seqFrom([1, 2, 4]..<8) // 1, 2, 4, 6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment