func TopoSpec(c gospec.Context) { c.Specify("Check toposort on linked list", func() { a := adag{ []int{1}, []int{2}, []int{3}, []int{4}, []int{5}, []int{6}, []int{}, } order := algorithm.TopoSort(a) checkOrder(c, a, order) }) c.Specify("multi-edges don't mess up toposort", func() { a := adag{ []int{1, 1, 1}, []int{}, } order := algorithm.TopoSort(a) checkOrder(c, a, order) }) c.Specify("Check toposort on a more complicated digraph", func() { a := adag{ []int{8, 7, 4}, // 0 []int{5}, []int{0}, []int{9}, []int{14}, []int{15}, // 5 []int{1}, []int{}, []int{}, []int{13}, []int{3}, // 10 []int{12}, []int{18}, []int{16}, []int{}, []int{14}, // 15 []int{}, []int{}, []int{}, []int{}, []int{}, } order := algorithm.TopoSort(a) checkOrder(c, a, order) }) c.Specify("A cyclic digraph returns nil", func() { a := adag{ []int{8, 7, 4}, // 0 []int{5}, []int{0}, []int{9}, []int{14}, []int{15}, // 5 []int{1}, []int{}, []int{20}, []int{13}, []int{3}, // 10 []int{12}, []int{18}, []int{16}, []int{2}, []int{14}, // 15 []int{6}, []int{}, []int{}, []int{}, []int{}, } order := algorithm.TopoSort(a) c.Expect(len(order), Equals, 0) }) }
func order(input []RectObject) []int { defer func() { if err := recover(); err != nil { base.Error().Printf("Failure in sorting: %v", err) } }() var minx, miny int for _, r := range input { x, y := r.Pos() if x < minx { minx = x } if y < miny { miny = y } } ra := make([]RectObject, len(input)) for i, r := range input { x, y := r.Pos() dx, dy := r.Dims() ra[i] = arog{x - minx + 1, y - miny + 1, dx, dy} } mapping := make(map[RectObject]int, len(ra)) for i := range ra { mapping[ra[i]] = i } var e endpointArray for i := range ra { e = append(e, endpoint{RectObject: ra[i], first: false}) e = append(e, endpoint{RectObject: ra[i], first: true}) } sort.Sort(e) var sweep_pos int less_func := func(_a, _b interface{}) bool { a := _a.(RectObject) b := _b.(RectObject) ax, ay, ax2, ay2 := firstAndLastPoints(a) da := ax*ax + ay*ay da2 := ax2*ax2 + ay2*ay2 w_a := width(a.Dims()) bx, by, bx2, by2 := firstAndLastPoints(b) db := bx*bx + by*by db2 := bx2*bx2 + by2*by2 w_b := width(b.Dims()) va := w_b * (w_a*da + (da2-da)*(sweep_pos-pos(ax, ay))) vb := w_a * (w_b*db + (db2-db)*(sweep_pos-pos(bx, by))) return va < vb } l := llrb.New(less_func) dag := make(adag, len(ra)) for _, p := range e { if p.first { sweep_pos = pos(firstPoint(p.RectObject)) l.ReplaceOrInsert(p.RectObject) lower := l.LowerBound(p.RectObject) upper := l.UpperBound(p.RectObject) if lower != nil { index := mapping[lower.(RectObject)] dag[index] = append(dag[index], mapping[p.RectObject]) } if upper != nil { index := mapping[p.RectObject] dag[index] = append(dag[index], mapping[upper.(RectObject)]) } } else { l.Delete(p.RectObject) } } return algorithm.TopoSort(dag) }