Guest User

Untitled

a guest
Dec 13th, 2017
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.30 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. )
  6.  
  7. type Label int
  8.  
  9. type Pos struct {
  10. x, y int
  11. }
  12.  
  13. type DisjointSets struct {
  14. parents map[Pos]Pos
  15. rank map[Pos]int
  16. labels map[Pos]Label
  17. }
  18.  
  19. func NewDisjointSets() *DisjointSets {
  20. return &DisjointSets{
  21. parents: make(map[Pos]Pos),
  22. rank: make(map[Pos]int),
  23. labels: make(map[Pos]Label),
  24. }
  25. }
  26.  
  27. func (s *DisjointSets) MakeSet(u Pos, label Label) {
  28. // ignore if set already exists
  29. if _, ok := s.parents[u]; ok {
  30. return
  31. }
  32.  
  33. s.labels[u] = label
  34. s.parents[u] = u
  35. s.rank[u] = 1
  36. }
  37.  
  38. func (s *DisjointSets) FindSet(u Pos) Pos {
  39. assertExists(s.parents, u)
  40.  
  41. var path []Pos
  42.  
  43. n := u
  44.  
  45. for {
  46. if s.parents[n] == n {
  47. break
  48. }
  49.  
  50. path = append(path, n)
  51. n = s.parents[n]
  52. }
  53.  
  54. // path compression
  55. for _, p := range path {
  56. s.parents[p] = n
  57. }
  58.  
  59. return n
  60. }
  61.  
  62. func (s *DisjointSets) Label(u Pos) Label {
  63. assertExists(s.parents, u)
  64.  
  65. parent := s.FindSet(u)
  66. return s.labels[parent]
  67. }
  68.  
  69. func (s *DisjointSets) union(u, v Pos) {
  70. assertExists(s.parents, u, v)
  71.  
  72. uParent := s.FindSet(u)
  73. vParent := s.FindSet(v)
  74.  
  75. // already in the same set
  76. if uParent == vParent {
  77. return
  78. }
  79.  
  80. uLabel := s.Label(u)
  81. vLabel := s.Label(v)
  82.  
  83. label := minLabel(uLabel, vLabel)
  84.  
  85. if s.rank[uParent] == s.rank[vParent] {
  86. s.rank[uParent]++
  87. s.parents[vParent] = uParent
  88. s.labels[uParent] = label
  89. } else if s.rank[uParent] > s.rank[vParent] {
  90. s.parents[vParent] = uParent
  91. s.labels[uParent] = label
  92. } else {
  93. s.parents[uParent] = vParent
  94. s.labels[vParent] = label
  95. }
  96. }
  97.  
  98. func (s *DisjointSets) SameComponent(u, v Pos) bool {
  99. assertExists(s.parents, u, v)
  100.  
  101. return s.FindSet(u) == s.FindSet(v)
  102. }
  103.  
  104. func (s *DisjointSets) Dump() {
  105. fmt.Println("====================")
  106.  
  107. for u, parent := range s.parents {
  108. fmt.Printf(
  109. "(%d,%d) parent: (%d,%d) label %dn",
  110. u.x,
  111. u.y,
  112. parent.x,
  113. parent.y,
  114. s.Label(u),
  115. )
  116. }
  117. }
  118.  
  119. func minLabel(labels ...Label) Label {
  120. if len(labels) == 0 {
  121. panic("len(labels) must be >= 0")
  122. }
  123.  
  124. var min = labels[0]
  125.  
  126. for _, label := range labels {
  127. if label < min {
  128. min = label
  129. }
  130. }
  131.  
  132. return min
  133. }
  134.  
  135. func assertExists(parents map[Pos]Pos, check ...Pos) {
  136. for _, u := range check {
  137. if _, ok := parents[u]; !ok {
  138. panic(fmt.Sprintf("Pos (%d,%d) is not a known set.", u.x, u.y))
  139. }
  140. }
  141. }
  142.  
  143. func main() {
  144. sets := NewDisjointSets()
  145.  
  146. sets.MakeSet(Pos{0, 0}, 1)
  147. sets.MakeSet(Pos{1, 0}, 2)
  148. sets.MakeSet(Pos{2, 0}, 2)
  149.  
  150. sets.MakeSet(Pos{0, 1}, 1)
  151. sets.MakeSet(Pos{1, 1}, 3)
  152. sets.MakeSet(Pos{2, 1}, 2)
  153.  
  154. sets.MakeSet(Pos{0, 2}, 3)
  155. sets.MakeSet(Pos{1, 2}, 3)
  156. sets.MakeSet(Pos{2, 2}, 4)
  157.  
  158. sets.Dump()
  159.  
  160. sets.union(Pos{0, 0}, Pos{1, 0})
  161. sets.union(Pos{0, 0}, Pos{1, 1})
  162.  
  163. sets.Dump()
  164.  
  165. fmt.Printf("%#vn", sets.SameComponent(Pos{1, 1}, Pos{2, 2}))
  166. fmt.Printf("%#vn", sets.SameComponent(Pos{1, 1}, Pos{0, 0}))
  167. fmt.Printf("%#vn", sets.SameComponent(Pos{0, 2}, Pos{0, 2}))
  168.  
  169. sets.union(Pos{1, 1}, Pos{1, 1})
  170.  
  171. sets.Dump()
  172.  
  173. sets.union(Pos{1, 1}, Pos{2, 2})
  174.  
  175. sets.Dump()
  176. }
Add Comment
Please, Sign In to add comment