mirror of https://github.com/deavmi/niknaks
Merge 4a431c43d1
into 0e232822fa
This commit is contained in:
commit
67d8af2954
|
@ -589,4 +589,412 @@ unittest
|
|||
|
||||
// Destroy the map (such that it ends the sweeper
|
||||
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[] shiftInto(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..$];
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
// rightwards testung (no shrink)
|
||||
unittest
|
||||
{
|
||||
int[] numbas = [1, 5, 2];
|
||||
numbas = numbas.shiftInto(1, true);
|
||||
|
||||
// should now be [0, 1, 2]
|
||||
writeln(numbas);
|
||||
assert(numbas == [0, 1, 2]);
|
||||
|
||||
numbas = [1, 5, 2];
|
||||
numbas = numbas.shiftInto(0, true);
|
||||
|
||||
// should now be [1, 5, 2]
|
||||
writeln(numbas);
|
||||
assert(numbas == [1, 5, 2]);
|
||||
|
||||
numbas = [1, 5, 2];
|
||||
numbas = numbas.shiftInto(2, true);
|
||||
|
||||
// should now be [0, 1, 5]
|
||||
writeln(numbas);
|
||||
assert(numbas == [0, 1, 5]);
|
||||
|
||||
numbas = [1, 2];
|
||||
numbas = numbas.shiftInto(1, true);
|
||||
|
||||
// should now be [0, 1]
|
||||
writeln(numbas);
|
||||
assert(numbas == [0, 1]);
|
||||
|
||||
numbas = [1, 2];
|
||||
numbas = numbas.shiftInto(0, true);
|
||||
|
||||
// should now be [1, 2]
|
||||
writeln(numbas);
|
||||
assert(numbas == [1, 2]);
|
||||
|
||||
numbas = [];
|
||||
numbas = numbas.shiftInto(0, false);
|
||||
|
||||
// should now be []
|
||||
writeln(numbas);
|
||||
assert(numbas == []);
|
||||
}
|
||||
|
||||
// leftwards testung (no shrink)
|
||||
unittest
|
||||
{
|
||||
int[] numbas = [1, 5, 2];
|
||||
numbas = numbas.shiftInto(1, false);
|
||||
|
||||
// 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
|
||||
// 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(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(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)
|
||||
{
|
||||
private T value;
|
||||
private Tree!(T)[] children;
|
||||
|
||||
this(T value)
|
||||
{
|
||||
this.value = 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;
|
||||
size_t idx;
|
||||
for(size_t i = 0; i < this.children.length; i++)
|
||||
{
|
||||
found = this.children[i] == node;
|
||||
if(found)
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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)),
|
||||
TouchStratergy!(T) touch = toDelegate(&Nothing!(T))
|
||||
)
|
||||
{
|
||||
version(unittest)
|
||||
{
|
||||
writeln("dfs entry: ", this);
|
||||
}
|
||||
|
||||
T[] collected;
|
||||
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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "Visit"
|
||||
collected ~= this.value;
|
||||
|
||||
|
||||
return collected;
|
||||
}
|
||||
|
||||
public override string toString()
|
||||
{
|
||||
return format("TreeNode [val: %s]", this.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
version(unittest)
|
||||
{
|
||||
import std.functional : toDelegate;
|
||||
import std.stdio : writeln;
|
||||
|
||||
private void DebugTouch(T)(Tree!(T) node)
|
||||
{
|
||||
writeln("Touching tree node ", node);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
InclusionStratergy!(string) strat = toDelegate(&Always!(string));
|
||||
TouchStratergy!(string) touch = toDelegate(&DebugTouch!(string));
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
string[] linearized = root.linearize();
|
||||
writeln(linearized);
|
||||
|
||||
assert(linearized[0] == "subtree");
|
||||
assert(linearized[1] == "root");
|
||||
|
||||
}
|
Loading…
Reference in New Issue