I am trying to solve equivalent binary trees exercise on go tour. Here is what I did;
package main
import \"tour/tree\"
import \"fmt\"
// Walk walks the tr
because the question just said the tree just 10 nodes,then following is my answer after read other answers:
func Walk(t *tree.Tree, ch chan int) {
defer close(ch)
var walker func(t *tree.Tree)
walker = func(t *tree.Tree) {
if t == nil {
return
}
walker(t.Left)
ch <- t.Value
walker(t.Right)
}
walker(t)
}
func Same(t1, t2 *tree.Tree) bool {
ch1, ch2 := make(chan int), make(chan int)
go Walk(t1, ch1)
go Walk(t2, ch2)
for range make([]struct{}, 10) {
if <-ch1 != <-ch2 {
return false
}
}
return true
}
You got it almost right, there's no need to use the select
statement because you will go through the default
case too often, here's my solution that works without needing to count the number of nodes in the tress:
func Same(t1, t2 *tree.Tree) bool {
ch1, ch2 := make(chan int), make(chan int)
go Walk(t1, ch1)
go Walk(t2, ch2)
for i := range ch1 {
j, more := <-ch2
if more {
if i != j { return false }
} else { return false }
}
return true
}
Here's a solution that doesn't depend on differing tree lengths, neither does it depend on traversal order:
package main
import (
"fmt"
"golang.org/x/tour/tree"
)
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
var walk func(*tree.Tree)
walk = func(tr *tree.Tree) {
if tr == nil {
return
}
walk(tr.Left)
ch <- tr.Value
walk(tr.Right)
}
walk(t)
close(ch)
}
func merge(ch chan int, m map[int]int) {
for i := range ch {
count, ok := m[i]
if ok {
m[i] = count + 1
} else {
m[i] = 1
}
}
}
// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
ch1 := make(chan int, 100)
ch2 := make(chan int, 100)
m := make(map[int]int)
go Walk(t1, ch1)
go Walk(t2, ch2)
merge(ch1, m)
merge(ch2, m)
for _, count := range m {
if count != 2 {
return false
}
}
return true
}
Here's the solution I came up with :
func Walker(t *tree.Tree, ch chan int){
if t==nil {return}
Walker(t.Left,ch)
ch<-t.Value
Walker(t.Right,ch)
}
func Walk(t *tree.Tree, ch chan int){
Walker(t,ch)
close(ch)
}
func Same(t1, t2 *tree.Tree) bool{
ch:=make(chan int)
dh:=make(chan int)
go Walk(t1,ch)
go Walk(t2,dh)
for i:=range ch {
j,ok:=<-dh
if(i!=j||!ok) {return false}
}
return true
}
I wrote 2 versions that always read both channels to the end:
package main
import (
"fmt"
"golang.org/x/tour/tree"
)
func Walk(t *tree.Tree, ch chan int) {
var walker func(t *tree.Tree)
walker = func(t *tree.Tree) {
if t == nil {
return
}
walker(t.Left)
ch <- t.Value
walker(t.Right)
}
walker(t)
close(ch)
}
func Same(t1, t2 *tree.Tree, sameChan func(ch1, ch2 chan int) bool) bool {
ch1, ch2 := make(chan int), make(chan int)
go Walk(t1, ch1)
go Walk(t2, ch2)
return sameChan(ch1, ch2)
}
func sameChan1(ch1, ch2 chan int) bool {
areSame := true
for {
v1, ok1 := <-ch1
v2, ok2 := <-ch2
if !ok1 && !ok2 {
return areSame
}
if !ok1 || !ok2 || v1 != v2 {
areSame = false
}
}
}
func sameChan2(ch1, ch2 chan int) bool {
areSame := true
for v1 := range ch1 {
v2, ok2 := <-ch2
if !ok2 || v1 != v2 {
areSame = false
}
}
for _ = range ch2 {
areSame = false
}
return areSame
}
func main() {
fmt.Println(Same(tree.New(1), tree.New(1), sameChan1))
fmt.Println(Same(tree.New(2), tree.New(1), sameChan1))
fmt.Println(Same(tree.New(1), tree.New(2), sameChan1))
fmt.Println(Same(tree.New(1), tree.New(1), sameChan2))
fmt.Println(Same(tree.New(2), tree.New(1), sameChan2))
fmt.Println(Same(tree.New(1), tree.New(2), sameChan2))
}
package main
import (
"fmt"
"golang.org/x/tour/tree"
)
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
walkRecursive(t, ch)
close(ch)
}
func walkRecursive(t *tree.Tree, ch chan int) {
if t == nil {
return
}
walkRecursive(t.Left, ch)
ch <- t.Value
walkRecursive(t.Right, ch)
}
// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
ch1 := make(chan int)
ch2 := make(chan int)
go Walk(t1, ch1)
go Walk(t2, ch2)
for {
v1, ok1 := <-ch1
v2, ok2 := <-ch2
if ok1 != ok2 {
return false
}
if !ok1 {
return true
}
if v1 != v2 {
return false
}
}
}
func main() {
fmt.Println(Same(tree.New(1), tree.New(2)))
}