func (sl *stringList) insert(i int, aString string) {
	sl.elements = append(sl.elements, "")
	copy(sl.elements[i+1:], sl.elements[i:])
	sl.elements[i] = aString
}
insert adds an element at the given index.
This method of insertion avoids creating a new slice, so garbage collection isn't involved.
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]
}
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
}
func (nl *nodeList) insert(i int, n *Node) {
	nl.elements = append(nl.elements, nil)
	copy(nl.elements[i+1:], nl.elements[i:])
	nl.elements[i] = n
}
func (nl *nodeList) push(n *Node) {
	nl.elements = append(nl.elements, n)
}
func (nl *nodeList) pop() *Node {
	size := len(nl.elements)
	if size == 0 {
		return nil
	}
	end := size - 1
	n := nl.elements[end]
	nl.elements[end] = nil
	nl.elements = nl.elements[0:end]
	return n
}
func (nl *nodeList) shift() *Node {
	if len(nl.elements) == 0 {
		return nil
	}
	n := nl.elements[0]
	nl.elements[0] = nil
	nl.elements = nl.elements[1:]
	return n
}
func (nl *nodeList) size() int {
	return len(nl.elements)
}
func (nl *nodeList) unshift(n *Node) {
	nl.insert(0, n)
}
type StringSet struct {
	members map[string]struct{}
}
func NewStringSet() *StringSet {
	return &StringSet{
		members: make(map[string]struct{}),
	}
}
func DecodeStringSet(blob []byte) (*StringSet, error) {
	ss := NewStringSet()
	buf := bytes.NewBuffer(blob)
	dec := gob.NewDecoder(buf)
	err := dec.Decode(&ss.members)
	if err != nil {
		return nil, err
	}
	return ss, nil
}
func (ss *StringSet) Add(aString string) {
	if ss.Contains(aString) {
		return
	}
	ss.members[aString] = keyExists
}
func (ss *StringSet) Remove(aString string) {
	delete(ss.members, aString)
}
func (ss *StringSet) Size() int {
	return len(ss.members)
}
func (ss *StringSet) Contains(aString string) bool {
	_, ok := ss.members[aString]
	return ok
}
func (ss *StringSet) Elements() []string {
	size := len(ss.members)
	members := make([]string, size, size)
	index := 0
	for k := range ss.members {
		members[index] = k
		index += 1
	}
	sort.Strings(members)
	return members
}
func (ss *StringSet) Difference(other *StringSet) *StringSet {
	diff := NewStringSet()
	if other == nil {
		for k := range ss.members {
			diff.Add(k)
		}
		return diff
	}
	for k := range ss.members {
		if !other.Contains(k) {
			diff.Add(k)
		}
	}
	return diff
}
func (ss *StringSet) Intersection(other *StringSet) *StringSet {
	intersection := NewStringSet()
	if other == nil {
		return intersection
	}
	for k := range ss.members {
		if other.Contains(k) {
			intersection.Add(k)
		}
	}
	return intersection
}
func (ss *StringSet) Encode() ([]byte, error) {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	err := enc.Encode(ss.members)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
type OrderedStringSet struct {
	members map[string]int
	order map[int]string
	counter int
}
func NewOrderedStringSet(members ...string) *OrderedStringSet {
	oss := OrderedStringSet{
		members: make(map[string]int),
		order: make(map[int]string),
		counter: 0,
	}
	for _, m := range members {
		oss.Add(m)
	}
	return &oss
}
func (oss *OrderedStringSet) Add(aString string) {
	if oss.Contains(aString) {
		return
	}
	oss.counter += 1
	oss.members[aString] = oss.counter
	oss.order[oss.counter] = aString
}
func (oss *OrderedStringSet) Clone() *OrderedStringSet {
	clone := NewOrderedStringSet()
	for _, k := range oss.Elements() {
		clone.Add(k)
	}
	return clone
}
func (oss *OrderedStringSet) Contains(aString string) bool {
	_, ok := oss.members[aString]
	return ok
}
func (oss *OrderedStringSet) Difference(setB *OrderedStringSet) *OrderedStringSet {
	diff := NewOrderedStringSet()
	if setB == nil {
		return oss.Clone()
	}
	for _, m := range oss.Elements() {
		if !setB.Contains(m) {
			diff.Add(m)
		}
	}
	return diff
}
func (oss *OrderedStringSet) Elements() []string {
	size := len(oss.order)
	var indices = make([]int, size, size)
	var order = make([]string, size, size)
	count := 0
	for index := range oss.order {
		indices[count] = index
		count += 1
	}
	sort.Ints(indices)
	count = 0
	for _, index := range indices {
		order[count] = oss.order[index]
		count += 1
	}
	return order
}
func (oss *OrderedStringSet) Intersection(setB *OrderedStringSet) *OrderedStringSet {
	intersection := NewOrderedStringSet()
	if setB == nil {
		return intersection
	}
	for _, m := range oss.Elements() {
		if setB.Contains(m) {
			intersection.Add(m)
		}
	}
	return intersection
}
func (oss *OrderedStringSet) Remove(aString string) {
	i, ok := oss.members[aString]
	if ok {
		delete(oss.order, i)
	}
	delete(oss.members, aString)
}
func (oss *OrderedStringSet) Size() int {
	return len(oss.members)
}
func (oss *OrderedStringSet) Subset(setB *OrderedStringSet) bool {
	for m := range oss.members {
		if _, ok := setB.members[m]; !ok {
			return false
		}
	}
	return true
}
func (oss *OrderedStringSet) Union(setB *OrderedStringSet) *OrderedStringSet {
	union := NewOrderedStringSet(oss.Elements()...)
	if setB == nil {
		return union
	}
	for _, m := range setB.Elements() {
		union.Add(m)
	}
	return union
}
type stringList struct {
	elements []string
}
func newStringList() *stringList {
	return &stringList{
		elements: make([]string, 0),
	}
}
func (sl *stringList) at(i int) (string, bool) {
	if i > len(sl.elements) - 1 || i < 0 {
		return "", false
	}
	return sl.elements[i], true
}
func (sl *stringList) delete(i int) (string, bool) {
	end := len(sl.elements) - 1
	if i > end || i < 0 {
		return "", false
	}
	e := sl.elements[i]
	copy(sl.elements[i:], sl.elements[i+1:])
	sl.elements[end] = ""
	sl.elements = sl.elements[:end]
	return e, true
}