diff --git a/src/collection/__comm__/_str_hash.scad b/src/collection/__comm__/_str_hash.scad new file mode 100644 index 00000000..ab9fc52b --- /dev/null +++ b/src/collection/__comm__/_str_hash.scad @@ -0,0 +1,11 @@ +use <../../util/sum.scad>; + +function _str_hash(value) = + let( + s = str(value), + leng = len(s) + ) + sum([ + for(i = [0:leng - 1]) + ord(s[i]) * pow(31, leng - 1 - i) + ]); \ No newline at end of file diff --git a/src/collection/_impl/_hashset_impl.scad b/src/collection/_impl/_hashset_impl.scad new file mode 100644 index 00000000..627f804a --- /dev/null +++ b/src/collection/_impl/_hashset_impl.scad @@ -0,0 +1,23 @@ +use <../../util/slice.scad>; +use <../../util/some.scad>; + +function _hashset_add(set, elem, hash, eq) = + let( + idx = hash(elem) % len(set), + bucket = set[idx] + ) + len(bucket) == 0 ? concat(slice(set, 0, idx), [[elem]], slice(set, idx + 1)) : + some(bucket, function(e) eq(e, elem)) ? set : + concat( + slice(set, 0, idx), + [concat(bucket, [elem])], + slice(set, idx + 1) + ); + +function _hashset(elems, leng, buckets, hash, eq, i = 0) = + i == leng ? buckets : + _hashset(elems, leng, _hashset_add(buckets, elems[i], hash, eq), hash, eq, i + 1); + +function _find(lt, elem, eq, leng, i = 0) = + i == leng ? -1 : + eq(lt[i], elem) ? i : _find(lt, elem, eq, leng, i + 1); \ No newline at end of file diff --git a/src/collection/hashset.scad b/src/collection/hashset.scad index 16657040..04643ff8 100644 --- a/src/collection/hashset.scad +++ b/src/collection/hashset.scad @@ -1,21 +1,28 @@ -use <../util/sum.scad>; +use <__comm__/_str_hash.scad>; +use <_impl/_hashset_impl.scad>; use <../util/slice.scad>; use <../util/some.scad>; -function strhash(value) = - let( - s = str(value), - leng = len(s) - ) - sum([ - for(i = [0:leng - 1]) - ord(s[i]) * pow(31, leng - 1 - i) - ]); - -df_hash = function(e) strhash(e); +// public functions: hashset, hashset_has, hashset_add, hashset_del, hashset_list + +/* +use ; + +s = hashset([1, 2, 3, 4, 5, 2, 3, 5]); +echo(hashset_list(s)); +s2 = hashset_add(s, 9); +echo(hashset_list(s2)); + +echo(hashset_has(s2, 13)); + +echo(hashset_list(hashset_del(s2, 2))); +*/ + + +df_hash = function(e) _str_hash(e); df_eq = function(e1, e2) e1 == e2; -function hashset(elems, bucket_size = 16, hash = df_hash, eq = df_eq) = +function hashset(elems, hash = df_hash, eq = df_eq, bucket_size = 16) = let( elems_undef = is_undef(elems), size = elems_undef ? bucket_size : len(elems), @@ -23,26 +30,12 @@ function hashset(elems, bucket_size = 16, hash = df_hash, eq = df_eq) = ) elems_undef ? buckets : _hashset(elems, len(elems), buckets, hash, eq); - -function _hashset(elems, leng, buckets, hash, eq, i = 0) = - i == leng ? buckets : - _hashset(elems, leng, hashset_add(buckets, elems[i], hash, eq), hash, eq, i + 1); function hashset_has(set, elem, hash = df_hash, eq = df_eq) = some(set[hash(elem) % len(set)], function(e) eq(e, elem)); function hashset_add(set, elem, hash = df_hash, eq = df_eq) = - let( - idx = hash(elem) % len(set), - bucket = set[idx] - ) - len(bucket) == 0 ? concat(slice(set, 0, idx), [[elem]], slice(set, idx + 1)) : - some(bucket, function(e) eq(e, elem)) ? set : - concat( - slice(set, 0, idx), - [concat(bucket, [elem])], - slice(set, idx + 1) - ); + _hashset_add(set, elem, hash, eq); function hashset_del(set, elem, hash = df_hash, eq = df_eq) = let( @@ -59,10 +52,6 @@ function hashset_del(set, elem, hash = df_hash, eq = df_eq) = slice(set, bidx + 1) ); -function _find(lt, elem, eq, leng, i = 0) = - i == leng ? -1 : - eq(lt[i], elem) ? i : _find(lt, elem, eq, leng, i + 1); - function hashset_list(set) = [ for(bucket = set) for(elem = bucket)