Graph traversal without creating additional data structures
struct Person {
name : String
children : Array[Person]
mut father : Person?
mut mother : Person?
mut visit : Bool
}
///|
fn Person::new(name : String) -> Person {
// init `visit` to false
{ name, father: None, mother: None, children: [], visit: false }
}
fn Person::set_father(self : Person, father : Person) -> Unit {
guard self.father is None
self.father = Some(father)
father.children.push(self)
}
fn Person::set_mother(self : Person, mother : Person) -> Unit {
guard self.mother is None
self.mother = Some(mother)
mother.children.push(self)
}impl Node for Person with set_will_visit(self, bool) {
self.visit = bool
}
impl Node for Person with will_visit(self) {
self.visit
}
impl Node for Person with each_nexts(self, f) {
self.children.each(f)
if self.mother is Some(p) {
f(p)
}
if self.father is Some(p) {
f(p)
}
}test {
let grandpa = Person::new("Grandpa")
let grandma = Person::new("Grandma")
let father = Person::new("Father")
let mother = Person::new("Mother")
for x in [1, 2, 3] {
let child = Person::new("Child \{x}")
child.set_father(father)
child.set_mother(mother)
}
father.set_father(grandpa)
father.set_mother(grandma)
// traverse the graph, using `for ... in bfs_at(start_node)`
let visited = []
for p in bfs_at(father) {
visited.push(p)
if p.name is "Child 3" {
break
}
}
inspect(
visited.map(p => p.name),
content=(
#|["Father", "Child 1", "Child 2", "Child 3"]
),
)
// If you need to traverse the graph again, remember to reset the `visit` field.
visited.each(p => p.visit = false)
// traverse the graph, using `bfs_at(start_node).each()`
let visited_by_iter = []
bfs_at(father).each(visited_by_iter.push(_))
inspect(
visited_by_iter.map(p => p.name),
content=(
#|["Father", "Child 1", "Child 2", "Child 3", "Grandma", "Grandpa", "Mother"]
),
)
}struct Person {
name : String
children : Array[Person]
mut father : Person?
mut mother : Person?
mut visit : Bool
}
///|
fn Person::new(name : String) -> Person {
// init `visit` to false
{ name, father: None, mother: None, children: [], visit: false }
}
fn Person::set_father(self : Person, father : Person) -> Unit {
guard self.father is None
self.father = Some(father)
father.children.push(self)
}
fn Person::set_mother(self : Person, mother : Person) -> Unit {
guard self.mother is None
self.mother = Some(mother)
mother.children.push(self)
}impl Node for Person with set_will_visit(self, bool) {
self.visit = bool
}
impl Node for Person with will_visit(self) {
self.visit
}
impl Node for Person with each_nexts(self, f) {
self.children.each(f)
if self.mother is Some(p) {
f(p)
}
if self.father is Some(p) {
f(p)
}
}test {
let grandpa = Person::new("Grandpa")
let grandma = Person::new("Grandma")
let father = Person::new("Father")
let mother = Person::new("Mother")
for x in [1, 2, 3] {
let child = Person::new("Child \{x}")
child.set_father(father)
child.set_mother(mother)
}
father.set_father(grandpa)
father.set_mother(grandma)
// traverse the graph, using `for ... in bfs_at(start_node)`
let visited = []
for p in bfs_at(father) {
visited.push(p)
if p.name is "Child 3" {
break
}
}
inspect(
visited.map(p => p.name),
content=(
#|["Father", "Child 1", "Child 2", "Child 3"]
),
)
// If you need to traverse the graph again, remember to reset the `visit` field.
visited.each(p => p.visit = false)
// traverse the graph, using `bfs_at(start_node).each()`
let visited_by_iter = []
bfs_at(father).each(visited_by_iter.push(_))
inspect(
visited_by_iter.map(p => p.name),
content=(
#|["Father", "Child 1", "Child 2", "Child 3", "Grandma", "Grandpa", "Mother"]
),
)
}pub(open) trait Node {
each_nexts(Self, (Self) -> Unit) -> Unit
will_visit(Self) -> Bool
set_will_visit(Self, Bool) -> Unit
}type BfsAt[A]type DfsAt[A]Graph traversal without creating additional data structures