func (nl *nodeList) delete(i int) *Node {
	end := len(nl.elements) - 1
	n := nl.elements[i]
	copy(nl.elements[i:], nl.elements[i+1:])
	nl.elements[end] = nil
	nl.elements = nl.elements[:end]
	return n
}
delete removes a node at the given index, and returns it
package phantom
import (
	"bytes"
	"encoding/gob"
	"sort"
)
type nodeSet struct {
	nodes map[*Node]struct{}
}
func newNodeSet() *nodeSet {
	return &nodeSet{
		nodes: make(map[*Node]struct{}),
	}
}
func (nset *nodeSet) size() int {
	return len(nset.nodes)
}
func (nset *nodeSet) add(node *Node) {
	if node == nil {
		return
	}
	if nset.contains(node) {
		return
	}
	nset.nodes[node] = keyExists
}
func (nset *nodeSet) remove(node *Node) {
	delete(nset.nodes, node)
}
func (nset *nodeSet) elements() []*Node {
	nodes := make([]*Node, len(nset.nodes))
	index := 0
	for k := range nset.nodes {
		nodes[index] = k
		index += 1
	}
	sort.Slice(nodes, func(i, j int) bool {
		if nodes[i].GetId() < nodes[j].GetId() {
			return true
		} else {
			return false
		}
	})
	return nodes
}
func (nset *nodeSet) contains(node *Node) bool {
	_, ok := nset.nodes[node]
	return ok
}
func (nset *nodeSet) difference(nset2 *nodeSet) *nodeSet {
	diff := newNodeSet()
	if nset2 == nil {
		return diff
	}
	for k := range nset.nodes {
		if !nset2.contains(k) {
			diff.add(k)
		}
	}
	return diff
}
func (nset *nodeSet) intersection(nset2 *nodeSet) *nodeSet {
	intersection := newNodeSet()
	if nset2 == nil {
		return intersection
	}
	for k := range nset.nodes {
		if nset2.contains(k) {
			intersection.add(k)
		}
	}
	return intersection
}
func (nset *nodeSet) clone() *nodeSet {
	clone := newNodeSet()
	for k := range nset.nodes {
		clone.add(k)
	}
	return clone
}
type orderedNodeSet struct {
	nodes map[*Node]int
	order map[int]*Node
	counter int
}
func newOrderedNodeSet() *orderedNodeSet {
	return &orderedNodeSet {
		nodes: make(map[*Node]int),
		order: make(map[int]*Node),
		counter: 0,
	}
}
func (ons *orderedNodeSet) add(node *Node) {
	if node == nil {
		return
	}
	if ons.contains(node) {
		return
	}
	ons.counter += 1
	ons.nodes[node] = ons.counter
	ons.order[ons.counter] = node
}
func (ons *orderedNodeSet) clone() *orderedNodeSet {
	clone := newOrderedNodeSet()
	for _, k := range ons.elements() {
		clone.add(k)
	}
	return clone
}
func (ons *orderedNodeSet) contains(node *Node) bool {
	_, ok := ons.nodes[node]
	return ok
}
func (ons *orderedNodeSet) difference(ons2 *orderedNodeSet) *orderedNodeSet {
	diff := newOrderedNodeSet()
	if ons2 == nil {
		return ons.clone()
	}
	for _, k := range ons.elements() {
		if !ons2.contains(k){
			diff.add(k)
		}
	}
	return diff
}
func (ons *orderedNodeSet) elements() []*Node {
	var indexes = make([]int, 0, len(ons.order))
	var nodes = make([]*Node, 0, len(ons.order))
	for k := range ons.order {
		indexes = append(indexes, k)
	}
	sort.Ints(indexes)
	for _, v := range indexes {
		nodes = append(nodes, ons.order[v])
	}
	return nodes
}
func (ons *orderedNodeSet) intersection(ons2 *orderedNodeSet) *orderedNodeSet {
	intersection := newOrderedNodeSet()
	if ons2 == nil {
		return intersection
	}
	for _, k := range ons.elements() {
		if ons2.contains(k) {
			intersection.add(k)
		}
	}
	return intersection
}
func (ons *orderedNodeSet) remove(node *Node) {
	if node == nil {
		return
	}
	i, ok := ons.nodes[node]
	if ok {
		delete(ons.order, i)
	}
	delete(ons.nodes, node)
}
func (ons *orderedNodeSet) size() int {
	return len(ons.nodes)
}
type nodeList struct {
	elements []*Node
}
func newNodeList(cap int) *nodeList {
	return &nodeList{
		elements: make([]*Node, 0, cap),
	}
}
func (nl *nodeList) at(i int) *Node {
	if i > len(nl.elements) - 1 || i < 0 {
		return nil
	}
	return nl.elements[i]
}