Skip to content

Instantly share code, notes, and snippets.

@oisdk
Created June 16, 2015 13:11
Show Gist options
  • Save oisdk/80113243e23989c313b2 to your computer and use it in GitHub Desktop.
Save oisdk/80113243e23989c313b2 to your computer and use it in GitHub Desktop.
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