Advertisement
Guest User

Untitled

a guest
Oct 22nd, 2017
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.98 KB | None | 0 0
  1. /*
  2. Kevin Koehler
  3. 1163209
  4. kak750
  5. CMPT 360 - Programming part of Midterm 1
  6. */
  7.  
  8. package main
  9.  
  10. import (
  11. "fmt"
  12. "os"
  13. "bufio"
  14. )
  15.  
  16. //checks error
  17. func check(e error) {
  18. if e != nil {
  19. panic(e)
  20. }
  21. }
  22.  
  23. //in this instance, a vertex has a weight (num phones)
  24. type Vertex struct {
  25. weight int
  26. id int
  27. neighbours []*Vertex
  28. }
  29.  
  30. //adjacency list implementation
  31. type Graph []*Vertex
  32.  
  33.  
  34. //tests that the graph constructed is properly written
  35. func testGraph(str []string, g Graph){
  36. var V, w1 int
  37. _, err := fmt.Sscanf(str[0], "%d", &V)
  38. check(err)
  39. _, err = fmt.Sscanf(str[1], "%d", &w1)
  40. check(err)
  41. if len(g)!=V {
  42. fmt.Println("test failed, graph wrong size")
  43. } else if g[0].weight != w1 {
  44. fmt.Println("test failed, vertex wrong weight")
  45. } else if len(g[0].neighbours) < 1 {
  46. fmt.Println("test failed, edges not working")
  47. }
  48. }
  49.  
  50. //creates a graph from a string read from stdin
  51. //returns a list of the leaves as well
  52. func readInput(str []string, ) (Graph, []*Vertex) {
  53. var numVertices int
  54. var sum int
  55. var g Graph
  56.  
  57. _, err := fmt.Sscanf(str[0], "%d", &numVertices)
  58. check(err)
  59. for i:=0; i<numVertices-1; i++ {
  60. var w int
  61. _, err = fmt.Sscanf(str[i+1], "%d", &w)
  62. check(err)
  63. sum+=w
  64. v := new(Vertex)
  65. v.id = i
  66. v.weight = w
  67. g = append(g, v)
  68. }
  69. v := new(Vertex)
  70. v.id = numVertices-1
  71. v.weight = numVertices - sum
  72. g = append(g, v)
  73.  
  74. for i:=0; i<numVertices-1; i++{
  75. var u, v int
  76. _, err = fmt.Sscanf(str[i+numVertices], "%d%d", &u, &v)
  77. check(err)
  78. g[u].neighbours = append(g[u].neighbours , g[v])
  79. g[v].neighbours = append(g[v].neighbours , g[u])
  80. }
  81. var leaves []*Vertex
  82. for i:= 0; i<len(g); i++{
  83. if len(g[i].neighbours) == 1 {
  84. leaves = append(leaves, g[i])
  85. }
  86. }
  87. return g, leaves
  88. }
  89.  
  90. var prevID = -1
  91.  
  92. //this needs to be done in O(log |V|) to fulfill assignment requirements
  93. //the general idea is this, select any arbitrary vertex of a tree,
  94. func findLeaf(lt []*Vertex) *Vertex {
  95. return lt[0]
  96. }
  97.  
  98. //returns the first neighbour of a leaf
  99. func findNeighbour(v *Vertex) *Vertex {
  100. return v.neighbours[0]
  101. }
  102.  
  103. //removes an index from a slice
  104. //fast method O(1)
  105. func RemoveIndex(s []*Vertex, i int) []*Vertex {
  106. s[len(s)-1], s[i] = s[i], s[len(s)-1]
  107. return s[:len(s)-1]
  108. }
  109.  
  110. //deletes a vertex l from another vertex n's adjacency list
  111. func deleteFromNeighbour(n *Vertex, l *Vertex) *Vertex{
  112. for i:=0; i<len(n.neighbours); i++ {
  113. if n.neighbours[i].id == l.id {
  114. n.neighbours = RemoveIndex(n.neighbours, i)
  115. }
  116. }
  117. return n
  118. }
  119.  
  120. //function safely removes a leaf
  121. func removeLeaf(v *Vertex, lt []*Vertex) []*Vertex {
  122. lt = RemoveIndex(lt, 0)
  123. leafNeighbour := findNeighbour(v)
  124. deleteFromNeighbour(leafNeighbour, v)
  125. if len(leafNeighbour.neighbours) == 1 {
  126. lt = append(lt, leafNeighbour)
  127. }
  128. return lt
  129. }
  130.  
  131. //abs val of int
  132. func intAbs(i int) int{
  133. if i < 0 { return (-1)*i } else { return i }
  134. }
  135.  
  136. //function containing the actual algorithm
  137. func calculateNumShipments(lt []*Vertex) int {
  138. counter := 0
  139. for len(lt) > 1 { //nontrivial
  140. l := findLeaf(lt)
  141. m := findNeighbour(l)
  142. xfer := l.weight - 1
  143. counter = counter + intAbs(xfer)
  144. m.weight = m.weight + xfer
  145. lt = removeLeaf(l, lt)
  146. }
  147. return counter
  148. }
  149.  
  150. //main function, entry point
  151. //program example usage: progName < test > output
  152. func main(){
  153. scanner := bufio.NewScanner(os.Stdin)
  154. scanner.Split(bufio.ScanLines)
  155. strs := []string{}
  156. for scanner.Scan(){
  157. strs = append(strs, scanner.Text())
  158. }
  159. g, lt := readInput(strs)
  160. testGraph(strs, g)
  161.  
  162. v := findLeaf(lt)
  163. if len(v.neighbours) != 1 {
  164. fmt.Println("error, leaf found with neighbours != 1, id: ", v.id, " num neighbours: ", len(v.neighbours))
  165. }
  166. m := findNeighbour(v)
  167. if(v.neighbours[0].id != m.id){
  168. fmt.Println("error, leaf found wrong neighbour")
  169. }
  170.  
  171. if len(lt[0].neighbours) != 1 {
  172. fmt.Println("error, no leaf in non-trivial tree")
  173. }
  174.  
  175. numShipments := calculateNumShipments(lt)
  176. fmt.Println(numShipments)
  177. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement