2015-09-25 19:45:10 +03:00
|
|
|
public enum Vertex<Element>: CustomDebugStringConvertible, CustomStringConvertible {
|
2015-09-25 01:23:48 +03:00
|
|
|
indirect case XY(Element, Memo<Vertex>, Memo<Vertex>)
|
2015-09-24 22:45:36 +03:00
|
|
|
case End
|
2015-09-24 20:28:46 +03:00
|
|
|
|
2015-09-25 19:36:11 +03:00
|
|
|
public func analysis<Result>(@noescape ifXY ifXY: (Element, Memo<Vertex>, Memo<Vertex>) -> Result, @noescape ifEnd: () -> Result) -> Result {
|
|
|
|
switch self {
|
|
|
|
case let .XY(a, x, y):
|
|
|
|
return ifXY(a, x, y)
|
|
|
|
case .End:
|
|
|
|
return ifEnd()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-28 19:09:43 +03:00
|
|
|
public var isEmpty: Bool {
|
|
|
|
return analysis(ifXY: const(false), ifEnd: const(true))
|
|
|
|
}
|
|
|
|
|
2015-09-25 01:23:56 +03:00
|
|
|
public var element: Element? {
|
2015-09-25 19:37:08 +03:00
|
|
|
return analysis(
|
|
|
|
ifXY: { x, _, _ in x },
|
|
|
|
ifEnd: const(nil))
|
2015-09-25 01:23:56 +03:00
|
|
|
}
|
2015-09-24 22:45:36 +03:00
|
|
|
|
|
|
|
public var right: Memo<Vertex> {
|
2015-09-25 19:37:08 +03:00
|
|
|
return analysis(
|
|
|
|
ifXY: { _, xs, _ in xs },
|
|
|
|
ifEnd: const(Memo(evaluated: .End)))
|
2015-09-24 22:45:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public var down: Memo<Vertex> {
|
2015-09-25 19:37:08 +03:00
|
|
|
return analysis(
|
|
|
|
ifXY: { _, _, ys in ys },
|
|
|
|
ifEnd: const(Memo(evaluated: .End)))
|
2015-09-24 20:28:46 +03:00
|
|
|
}
|
|
|
|
|
2015-09-24 22:45:36 +03:00
|
|
|
public var diagonal: Memo<Vertex> {
|
|
|
|
return right.flatMap { $0.down }
|
|
|
|
}
|
2015-09-25 19:37:42 +03:00
|
|
|
|
2015-09-24 22:45:56 +03:00
|
|
|
|
2015-09-25 19:37:58 +03:00
|
|
|
public var row: Stream<Element> {
|
|
|
|
return Stream.unfold(Memo(evaluated: self)) {
|
|
|
|
$0.value.analysis(
|
|
|
|
ifXY: { here, across, _ in .Some(here, across) },
|
|
|
|
ifEnd: const(nil))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public var column: Stream<Element> {
|
|
|
|
return Stream.unfold(Memo(evaluated: self)) {
|
|
|
|
$0.value.analysis(
|
|
|
|
ifXY: { here, _, down in .Some(here, down) },
|
|
|
|
ifEnd: const(nil))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-25 19:38:11 +03:00
|
|
|
public var rowMajor: Stream<Stream<Element>> {
|
|
|
|
return Stream.unfold(Memo(evaluated: self), { (state: Memo<Vertex>) -> (Stream<Element>, Memo<Vertex>)? in
|
|
|
|
state.value.analysis(
|
|
|
|
ifXY: { _, _, down in (state.value.row, down) },
|
|
|
|
ifEnd: const(nil))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
public var columnMajor: Stream<Stream<Element>> {
|
|
|
|
return Stream.unfold(Memo(evaluated: self), { (state: Memo<Vertex>) -> (Stream<Element>, Memo<Vertex>)? in
|
|
|
|
state.value.analysis(
|
|
|
|
ifXY: { _, across, _ in (state.value.column, across) },
|
|
|
|
ifEnd: const(nil))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-25 18:57:53 +03:00
|
|
|
public init<S1: SequenceType, S2: SequenceType>(rows: S1, columns: S2, combine: (S1.Generator.Element, S2.Generator.Element) -> Element) {
|
|
|
|
let rows = Stream(sequence: rows)
|
|
|
|
let columns = Stream(sequence: columns)
|
2015-09-26 01:50:59 +03:00
|
|
|
func across(vertex: Vertex<Element>) -> Stream<Memo<Vertex<Element>>> {
|
|
|
|
return Stream.unfold(Memo(evaluated: vertex)) { vertex in
|
|
|
|
vertex.value.analysis(
|
|
|
|
ifXY: { _, xs, _ in .Some(vertex, xs) },
|
|
|
|
ifEnd: const(.Some(vertex, vertex)))
|
|
|
|
}
|
|
|
|
}
|
2015-09-25 19:52:59 +03:00
|
|
|
self = rows
|
|
|
|
.map { a in columns.map { b in combine(a, b) } }
|
2015-09-26 01:50:59 +03:00
|
|
|
.fold(.End) {
|
|
|
|
$0.zipWith(across($1.value)).fold(.End) {
|
|
|
|
.XY($0.0, $1, $0.1)
|
|
|
|
}
|
2015-09-24 22:45:56 +03:00
|
|
|
}
|
|
|
|
}
|
2015-09-24 22:45:36 +03:00
|
|
|
|
|
|
|
|
|
|
|
public func map<Other>(transform: Element -> Other) -> Vertex<Other> {
|
2015-09-24 20:28:46 +03:00
|
|
|
switch self {
|
2015-09-24 22:45:36 +03:00
|
|
|
case let .XY(xy, xs, ys):
|
|
|
|
return .XY(transform(xy), xs.map { $0.map(transform) }, ys.map { $0.map(transform) })
|
|
|
|
case .End:
|
|
|
|
return .End
|
2015-09-24 20:28:46 +03:00
|
|
|
}
|
|
|
|
}
|
2015-09-25 19:44:20 +03:00
|
|
|
|
|
|
|
|
|
|
|
public var debugDescription: String {
|
|
|
|
return rowMajor.map {
|
|
|
|
$0.map { String(reflecting: $0) }.joinWithSeparator("\t")
|
|
|
|
}.joinWithSeparator("\n")
|
|
|
|
}
|
2015-09-25 19:45:10 +03:00
|
|
|
|
|
|
|
public var description: String {
|
|
|
|
return rowMajor.map {
|
|
|
|
$0.map { String($0) }.joinWithSeparator("\t")
|
|
|
|
}.joinWithSeparator("\n")
|
|
|
|
}
|
2015-09-24 20:28:46 +03:00
|
|
|
}
|