From 34d2b3031f56dc683dffb137efe5e585abb0c595 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Sat, 13 Apr 2024 14:56:54 +0200 Subject: [PATCH 01/14] Tree - WIP --- source/niknaks/containers.d | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index dd255bc..14d55d2 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -589,4 +589,18 @@ unittest // Destroy the map (such that it ends the sweeper destroy(map); +} + + +public class Tree(T) +{ + private T value; + private Tree!(T)[] children; + + this(T value) + { + this.value = value; + } + + public T[] dfs() } \ No newline at end of file From 60028a34be90a65099cd2fffa5baeb848c5d130a Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Mon, 22 Apr 2024 17:02:24 +0200 Subject: [PATCH 02/14] Tree - Added initial dfs --- source/niknaks/containers.d | 61 ++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 14d55d2..c168494 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -591,6 +591,32 @@ unittest destroy(map); } +// TODO: make delegate kak +// public interface InclusionStratergy(T) +// { +// public bool include(T item); +// } + +// private class AlwaysStrat(T) : InclusionStratergy +// { +// public override bool include(T item) +// { +// return true; +// } +// } + +public template Always(T) +{ + public bool always(T) + { + return true; + } +} + +public template InclusionStratergy(T) +{ + public alias InclusionStratergy = bool delegate(T item); +} public class Tree(T) { @@ -602,5 +628,38 @@ public class Tree(T) this.value = value; } - public T[] dfs() + public T[] dfs(InclusionStratergy!(T) strat) + { + T[] collected; + foreach(Tree!(T) child; this.children) + { + if(strat(child.value)) + { + collected ~= child.dfs(strat); + + } + } + + if(strat(this.value)) + { + collected ~= this.value; + } + + return collected; + } +} + + +version(unittest) +{ + import std.functional : toDelegate; + import std.stdio : writeln; +} + +unittest +{ + Tree!(string) treeOfStrings = new Tree!(string)("Top"); + + string[] result = treeOfStrings.dfs(toDelegate(&Always!(string).always)); + writeln("dfs: ", result); } \ No newline at end of file From 84f18407e866bdbdbb16eff996a5011b1c8c7bb7 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Mon, 22 Apr 2024 17:03:30 +0200 Subject: [PATCH 03/14] Tree - By default use the `always` strat --- source/niknaks/containers.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index c168494..53f2afe 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -628,7 +628,7 @@ public class Tree(T) this.value = value; } - public T[] dfs(InclusionStratergy!(T) strat) + public T[] dfs(InclusionStratergy!(T) strat = toDelegate(&Always!(T).always)) { T[] collected; foreach(Tree!(T) child; this.children) @@ -660,6 +660,6 @@ unittest { Tree!(string) treeOfStrings = new Tree!(string)("Top"); - string[] result = treeOfStrings.dfs(toDelegate(&Always!(string).always)); + string[] result = treeOfStrings.dfs(); writeln("dfs: ", result); } \ No newline at end of file From 4ecb57d4fa3576a9538282bca1fe9ebefc0ad0f1 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Mon, 22 Apr 2024 20:14:26 +0200 Subject: [PATCH 04/14] Tree - Added a TODO --- source/niknaks/containers.d | 1 + 1 file changed, 1 insertion(+) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 53f2afe..39ad66c 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -618,6 +618,7 @@ public template InclusionStratergy(T) public alias InclusionStratergy = bool delegate(T item); } +// TODO: Technically this is a graph public class Tree(T) { private T value; From d5b00c548e885ad0b4d0f78d61f5cc51a622b995 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Mon, 22 Apr 2024 20:18:50 +0200 Subject: [PATCH 05/14] Tree - Added ability to append Tree (unittests) - Updated unittests to test appending --- source/niknaks/containers.d | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 39ad66c..22cec7c 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -629,6 +629,16 @@ public class Tree(T) this.value = value; } + public void appendValue(T value) + { + + } + + public void appendNode(Tree!(T) node) + { + this.children ~= node; + } + public T[] dfs(InclusionStratergy!(T) strat = toDelegate(&Always!(T).always)) { T[] collected; @@ -661,6 +671,15 @@ unittest { Tree!(string) treeOfStrings = new Tree!(string)("Top"); + Tree!(string) subtree_1 = new Tree!(string)("1"); + Tree!(string) subtree_2 = new Tree!(string)("2"); + Tree!(string) subtree_3 = new Tree!(string)("3"); + + treeOfStrings.appendNode(subtree_1); + treeOfStrings.appendNode(subtree_2); + treeOfStrings.appendNode(subtree_3); + + string[] result = treeOfStrings.dfs(); writeln("dfs: ", result); } \ No newline at end of file From f49ecf190812e56134388e5cface8110dfcc15ce Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Mon, 22 Apr 2024 22:14:28 +0200 Subject: [PATCH 06/14] InclusionStratergy - Now uses the `TreeNode!(T)` instead of the `T` itself --- source/niknaks/containers.d | 59 ++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 22cec7c..5c13fdc 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -607,17 +607,38 @@ unittest public template Always(T) { - public bool always(T) + public bool Always(Tree!(T) treeNode) { + version(unittest) + { + import std.stdio : writeln; + writeln("Strat for: ", treeNode); + } return true; } } +public template Nothing(T) +{ + public void Nothing(Tree!(T) treeNode) + { + + } +} + public template InclusionStratergy(T) { - public alias InclusionStratergy = bool delegate(T item); + public alias InclusionStratergy = bool delegate(Tree!(T) item); } +// Called prior to visitation? +public template TouchStratergy(T) +{ + public alias TouchStratergy = void delegate(Tree!(T) item); +} + +import std.string : format; + // TODO: Technically this is a graph public class Tree(T) { @@ -639,25 +660,41 @@ public class Tree(T) this.children ~= node; } - public T[] dfs(InclusionStratergy!(T) strat = toDelegate(&Always!(T).always)) + public T[] dfs + ( + InclusionStratergy!(T) strat = toDelegate(&Always!(T)), + TouchStratergy!(T) touch = toDelegate(&Nothing!(T)) + ) { T[] collected; foreach(Tree!(T) child; this.children) { - if(strat(child.value)) + if(strat(child)) { + // Touch + touch(child); + + // Visit collected ~= child.dfs(strat); - } } - if(strat(this.value)) + if(strat(this)) { + // Touch + touch(this); + + // "Visit" collected ~= this.value; } return collected; } + + public override string toString() + { + return format("TreeNode [val: %s]", this.value); + } } @@ -665,6 +702,11 @@ version(unittest) { import std.functional : toDelegate; import std.stdio : writeln; + + private void DebugTouch(T)(Tree!(T) node) + { + writeln("Touching tree node ", node); + } } unittest @@ -680,6 +722,9 @@ unittest treeOfStrings.appendNode(subtree_3); - string[] result = treeOfStrings.dfs(); + InclusionStratergy!(string) strat = toDelegate(&Always!(string)); + TouchStratergy!(string) touch = toDelegate(&DebugTouch!(string)); + + string[] result = treeOfStrings.dfs(strat, touch); writeln("dfs: ", result); } \ No newline at end of file From 167c2b7c0de277dffdb7b4900a7c1403b95eb9bb Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Tue, 23 Apr 2024 15:49:49 +0200 Subject: [PATCH 07/14] VisitationTree - Working on a visitation tree implementation --- source/niknaks/containers.d | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 5c13fdc..518c943 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -727,4 +727,56 @@ unittest string[] result = treeOfStrings.dfs(strat, touch); writeln("dfs: ", result); +} + +public class VisitationTree(T) : Tree!(T) +{ + private bool visisted; + + this(T value) + { + super(value); + } + + public T[] linearize() + { + return dfs(toDelegate(&_shouldVisit), toDelegate(&_touch)); + } + + private static bool _shouldVisit(Tree!(T) tnode) + { + VisitationTree!(T) vnode = cast(VisitationTree!(T))tnode; + return vnode && !vnode.isVisited(); + } + + private static void _touch(Tree!(T) tnode) + { + VisitationTree!(T) vnode = cast(VisitationTree!(T))tnode; + if(vnode) + { + vnode.mark(); + } + } + + private void mark() + { + this.visisted = true; + } + + private bool isVisited() + { + return this.visisted; + } +} + +unittest +{ + VisitationTree!(string) root = new VisitationTree!(string)("root"); + + VisitationTree!(string) thing = new VisitationTree!(string)("subtree"); + root.appendNode(thing); + thing.appendNode(root); + + writeln(root.linearize()); + } \ No newline at end of file From 04edc241adb1635bf6de60b64d80c67e101a46c5 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Tue, 23 Apr 2024 15:52:02 +0200 Subject: [PATCH 08/14] Tree - Pass in, explcitly, the touch startergy --- source/niknaks/containers.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 518c943..7d7eee8 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -675,7 +675,7 @@ public class Tree(T) touch(child); // Visit - collected ~= child.dfs(strat); + collected ~= child.dfs(strat, touch); } } From ce78102af9943e823095f89fb717149eb1c6fea7 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Tue, 23 Apr 2024 16:02:40 +0200 Subject: [PATCH 09/14] Tree - Correct visitation stratergy --- source/niknaks/containers.d | 42 +++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 7d7eee8..20b128f 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -666,27 +666,47 @@ public class Tree(T) TouchStratergy!(T) touch = toDelegate(&Nothing!(T)) ) { + version(unittest) + { + writeln("dfs entry: ", this); + } + T[] collected; - foreach(Tree!(T) child; this.children) + scope(exit) + { + version(unittest) + { + writeln("leaving node ", this, " with collected ", collected); + } + } + + // Touch + touch(this); // root[x] + + foreach(Tree!(T) child; this.children) // subtree[x], { if(strat(child)) { - // Touch - touch(child); + version(unittest) + { + writeln("dfs, strat good for child: ", child); + } // Visit collected ~= child.dfs(strat, touch); } + else + { + version(unittest) + { + writeln("dfs, strat ignored for child: ", child); + } + } } - if(strat(this)) - { - // Touch - touch(this); - - // "Visit" - collected ~= this.value; - } + // "Visit" + collected ~= this.value; + return collected; } From e44caf3643a355d07dc1a3903c16c428fa85e89b Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Fri, 26 Apr 2024 15:35:29 +0200 Subject: [PATCH 10/14] VisitationTree (unittests) - Added missing assertions --- source/niknaks/containers.d | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 20b128f..05b6cee 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -797,6 +797,10 @@ unittest root.appendNode(thing); thing.appendNode(root); - writeln(root.linearize()); + string[] linearized = root.linearize(); + writeln(linearized); + + assert(linearized[0] == "subtree"); + assert(linearized[1] == "root"); } \ No newline at end of file From 838ddbb9db75e07f21201c5db9f6c603aadf7008 Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Fri, 26 Apr 2024 15:36:54 +0200 Subject: [PATCH 11/14] Tree (unittests) - Added missing assertions --- source/niknaks/containers.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 05b6cee..e0dbd26 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -747,6 +747,11 @@ unittest string[] result = treeOfStrings.dfs(strat, touch); writeln("dfs: ", result); + + assert(result[0] == "1"); + assert(result[1] == "2"); + assert(result[2] == "3"); + assert(result[3] == "Top"); } public class VisitationTree(T) : Tree!(T) From 41ebad076802aca2d1a8ae83b26530c06913b428 Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Fri, 26 Apr 2024 16:05:10 +0200 Subject: [PATCH 12/14] Methods - Added rightward shifting mechanism --- source/niknaks/containers.d | 121 +++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index e0dbd26..6f36008 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -591,6 +591,105 @@ unittest destroy(map); } +// Given [0, 1, 5] +// and shift right at index 1 +// then 0 moves into 1's place +// 0's position is then filled with T.init + +public T[] shift(T)(T[] array, size_t position, bool rightwards = false, bool shrink = false) +{ + // Out of range + if(position >= array.length) + { + return array; + } + + // if rightwards + if(rightwards) + { + // nothing further left than index 0 + if(!position) + { + return array; + } + + for(size_t i = position; i > 0; i--) + { + array[i] = array[i-1]; + } + + // no shrink, then fill with T.init + if(!shrink) + { + array[0] = T.init; + } + // chomp left-hand side + else + { + array = array[1..$]; + } + } + + return array; +} + +// rightwards testung (no shrink) +unittest +{ + int[] numbas = [1, 5, 2]; + numbas = numbas.shift(1, true); + + // should now be [0, 1, 2] + writeln(numbas); + assert(numbas == [0, 1, 2]); + + numbas = [1, 5, 2]; + numbas = numbas.shift(0, true); + + // should now be [1, 5, 2] + writeln(numbas); + assert(numbas == [1, 5, 2]); + + numbas = [1, 5, 2]; + numbas = numbas.shift(2, true); + + // should now be [0, 1, 5] + writeln(numbas); + assert(numbas == [0, 1, 5]); + + numbas = [1, 2]; + numbas = numbas.shift(1, true); + + // should now be [0, 1] + writeln(numbas); + assert(numbas == [0, 1]); + + numbas = [1, 2]; + numbas = numbas.shift(0, true); + + // should now be [1, 2] + writeln(numbas); + assert(numbas == [1, 2]); + + numbas = []; + numbas = numbas.shift(0, true); + + // should now be [] + writeln(numbas); + assert(numbas == []); +} + +public T[] remove(T)(T[] array, size_t idx) +{ + // Return your array on this + if(!(idx < array.length)) + { + return array; + } + + return null; +} + // TODO: make delegate kak // public interface InclusionStratergy(T) // { @@ -650,16 +749,36 @@ public class Tree(T) this.value = value; } - public void appendValue(T value) + this() { } + public void setValue(T value) + { + this.value = value; + } + public void appendNode(Tree!(T) node) { this.children ~= node; } + public bool removeNode(Tree!(T) node) + { + bool found = false; + for(size_t i = 0; i < this.children.length; i++) + { + found = this.children[i] == node; + if(found) + { + + } + } + + return true; + } + public T[] dfs ( InclusionStratergy!(T) strat = toDelegate(&Always!(T)), From 11fd2f856e3b51d5423d6205afa94c1b88bdb314 Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Fri, 26 Apr 2024 16:28:19 +0200 Subject: [PATCH 13/14] Methods - Added leftwards shifting mechanism --- source/niknaks/containers.d | 92 ++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 16 deletions(-) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 6f36008..0fc8883 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -596,7 +596,7 @@ unittest // then 0 moves into 1's place // 0's position is then filled with T.init -public T[] shift(T)(T[] array, size_t position, bool rightwards = false, bool shrink = false) +public T[] shiftInto(T)(T[] array, size_t position, bool rightwards = false, bool shrink = false) { // Out of range if(position >= array.length) @@ -629,6 +629,32 @@ public T[] shift(T)(T[] array, size_t position, bool rightwards = false, bool sh array = array[1..$]; } } + // if leftwards + else + { + // nothing furtherright + if(position == array.length-1) + { + return array; + } + + for(size_t i = position; i < array.length-1; i++) + { + array[i] = array[i+1]; + } + + // no shrink, then fill with T.init + if(!shrink) + { + array[$-1] = T.init; + } + // chomp right-hand side + else + { + array = array[0..$-1]; + } + } + return array; } @@ -637,57 +663,83 @@ public T[] shift(T)(T[] array, size_t position, bool rightwards = false, bool sh unittest { int[] numbas = [1, 5, 2]; - numbas = numbas.shift(1, true); + numbas = numbas.shiftInto(1, true); // should now be [0, 1, 2] writeln(numbas); assert(numbas == [0, 1, 2]); numbas = [1, 5, 2]; - numbas = numbas.shift(0, true); + numbas = numbas.shiftInto(0, true); // should now be [1, 5, 2] writeln(numbas); assert(numbas == [1, 5, 2]); numbas = [1, 5, 2]; - numbas = numbas.shift(2, true); + numbas = numbas.shiftInto(2, true); // should now be [0, 1, 5] writeln(numbas); assert(numbas == [0, 1, 5]); numbas = [1, 2]; - numbas = numbas.shift(1, true); + numbas = numbas.shiftInto(1, true); // should now be [0, 1] writeln(numbas); assert(numbas == [0, 1]); numbas = [1, 2]; - numbas = numbas.shift(0, true); + numbas = numbas.shiftInto(0, true); // should now be [1, 2] writeln(numbas); assert(numbas == [1, 2]); numbas = []; - numbas = numbas.shift(0, true); + numbas = numbas.shiftInto(0, false); // should now be [] writeln(numbas); assert(numbas == []); } -public T[] remove(T)(T[] array, size_t idx) +// leftwards testung (no shrink) +unittest { - // Return your array on this - if(!(idx < array.length)) - { - return array; - } + int[] numbas = [1, 5, 2]; + numbas = numbas.shiftInto(1, false); - return null; + // should now be [1, 2, 0] + writeln(numbas); + assert(numbas == [1, 2, 0]); + + numbas = [1, 5, 2]; + numbas = numbas.shiftInto(0, false); + + // should now be [5, 2, 0] + writeln(numbas); + assert(numbas == [5, 2, 0]); + + numbas = [1, 5, 2]; + numbas = numbas.shiftInto(2, false); + + // should now be [1, 5, 2] + writeln(numbas); + assert(numbas == [1, 5, 2]); + + numbas = []; + numbas = numbas.shiftInto(0, true); + + // should now be [] + writeln(numbas); + assert(numbas == []); +} + +public T[] removeResize(T)(T[] array, size_t position) +{ + return array.shiftInto(position, false, true); } // TODO: make delegate kak @@ -767,16 +819,24 @@ public class Tree(T) public bool removeNode(Tree!(T) node) { bool found = false; + size_t idx; for(size_t i = 0; i < this.children.length; i++) { found = this.children[i] == node; if(found) { - + idx = i; + break; } } - return true; + // if(found) + // { + // this.children = this.children.removeResize(idx, true, true); + // return true; + // } + + return false; } public T[] dfs From 4a431c43d104189a083b42b3e6312252893d5c33 Mon Sep 17 00:00:00 2001 From: Tristan Brice Velloza Kildaire Date: Fri, 26 Apr 2024 16:35:21 +0200 Subject: [PATCH 14/14] TreeNode - Added removal - Added indexing support --- source/niknaks/containers.d | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/source/niknaks/containers.d b/source/niknaks/containers.d index 0fc8883..1eaff9f 100644 --- a/source/niknaks/containers.d +++ b/source/niknaks/containers.d @@ -830,15 +830,25 @@ public class Tree(T) } } - // if(found) - // { - // this.children = this.children.removeResize(idx, true, true); - // return true; - // } + if(found) + { + this.children = this.children.removeResize(idx); + return true; + } return false; } + public T opIndex(size_t idx) + { + return idx < this.children.length ? this.children[idx].getValue() : T.init; + } + + public T getValue() + { + return this.value; + } + public T[] dfs ( InclusionStratergy!(T) strat = toDelegate(&Always!(T)),