From c66b22bb2c3934786dd986f81ec20ad7f5801df5 Mon Sep 17 00:00:00 2001 From: Justin Lin Date: Thu, 4 Mar 2021 17:14:39 +0800 Subject: [PATCH] add hashset --- src/collection/hashset.scad | 72 +++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/collection/hashset.scad diff --git a/src/collection/hashset.scad b/src/collection/hashset.scad new file mode 100644 index 00000000..b88d5774 --- /dev/null +++ b/src/collection/hashset.scad @@ -0,0 +1,72 @@ +use <../util/sum.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); +df_eq = function(e1, e2) e1 == e2; + +function hashset(elems, bucket_size = 16, hash = df_hash, eq = df_eq) = + let( + elems_undef = is_undef(elems), + size = elems_undef ? bucket_size : len(elems), + buckets = [for(i = [0:bucket_size - 1]) []] + ) + 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) + ); + +function hashset_del(set, elem, hash = df_hash, eq = df_eq) = + let( + bidx = hash(elem) % len(set), + bucket = set[bidx], + leng = len(bucket) + ) + leng == 0 ? set : + let(i = _find(bucket, elem, eq, leng), _ = echo(i)) + i == -1 ? set : + concat( + slice(set, 0, bidx), + [concat(slice(bucket, 0, i), slice(bucket, i + 1))], + 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) + elem +]; \ No newline at end of file