public override FTree <T> App2(List <T> ts, FTree <T> rightFT) { if (!(rightFT is DeepFTree <T>)) { FTree <T> resultFT = this; foreach (T t in ts) { resultFT = resultFT.PushBack(t); } return((rightFT is EmptyFTree <T>) ? resultFT : resultFT.PushBack(rightFT.LeftView().head)); } else // the right tree is also a deep tree { var deepRight = rightFT as DeepFTree <T>; var cmbList = new List <T>(backDig.digNodes); cmbList.AddRange(ts); cmbList.AddRange(deepRight.frontDig.digNodes); FTree <T> resultFT = new DeepFTree <T> (frontDig, innerFT.App2(ListOfNodes(cmbList), deepRight.innerFT), deepRight.backDig ); return(resultFT); } }
/// <summary> Get or set the object at a specific point. </summary> public object this[Point APoint] { get { KDTree.Node LNode = FTree.Query(APoint); if (LNode != null) { return(LNode.Object); } else { return(null); } } set { // Remove any item at this spot KDTree.Node LNode = FTree.Query(APoint); if (LNode != null) { FTree.Remove(LNode); FNodes.Remove(LNode.Object); } // Add the new item at the spot if (value != null) { LNode = new KDTree.Node(APoint, value); FTree.Add(LNode); FNodes.Add(value, LNode); } } }
public override void Split(int index, out FTree <TChild> left, out TChild center, out FTree <TChild> right, Lineage lineage) { Digit leftDigit, rightDigit; CenterDigit.Split(index, out leftDigit, out center, out rightDigit, lineage); left = leftDigit == null ? Empty : new Single(leftDigit, lineage); right = rightDigit == null ? Empty : new Single(rightDigit, lineage); }
/// <summary> /// This method will re-initialize this instance using the specified parameters. /// </summary> private FTree <TChild> _mutate(Digit left, FTree <Digit> deep, Digit right) { LeftDigit = left; DeepTree = deep; RightDigit = right; Measure = left.Measure + deep.Measure + right.Measure; return(this); }
public Compound(Digit leftDigit, FTree <Digit> deepTree, Digit rightDigit, Lineage lineage) : base(leftDigit.Measure + deepTree.Measure + rightDigit.Measure, TreeType.Compound, lineage, 3) { leftDigit.AssertNotNull(); deepTree.AssertNotNull(); rightDigit.AssertNotNull(); _mutate(leftDigit, deepTree, rightDigit); }
public override FTree <T> App2(List <T> ts, FTree <T> rightFT) { FTree <T> resultFT = rightFT; for (int i = ts.Count - 1; i >= 0; i--) { resultFT = resultFT.PushFront(ts[i]); } return(resultFT.PushFront(theSingle)); }
/// <summary> /// <para> /// This method can mutate the current instance and return it, or return a new instance, based on the supplied /// Lineage. /// </para> /// <para>If the current Lineage allows mutation from the specified Lineage, the instance will be MUTATED and returned.</para> /// <para>Otherwise, the method will return a NEW instance that is a member of the supplied Lineage. </para> /// </summary> private FTree <TChild> MutateOrCreate(Digit left, FTree <Digit> deep, Digit right, Lineage lineage) { if (_lineage.AllowMutation(lineage)) { return(_mutate(left, deep, right)); } else { return(new Compound(left, deep, right, lineage)); } }
/// <summary> Get all objects within a given range of the plane. </summary> public object[] QueryRect(Rectangle ARect) { ArrayList LNodes = FTree.Query(ARect); object[] LResult = new object[LNodes.Count]; for (int i = 0; i < LResult.Length; i++) { LResult[i] = ((KDTree.Node)LNodes[i]).Object; } return(LResult); }
public override void Split(int index, out FTree <TChild> left, out TChild child, out FTree <TChild> right, Lineage lineage) { #if ASSERTS var oldMeasure = Measure; var oldValue = this[index]; #endif switch (WhereIsThisIndex(index)) { case IN_START: case IN_MIDDLE_OF_LEFT: Digit lLeft, lRight; LeftDigit.Split(index, out lLeft, out child, out lRight, lineage); index -= lLeft == null ? 0 : lLeft.Measure; left = CreateCheckNull(Lineage.Immutable, lLeft); right = CreateCheckNull(lineage, lRight, DeepTree, RightDigit); break; case IN_START_OF_DEEP: case IN_MIDDLE_OF_DEEP: index -= LeftDigit.Measure; FTree <Digit> mLeft, mRight; Digit mCenter; DeepTree.Split(index, out mLeft, out mCenter, out mRight, lineage); Digit mcLeft, mcRight; index -= mLeft.Measure; mCenter.Split(index, out mcLeft, out child, out mcRight, lineage); index -= mcLeft == null ? 0 : mcLeft.Measure; left = CreateCheckNull(Lineage.Immutable, LeftDigit, mLeft, mcLeft); right = CreateCheckNull(lineage, mcRight, mRight, RightDigit); break; case IN_MIDDLE_OF_RIGHT: case IN_START_OF_RIGHT: Digit rLeft, rRight; index -= LeftDigit.Measure + DeepTree.Measure; RightDigit.Split(index, out rLeft, out child, out rRight, lineage); index -= rLeft == null ? 0 : rLeft.Measure; right = CreateCheckNull(Lineage.Immutable, rRight); left = CreateCheckNull(lineage, LeftDigit, DeepTree, rLeft); break; case IN_END: case OUTSIDE: throw ImplErrors.Arg_out_of_range("index", index); default: throw ImplErrors.Invalid_execution_path("Index didn't match any of the cases."); } #if ASSERTS oldMeasure.AssertEqual(left.Measure + child.Measure + right.Measure); oldValue.AssertEqual(child[index]); #endif }
public DeepFTree(Digit <T> frontDig, FTree <Node <T> > innerFT, Digit <T> backDig) { if (frontDig.digNodes.Count > 0) { this.frontDig = frontDig; this.innerFT = innerFT; this.backDig = backDig; } else { throw new Exception("The DeepFTree() constructor is passed an empty frontDig !"); } }
public override FTree <TChild> Insert(int index, Leaf <TValue> leaf, Lineage lineage) { var whereIsThisIndex = WhereIsThisIndex(index); #if ASSERTS var newMeasure = Measure + 1; var oldValue = this[index].Value; #endif FTree <Digit> newDeep; FTree <TChild> res = null; switch (whereIsThisIndex) { case IN_START: case IN_MIDDLE_OF_LEFT: Digit leftL, leftR; LeftDigit.Insert(index, leaf, out leftL, out leftR, lineage); newDeep = leftR != null?DeepTree.AddFirst(leftR, lineage) : DeepTree; res = MutateOrCreate(leftL, newDeep, RightDigit, lineage); break; case IN_START_OF_DEEP: case IN_MIDDLE_OF_DEEP: if (DeepTree.Measure == 0) { goto case IN_START_OF_RIGHT; } newDeep = DeepTree.Insert(index - LeftDigit.Measure, leaf, lineage); res = MutateOrCreate(LeftDigit, newDeep, RightDigit, lineage); break; case IN_START_OF_RIGHT: case IN_MIDDLE_OF_RIGHT: Digit rightR; Digit rightL; RightDigit.Insert(index - LeftDigit.Measure - DeepTree.Measure, leaf, out rightL, out rightR, lineage); newDeep = rightR != null?DeepTree.AddLast(rightL, lineage) : DeepTree; rightR = rightR ?? rightL; res = MutateOrCreate(LeftDigit, newDeep, rightR, lineage); break; } #if ASSERTS res.Measure.AssertEqual(newMeasure); res[index].Value.AssertEqual(leaf.Value); res[index + 1].Value.AssertEqual(oldValue); #endif return(res); }
FTree <TChild> CreateCheckNull(Lineage lineage, Digit left = null, FTree <Digit> deep = null, Digit right = null) { var memberPermutation = left != null ? 1 << 0 : 0; memberPermutation |= (deep != null && deep.Measure != 0) ? 1 << 1 : 0; memberPermutation |= right != null ? 1 << 2 : 0; switch (memberPermutation) { case 0 << 0 | 0 << 1 | 0 << 2: return(Empty); case 1 << 0 | 0 << 1 | 0 << 2: return(new Single(left, lineage)); case 1 << 0 | 1 << 1 | 0 << 2: var r2 = deep.Right; var deep1 = deep.RemoveLast(lineage); return(MutateOrCreate(left, deep1, r2, lineage)); case 1 << 0 | 1 << 1 | 1 << 2: return(MutateOrCreate(left, deep, right, lineage)); case 0 << 0 | 1 << 1 | 1 << 2: return(MutateOrCreate(deep.Left, deep.RemoveFirst(lineage), right, lineage)); case 1 << 0 | 0 << 1 | 1 << 2: return(MutateOrCreate(left, deep, right, lineage)); case 0 << 0 | 1 << 1 | 0 << 2: left = deep.Left; deep = deep.RemoveFirst(lineage); if (deep.Measure != 0) { right = deep.Right; deep = deep.RemoveLast(lineage); return(MutateOrCreate(left, deep, right, lineage)); } return(new Single(left, lineage)); case 0 << 0 | 0 << 1 | 1 << 2: return(new Single(right, lineage)); default: throw ImplErrors.Invalid_execution_path("Explicitly checked all possible tree permutations."); } }
public void LoadBanWords() { if (banWordLoaded) { return; } banWordLoaded = true; byte[] bytes = BinaryLoader(ConfigPath + "/ban_words.txt"); string text = Encoding.UTF8.GetString(bytes); string[] words = text.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); FTree tree = null; foreach (string word in words) { string str = word.Trim(); if (string.IsNullOrEmpty(str)) { continue; } if (str[0] == '[') { if (str == "[名字]") { tree = nameFTree; } else { tree = commonFtree; } } if (tree != null) { tree.InsertWord(str); } } }
/// <summary> /// Splits the finger tree right before the specified index. /// </summary> /// <param name="index">The index.</param> /// <param name="left">The left.</param> /// <param name="right">The right.</param> /// <param name="lineage">The lineage.</param> public void Split(int index, out FTree<TChild> left, out FTree<TChild> right, Lineage lineage) { if (index == Measure) { left = this; right = Empty; return; } #if ASSERTS var oldValue = this[index]; var oldFirst = Left; var oldLast = Right; #endif TChild center; Split(index, out left, out center, out right, lineage); right = right.AddFirst(center, lineage); #if ASSERTS center[0].AssertEqual(oldValue); if (left.Measure != 0) { left.Left.AssertEqual(oldFirst); } if (right.Measure != 0) { right.Right.AssertEqual(oldLast); } #endif }
public override FTree <TChild> RemoveAt(int index, Lineage lineage) { var whereIsThisIndex = WhereIsThisIndex(index); Digit newLeft; FTree <TChild> ret = this; #if ASSERTS var newMeasure = Measure - 1; var expectedAtIndex = index != Measure - 1 ? this[index + 1] : null; var expectedBeforeIndex = index != 0 ? this[index - 1] : null; #endif switch (whereIsThisIndex) { case IN_START: case IN_MIDDLE_OF_LEFT: if (LeftDigit.IsFragment) { var fixedTree = FixLeftDigit(lineage); ret = fixedTree.RemoveAt(index, lineage); } else { newLeft = LeftDigit.Remove(index, lineage); ret = CreateCheckNull(lineage, newLeft, DeepTree, RightDigit); } break; case IN_START_OF_DEEP: case IN_MIDDLE_OF_DEEP: if (DeepTree.Measure == 0) { goto case IN_START_OF_RIGHT; } var deep = DeepTree; FTree <Digit> newDeep; if (deep.IsFragment) { newDeep = deep.AddFirst(LeftDigit, lineage); newDeep = newDeep.RemoveAt(index, lineage); newLeft = newDeep.Left; newDeep = newDeep.RemoveFirst(lineage); ret = MutateOrCreate(newLeft, newDeep, RightDigit, lineage); } else { newDeep = DeepTree.RemoveAt(index - LeftDigit.Measure, lineage); ret = CreateCheckNull(lineage, LeftDigit, newDeep, RightDigit); } break; case IN_START_OF_RIGHT: case IN_MIDDLE_OF_RIGHT: if (RightDigit.IsFragment) { var fixedTree = FixRightDigit(lineage); ret = fixedTree.RemoveAt(index, lineage); } else { var newRight = RightDigit.Remove(index - LeftDigit.Measure - DeepTree.Measure, lineage); ret = CreateCheckNull(lineage, LeftDigit, DeepTree, newRight); } break; case IN_END: case OUTSIDE: throw ImplErrors.Arg_out_of_range("index", index); default: throw ImplErrors.Invalid_execution_path("Checked all possible index locations already."); } #if ASSERTS ret.Measure.AssertEqual(newMeasure); if (expectedAtIndex != null) { ret[index].Value.AssertEqual(expectedAtIndex.Value); } if (expectedBeforeIndex != null) { ret[index - 1].Value.AssertEqual(expectedBeforeIndex.Value); } #endif return(ret); }
/// <summary> /// concatenates the two trees together. the supplied lineage cannot be shared by any of the trees, or the result will be corrupt!! <br/> /// However, you can reuse the lineage after calling this method. /// </summary> /// <param name="first">The first.</param> /// <param name="last">The last.</param> /// <param name="lineage">The lineage.</param> /// <returns></returns> public static FTree<TChild> Concat(FTree<TChild> first, FTree<TChild> last, Lineage lineage) { var status = first._kind << 3 | last._kind; FTree<Digit> newDeep; switch (status) { //+ Implementation //This should be farily legible. It is a solution I like to call a 'case table' //Note that TreeType is *not* an enum but a static class with constants. //This is because enums do not support the bitwise << operator. /* If either of the trees is empty*/ case TreeType.Empty << 3 | TreeType.Single: case TreeType.Empty << 3 | TreeType.Compound: return last; case TreeType.Single << 3 | TreeType.Empty: case TreeType.Compound << 3 | TreeType.Empty: return first; case TreeType.Empty << 3 | TreeType.Empty: return first; /* If both are single... we just create a new Compound with their digits.*/ case TreeType.Single << 3 | TreeType.Single: var single1 = (Single) first; var single2 = (Single) last; return new Compound(single1.CenterDigit, FTree<Digit>.Empty, single2.CenterDigit, lineage); case TreeType.Single << 3 | TreeType.Compound: var asSingle = (Single) first; var asCompound = (Compound) last; Digit left, mid, right; asSingle.CenterDigit.Fuse(asCompound.LeftDigit, out left, out mid, out right, lineage); newDeep = asCompound.DeepTree; if (right != null) { newDeep = newDeep.AddFirst(right, lineage); } if (mid != null) { newDeep = newDeep.AddFirst(mid, lineage); } return new Compound(left, newDeep, asCompound.RightDigit, lineage); /* If one is single, we push the digit of the Compound into its Deep.*/ case TreeType.Compound << 3 | TreeType.Single: var rightSingle = (Single) last; var leftCompound = (Compound) first; Digit rLeft, rMid, rRight; leftCompound.RightDigit.Fuse(rightSingle.CenterDigit, out rLeft, out rMid, out rRight, lineage); Digit rDigit; newDeep = leftCompound.DeepTree; if (rMid != null) { newDeep = newDeep.AddLast(rLeft, lineage); if (rRight != null) { newDeep = newDeep.AddLast(rMid, lineage); rDigit = rRight; } else { rDigit = rMid; } } else { rDigit = rLeft; } return new Compound(leftCompound.LeftDigit, newDeep, rDigit, lineage); /* This is the most complex case. * First note that when we have two Compounds, we essentially have two inner digits and two outer digits: * A..B ++ C..D => A..D * The digits B C must somehow be pushed into the FTree, but the digits A D are going to be its left and right digits. * What we do with the digits B C is call the function ReformDigitsForConcat on the inner digits * Because the law is that only digits with 2 or 3 elements can be pushed to become items in the deeper trees * We need to reform the digits, whatever their current shape, into 2-3 digits. * Look up the function to see how it's done. */ case TreeType.Compound << 3 | TreeType.Compound: Digit leftmost; Digit middle; Digit rightmost; var compound1 = (Compound) first; var compound2 = (Compound) last; var innerLeft = compound1.RightDigit; var innerRight = compound2.LeftDigit; innerLeft.Fuse(innerRight, out leftmost, out middle, out rightmost, lineage); FTree<Digit> deep; if (compound1.Measure > compound2.Measure) //We want to push the small tree into the large one. { deep = compound1.DeepTree; if (leftmost != null) deep = deep.AddLast(leftmost, lineage); if (middle != null) deep = deep.AddLast(middle, lineage); if (rightmost != null) deep = deep.AddLast(rightmost, lineage); deep = FTree<Digit>.Concat(deep, compound2.DeepTree, lineage); } else { deep = compound2.DeepTree; if (rightmost != null) deep = deep.AddFirst(rightmost, lineage); if (middle != null) deep = deep.AddFirst(middle, lineage); if (leftmost != null) deep = deep.AddFirst(leftmost, lineage); deep = FTree<Digit>.Concat(compound1.DeepTree, deep, lineage); } return new Compound(compound1.LeftDigit, deep, compound2.RightDigit, lineage); } throw ImplErrors.Invalid_execution_path("Checked all permutations of finger tree concatenation."); }
public FTree<TChild> AddFirstList(FTree<TChild> list, Lineage lineage) { return Concat(list, this, lineage); }
/// <summary> /// Concats the specified ftree to the end of this one. If the lineage is shared by either of the trees, the result is corrupt! /// </summary> /// <param name="list">The list.</param> /// <param name="lineage">The lineage.</param> /// <returns></returns> public FTree<TChild> AddLastList(FTree<TChild> list, Lineage lineage) { return Concat(this, list, lineage); }
public abstract void Split(int index, out FTree<TChild> left, out TChild child, out FTree<TChild> right, Lineage lineage);
public override FTree <T> Merge(FTree <T> rightFT) { var emptyList = new List <T>(); return(App2(emptyList, rightFT)); }
/// <summary> /// Constructs a finger tree from the specified array, consisting of the elements at [index..index+count) /// A lot faster than adding iteratively without lineages, and quite a bit faster than adding iteratively with /// lineages. /// </summary> /// <param name="arr">The arr.</param> /// <param name="index">The index.</param> /// <param name="count">The count.</param> /// <param name="lin">The lineage.</param> /// <remarks> /// Related: /// http://cs.stackexchange.com/questions/41081/guessing-the-structure-of-a-finger-tree-from-the-number-of-elements /// <br/> /// Algorithm: https://hackage.haskell.org/package/containers-0.4.0.0/docs/src/Data-Sequence.html#applicativeTree /// </remarks> /// <returns></returns> public static FTree<TChild> Construct(TValue[] arr, ref int index, int count, Lineage lin) { var myChildSize = FastMath.PowN(3, Nesting - 1); var divRem = count % myChildSize; FTree<TChild> ret; var digit = ExampleDigit; int number; if (divRem == 0 && (number = count / myChildSize) <= 8) { switch (number) { case 0: return Empty; case 1: case 2: case 3: case 4: var center = digit.ConstructMult(arr, ref index, number, lin); ret = new Single(center, lin); break; case 5: var left1 = digit.Construct3(arr, ref index, lin); var right1 = digit.ConstructMult(arr, ref index, 2, lin); ret = new Compound(left1, FTree<Digit>.Empty, right1, lin); break; case 6: var left2 = digit.Construct3(arr, ref index, lin); var right2 = digit.Construct3(arr, ref index, lin); ret = new Compound(left2, FTree<Digit>.Empty, right2, lin); break; case 7: var left3 = digit.ConstructMult(arr, ref index, 4, lin); var right3 = digit.Construct3(arr, ref index, lin); ret = new Compound(left3, FTree<Digit>.Empty, right3, lin); break; case 8: var left4 = digit.ConstructMult(arr, ref index, 4, lin); var right4 = digit.ConstructMult(arr, ref index, 4, lin); ret = new Compound(left4, FTree<Digit>.Empty, right4, lin); break; default: throw ImplErrors.Invalid_execution_path("An if statement just checked if number <= 8."); } } else { var nextChildSize = myChildSize * 3; var nextDivRem = count % nextChildSize; #if ASSERTS //this is guaranteed by previous recursive calls to Construct. count must be divisible by myChildSize //and since nextChildSize = myChildSize * 3, then nextDivRem % myChildSize must be within [0,2]. //we maintain this invariant by the next if-else block, which makes sure that the 'count' for the next invocation //really is divisible by nextChildSize. At the topmost level, myChildSize is 1, and nextChildSize is 3. (nextDivRem % myChildSize).AssertBetween(0, 2); #endif if (nextDivRem == 0) { //If nextDivRem is already divisible by nextChildSize, we should preserve this by removing 2*nextChildSize from it. //Since 2*nextChildSize = 0 (mod nextChildSize), the divisibility is preserved. var left = digit.Construct3(arr, ref index, lin); var deep = FTree<Digit>.Construct(arr, ref index, count - (nextChildSize << 1), lin); var right = digit.Construct3(arr, ref index, lin); ret = new Compound(left, deep, right, lin); } else if (nextDivRem == myChildSize) { //In this case, nextDivRem % myChildSize == 1. //In order to make sure 'count' is divisible by nextChildSize, we need to remove 1 myChildSize from it. //while also filling the current finger tree level. So we remove 7*myChildSize, which is //7*myChildSize = myChildSize + 2*nextChildSize = myChildSize (mod nextChildSize) var left = digit.ConstructMult(arr, ref index, 4, lin); var deep = FTree<Digit>.Construct(arr, ref index, count - ((nextChildSize << 1) + myChildSize), lin); var right = digit.Construct3(arr, ref index, lin); ret = new Compound(left, deep, right, lin); } else { //like the other cases. var left = digit.ConstructMult(arr, ref index, 4, lin); var deep = FTree<Digit>.Construct(arr, ref index, count - ((nextChildSize << 1) + (myChildSize << 1)), lin); var right = digit.ConstructMult(arr, ref index, 4, lin); ret = new Compound(left, deep, right, lin); } } #if ASSERTS ret.Measure.AssertEqual(count); #endif return ret; }
public override FTree <T> Merge(FTree <T> rightFT) { return(rightFT); }
public override void Split(int index, out FTree <TChild> left, out TChild child, out FTree <TChild> right, Lineage lineage) { throw ImplErrors.Invalid_invocation("Empty FingerTree"); }
public override FTree <T> Merge(FTree <T> rightFT) { return(rightFT.PushFront(theSingle)); }
/// <summary> Removes the object at a given point. </summary> public void Remove(object AObject) { KDTree.Node LNode = (KDTree.Node)FNodes[AObject]; FTree.Remove(LNode); FNodes.Remove(AObject); }