depth tracking

This commit is contained in:
Kyle Matthew Hedden 2021-03-22 13:31:05 -04:00
parent 0c0fff22bb
commit a45b5119cb
3 changed files with 25 additions and 24 deletions

View File

@ -24,28 +24,28 @@ public extension MoleculeModelProtocol {
public extension MoleculeModelProtocol { public extension MoleculeModelProtocol {
// Base case. No additional children to traverse. // Base case. No additional children to traverse.
func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int)->Result) -> Result {
return nextPartialResult(initialResult, self) return nextPartialResult(initialResult, self, depth)
} }
// Base case. No additional children to traverse. // Base case. No additional children to traverse.
func depthFirstTraverse(options: TreeTraversalOptions, onVisit: (MoleculeModelProtocol)->Void) { func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) {
onVisit(self) onVisit(depth, self)
} }
} }
public extension Array where Element == MoleculeModelProtocol { public extension Array where Element == MoleculeModelProtocol {
func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result { func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int)->Result) -> Result {
return reduce(initialResult) { (result, molecule) -> Result in return reduce(initialResult) { (result, molecule) -> Result in
return molecule.reduceDepthFirstTraverse(options: options, initialResult: result, nextPartialResult: nextPartialResult) return molecule.reduceDepthFirstTraverse(options: options, depth: depth, initialResult: result, nextPartialResult: nextPartialResult)
} }
} }
func depthFirstTraverse(options: TreeTraversalOptions, callback: (MoleculeModelProtocol)->Void) { func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, callback: (Int, MoleculeModelProtocol)->Void) {
forEach { (molecule) in forEach { (molecule) in
molecule.depthFirstTraverse(options: options, onVisit: callback) molecule.depthFirstTraverse(options: options, depth: depth, onVisit: callback)
} }
} }
} }

View File

@ -16,38 +16,39 @@ public protocol ParentMoleculeModelProtocol: MoleculeModelProtocol {
public extension ParentMoleculeModelProtocol { public extension ParentMoleculeModelProtocol {
func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol) -> Result) -> Result { func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int) -> Result) -> Result {
var result = initialResult var result = initialResult
if (options == .parentFirst) { if (options == .parentFirst) {
result = nextPartialResult(result, self) result = nextPartialResult(result, self, depth)
} }
result = children.reduce(result) { (result, molecule) -> Result in result = children.reduce(result) { (result, molecule) -> Result in
if let additionalParent = molecule as? ParentMoleculeModelProtocol { if let additionalParent = molecule as? ParentMoleculeModelProtocol {
// Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol. // Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol.
return additionalParent.reduceDepthFirstTraverse(options: options, initialResult: result, nextPartialResult: nextPartialResult) return additionalParent.reduceDepthFirstTraverse(options: options, depth: depth + 1, initialResult: result, nextPartialResult: nextPartialResult)
} }
return molecule.reduceDepthFirstTraverse(options: options, initialResult: result, nextPartialResult: nextPartialResult) return molecule.reduceDepthFirstTraverse(options: options, depth: depth + 1, initialResult: result, nextPartialResult: nextPartialResult)
} }
if (options == .childFirst) { if (options == .childFirst) {
result = nextPartialResult(result, self) result = nextPartialResult(result, self, depth)
} }
// if options == .leafOnly don't call on self. // if options == .leafOnly don't call on self.
return result return result
} }
func depthFirstTraverse(options: TreeTraversalOptions, onVisit: (MoleculeModelProtocol)->Void) { func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void) {
if (options == .parentFirst) { if (options == .parentFirst) {
onVisit(self) onVisit(depth, self)
} }
children.forEach { (molecule) in children.forEach { (molecule) in
if let additionalParent = molecule as? ParentMoleculeModelProtocol { if let additionalParent = molecule as? ParentMoleculeModelProtocol {
// Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol. // Safety net to make sure the ParentMoleculeModelProtocol's method extension is called over the base MoleculeModelProtocol.
additionalParent.depthFirstTraverse(options: options, onVisit: onVisit) additionalParent.depthFirstTraverse(options: options, depth: depth + 1, onVisit: onVisit)
} else {
molecule.depthFirstTraverse(options: options, depth: depth + 1, onVisit: onVisit)
} }
molecule.depthFirstTraverse(options: options, onVisit: onVisit)
} }
if (options == .childFirst) { if (options == .childFirst) {
onVisit(self) onVisit(depth, self)
} }
// if options == .leafOnly don't call on self. // if options == .leafOnly don't call on self.
} }

View File

@ -17,9 +17,9 @@ public protocol MoleculeTreeTraversalProtocol {
// Future options -- Parent first depth first, leaves only. // Future options -- Parent first depth first, leaves only.
func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol)->Result) -> Result func reduceDepthFirstTraverse<Result>(options: TreeTraversalOptions, depth: Int, initialResult: Result, nextPartialResult: (Result, MoleculeModelProtocol, Int)->Result) -> Result
func depthFirstTraverse(options: TreeTraversalOptions, onVisit: (MoleculeModelProtocol)->Void) func depthFirstTraverse(options: TreeTraversalOptions, depth: Int, onVisit: (Int, MoleculeModelProtocol)->Void)
//func breadthFirstTraverse() //func breadthFirstTraverse()
} }
@ -31,19 +31,19 @@ public protocol MoleculeTreeTraversalProtocol {
extension MoleculeTreeTraversalProtocol { extension MoleculeTreeTraversalProtocol {
func countMolecules(options: TreeTraversalOptions = .parentFirst) -> Int { func countMolecules(options: TreeTraversalOptions = .parentFirst) -> Int {
return reduceDepthFirstTraverse(options: options, initialResult: 0) { (accumulator, molecule) in return reduceDepthFirstTraverse(options: options, depth: 0, initialResult: 0) { (accumulator, molecule, depth) in
return accumulator + 1 return accumulator + 1
} }
} }
func printMolecules(options: TreeTraversalOptions = .parentFirst) { func printMolecules(options: TreeTraversalOptions = .parentFirst) {
depthFirstTraverse(options: options) { (molecule) in depthFirstTraverse(options: options, depth: 1) { (depth, molecule) in
print("\"\(molecule.moleculeName)\" [\(molecule)]") print("\(String(repeating: ">>", count: depth)) \"\(molecule.moleculeName)\" [\(molecule)]")
} }
} }
func allMoleculesOfType<T>(options: TreeTraversalOptions = .parentFirst) -> [T] { func allMoleculesOfType<T>(options: TreeTraversalOptions = .parentFirst) -> [T] {
return reduceDepthFirstTraverse(options: options, initialResult: []) { (accumulator, molecule) in return reduceDepthFirstTraverse(options: options, depth: 0, initialResult: []) { (accumulator, molecule, depth) in
if let typedMolecule = molecule as? T { if let typedMolecule = molecule as? T {
return accumulator + [typedMolecule] return accumulator + [typedMolecule]
} }