From ef1dff3ccd536cda7d75e4316bcec79cba9cc475 Mon Sep 17 00:00:00 2001 From: Denise Date: Tue, 7 Apr 2026 20:25:27 +0200 Subject: [PATCH] Added Set collections (Sparse Set). --- modules/std/collections/set.wx | 414 +++++++++++++++++++++++++++++++++ modules/std/std.wx | 2 + 2 files changed, 416 insertions(+) create mode 100644 modules/std/collections/set.wx diff --git a/modules/std/collections/set.wx b/modules/std/collections/set.wx new file mode 100644 index 00000000..0a5f53a4 --- /dev/null +++ b/modules/std/collections/set.wx @@ -0,0 +1,414 @@ + +Namespace std.collections + +#rem wonkeydoc Convenience type alias for Set\. +#end +Alias UIntSet:Set + +#rem wonkeydoc The Set class provides support for Sparse Set. +A Set is an efficient data structure for storing sets of small integers from a large universe, guaranteeing constant-time insertion, deletion, and search operations. +Set implement the [[IContainer]] interface so can be used with Eachin loops. +#end +Class Set Implements IContainer Where T=ULong Or T=UInt Or T=UShort Or T=UByte + + #rem wonkeydoc The Set.Iterator struct. + #end + Struct Iterator + + Private + + Field _set:Set + Field _index:Int + + Method AssertCurrent() + DebugAssert( _index < _set._n, "Invalid Set iterator" ) + End + + Method New( set:Set, index:Int ) + _set = set + _index = index + End + + Public + + #rem wonkeydoc Checks if the iterator has reached the end of the Set. + #end + Property AtEnd:Bool() + Return _index >= _set._n + End + + #rem wonkeydoc The value currently pointed to by the iterator. + #end + Property Current:T() + AssertCurrent() + Return _set._dense[_index] + Setter( current:T ) + AssertCurrent() + _set._dense[_index] = current + End + + #rem wonkeydoc Bumps the iterator so it points to the next value in the Set. + #end + Method Bump() + AssertCurrent() + _index += 1 + End + + #rem wonkeydoc Safely erases the value pointed to by the iterator. + After calling this method, the iterator will point to the value after the removed value. + Therefore, if you are manually iterating through a stack you should not call [[Bump]] after calling this method or you will end up skipping a value. + #end + Method Erase() + ' AssertCurrent() + ' _set.Erase( _index ) + End + + #rem wonkeydoc Safely inserts a value before the value pointed to by the iterator. + After calling this method, the iterator will point to the newly added value. + #end + Method Insert( value:T ) + ' DebugAssert( _index <= _set.n,"Invalid set iterator" ) + ' _set.Insert( _index, value ) + End + End + + #rem wonkeydoc The Set.BackwardsIterator struct. + #end + Struct BackwardsIterator + + Private + + Field _set:Set + Field _index:Int + + Method AssertCurrent() + DebugAssert( _index >= 0, "Invalid Set iterator" ) + End + + Method New( set:Set, index:Int ) + _set = set + _index = index + End + + Public + + #rem wonkeydoc Checks if the iterator has reached the end of the Set. + #end + Property AtEnd:Bool() + Return _index = -1 + End + + #rem wonkeydoc The value currently pointed to by the iterator. + #end + Property Current:T() + AssertCurrent() + Return _set._dense[_index] + Setter( current:T ) + AssertCurrent() + _set._dense[_index] = current + End + + #rem wonkeydoc Bumps the iterator so it points to the next value in the Set. + #end + Method Bump() + AssertCurrent() + _index -= 1 + End + + #rem wonkeydoc Safely erases the value pointed to by the iterator. + After calling this method, the iterator will point to the value after the removed value. + Therefore, if you are manually iterating through a stack you should not call [[Bump]] after calling this method or you + will end up skipping a value. + #end + Method Erase() + ' AssertCurrent() + ' _set.Erase( _index ) + ' _index -= 1 + End + + #rem wonkeydoc Safely inserts a value before the value pointed to by the iterator. + After calling this method, the iterator will point to the newly added value. + #end + Method Insert( value:T ) + ' DebugAssert( _index < _set.n, "Invalid set iterator" ) + ' _index += 1 + ' _set.Insert( _index, value ) + End + End + + Private + + Field _sparse:T[] + Field _dense:T[] + Field _maxValue:T + Field _capacity:Int + Field _n:Int + + Public + + '------------- IContainer ------------- + + #rem wonkeydoc Checks if the Set is empty. + @return True if the set is empty. + #end + Property Empty:Bool() + Return _n = 0 + End + + Property First:T() + Return Self.Empty ? Null Else _dense[0] + End + + Property Last:T() + Return Self.Empty ? Null Else _dense[_n - 1] + End + + Property Length:Int() + Return _n + End + + #rem wonkeydoc Gets an iterator for visiting Set values. + Returns an iterator suitable for use with Eachin, or for manual iteration. + @return A set iterator. + #end + Method All:Iterator() + Return New Iterator( Self, 0 ) + End + + #rem wonkeydoc Gets an iterator for visiting Set values in reverse order. + Returns an iterator suitable for use with Eachin, or for manual iteration. + @return A backwards set iterator. + #end + Method Backwards:BackwardsIterator() + Return New BackwardsIterator( Self, _n - 1 ) + End + + #rem wonkeydoc Creates a new Set. + New() creates an empty default Set. + New( MaxValue:T, Capacity:Int ) creates a Set. + New( values:T[], MaxValue:T, Capacity:Int ) creates a Set with the contents of an array. + New( values:List, MaxValue:T, Capacity:Int ) creates a Set with the contents of a list. + New( values:Deque, MaxValue:T, Capacity:Int ) create a Set with the contents of a deque. + New( values:Stack, MaxValue:T, Capacity:Int ) create a Set with the contents of a stack. + New( values:Set, MaxValue:T, Capacity:Int ) create a Set with the contents of a set. + @param MaxValue The Highest value. + @param Capacity The Capacity of the Set. + #end + Method New( _maxV:T = 512, _cap:Int = 64 ) + + _sparse = New T[_maxV + 1] + _dense = New T[_cap] + _capacity = _cap + _maxValue = _maxV + _n = 0 + End + + Method New( values:T[], _maxV:T = 512, _cap:Int = 64 ) + + _sparse = New T[_maxV + 1] + _dense = New T[_cap] + _capacity = _cap + _maxValue = _maxV + _n = 0 + AddAll( values ) + End + + Method New( values:List, _maxV:T = 512, _cap:Int = 64 ) + + _sparse = New T[_maxV + 1] + _dense = New T[_cap] + _capacity = _cap + _maxValue = _maxV + _n = 0 + AddAll( values ) + End + +' Method New( values:Deque, _maxV:T = 512, _cap:Int = 64 ) +' +' _sparse = New T[_maxV + 1] +' _dense = New T[_cap] +' _capacity = _cap +' _maxValue = _maxV +' _n = 0 +' AddAll( values ) +' End + + Method New( values:Stack, _maxV:T = 512, _cap:Int = 64 ) + + _sparse = New T[_maxV + 1] + _dense = New T[_cap] + _capacity = _cap + _maxValue = _maxV + _n = 0 + AddAll( values ) + End + + Method New( values:Set, _maxV:T = 512, _cap:Int = 64 ) + + _sparse = New T[_maxV + 1] + _dense = New T[_cap] + _capacity = _cap + _maxValue = _maxV + _n = 0 + AddAll( values ) + End + + #rem wonkeydoc Add a new value to Set, if the value is not in the Set. + @param value The value to add. + #end + Method Add( value:T ) + + If value > _maxValue Return + If _n >= _capacity Return + If Contains( value ) Return + + _dense[_n] = value + _sparse[value] = _n + _n += 1 + End + + #rem wonkeydoc Adds the values in an array or container to the Set. + @param values The values to add. + #end + Method AddAll( values:T[] ) + For Local value := Eachin values + Add( value ) + Next + End + + Method AddAll( values:C ) Where C Implements IContainer + For Local value := Eachin values + Add( value ) + Next + End + + #rem wonkeydoc Delete a value from the Set, if the value is in the Set. + @param value The value to remove. + @return True if the value was removed. + #end + Method Remove:Bool( value:T ) + + If Not Contains( value ) Return False + + Local tmp := _dense[_n - 1] + _dense[_sparse[value]] = tmp + _sparse[tmp] = _sparse[value] + _n -= 1 + Return True + End + + #rem wonkeydoc Checks if the Set contains a value. + @param value The value to check for. + @return True if the Set contains the value, else false. + #end + Method Contains:Bool( value:T ) + + If value > _maxValue Return False + If _sparse[value] < _n And _dense[_sparse[value]] = value Return True + Return False + End + + #rem wonkeydoc Clears the Set. + #end + Method Clear() + _n = 0 + End + + Operator To:String() + + Local res:="{ " + For Local i:=0 Until _n + If i > 0 res += ", " + res += _dense[i] + Next + Return res + " }" + End + + Operator+=( item:T ) + Add( item ) + End + + Operator+=( items:T[] ) + AddAll( items ) + End + + Operator+=( items:List ) + AddAll( items ) + End + + Operator+=( items:Stack ) + AddAll( items ) + End + + Operator+=( items:Set ) + AddAll( items ) + End + + Operator-=( item:T ) + Remove( item ) + End + +' Operator-=( items:T[] ) +' DelAll( items ) +' End + +' Operator-=( items:List ) +' DelAll( items ) +' End + +' Operator-=( items:Stack ) +' DelAll( items ) +' End + +' Operator-=( items:Set ) +' DelAll( items ) +' End + + #rem wonkeydoc returns the intersection of both sets. + #end + Method Intersection:Set( s:Set ) + + Local iCap := Min( _n, s._n ) + Local iMaxValue := Max( _maxValue, s._maxValue ) + Local r := New Set( iMaxValue, iCap ) + + If _n < s._n + For Local i := 0 Until _n + If s.Contains( _dense[i] ) + r.Add( _dense[i] ) + End + Next + Else + For Local i := 0 Until s._n + If Contains( s._dense[i] ) + r.Add( s._dense[i] ) + End + Next + End + + Return r + End + + #rem wonkeydoc returns the union of both sets. + #end + Method Union:Set( s:Set ) + + Local uCap := _n + s._n + Local uMaxValue := Max( _maxValue, s._maxValue ) + Local r := New Set( uMaxValue, uCap ) + + For Local i := 0 Until _n + r.Add( _dense[i] ) + Next + + For Local i := 0 Until s._n + r.Add( s._dense[i] ) + Next + Return r + End + + Method ToArray:T[]() + Return _dense.Slice( 0, _n ) + End + +End diff --git a/modules/std/std.wx b/modules/std/std.wx index ad09f5da..f24100d3 100644 --- a/modules/std/std.wx +++ b/modules/std/std.wx @@ -22,6 +22,8 @@ Namespace std #Import "collections/map" #Import "collections/deque" '#Import "collections/ring" +#Import "collections/set" +'Import "collections/hashset" #Import "resource/resource"