98 lines
2.5 KiB
GDScript
98 lines
2.5 KiB
GDScript
class_name Set extends BST._Node
|
|
|
|
var data: Variant
|
|
|
|
func _init(data: Variant = null) -> void:
|
|
super(_get_value(data))
|
|
self.data = data
|
|
|
|
static func _get_value(value: Variant) -> int:
|
|
match typeof(value):
|
|
TYPE_NIL: return -1
|
|
TYPE_INT: return value
|
|
_: return hash(value)
|
|
|
|
static func empty() -> Set:
|
|
return Set.new(null)
|
|
|
|
static func from_iter(iter: Variant) -> Set:
|
|
var nodes: Array[_Node] = []
|
|
for value in iter:
|
|
nodes.append(Set.new(value))
|
|
return BST._build_balanced_tree(nodes).unwrap()
|
|
|
|
static func compare(a: Set, b: Set) -> bool:
|
|
return a.data < b.data
|
|
|
|
func balance() -> Set:
|
|
var nodes = BST._store_in_order(Option.some(self))
|
|
nodes.sort_custom(compare)
|
|
return BST._build_balanced_tree(nodes).unwrap()
|
|
|
|
|
|
func is_empty() -> bool:
|
|
return value == -1 and not has_children()
|
|
|
|
func contains(data: Variant) -> bool:
|
|
return BST.search(self, _get_value(data)).is_some()
|
|
|
|
func insert(data: Variant) -> _Node:
|
|
if is_empty():
|
|
self.value = _get_value(data)
|
|
self.data = data
|
|
return self
|
|
elif not contains(data):
|
|
return BST._insert(Option.some(self), Set.new(data))
|
|
else:
|
|
return self
|
|
|
|
func remove(data: Variant) -> Option:
|
|
return BST.remove(self, _get_value(data))
|
|
|
|
func get(data: Variant) -> Option:
|
|
return BST.search(self, _get_value(data)).map(func(x: Set) -> Variant: return x.data)
|
|
|
|
func equals(other: Set) -> bool:
|
|
if not size() == other.size(): return false
|
|
|
|
for value in iter():
|
|
if not other.contains(value): return false
|
|
|
|
return true
|
|
|
|
func union(other: Set) -> Set:
|
|
var u = Set.from_iter(iter())
|
|
for value in other.iter():
|
|
u.insert(value)
|
|
return u.balance()
|
|
|
|
func intersect(other: Set) -> Set:
|
|
var i = Set.empty()
|
|
for value in iter():
|
|
if other.contains(value):
|
|
i.insert(value)
|
|
return i.balance()
|
|
|
|
func difference(other: Set) -> Set:
|
|
if self.is_empty(): return Set.empty()
|
|
elif other.is_empty(): return Set.from_iter(iter())
|
|
var diff = Set.empty()
|
|
for value in iter():
|
|
if not other.contains(value):
|
|
diff.insert(value)
|
|
return diff.balance()
|
|
|
|
static func _iter(_set: Set) -> Iterator:
|
|
var iters = Option.collect_some([
|
|
_set.left.map(_iter),
|
|
Option.none if _set.value == -1 else Option.some(SingletonIterator.new(_set.data)),
|
|
_set.right.map(_iter)
|
|
], true).unwrap()
|
|
|
|
var iter_arr: Array[Iterator]
|
|
iter_arr.assign(iters)
|
|
|
|
return FusedIterator.new(iter_arr)
|
|
|
|
func iter() -> Iterator:
|
|
return _iter(self)
|