I need to merge a xml of unknown strucutre. The request is that the hierarchy won't change:
XDocument xDoc1 = XDocument.Parse(#"<Root>
<LeafA>
<a>item1</a>
</LeafA>
<LeafA>
<b>item3</b>
</LeafA>
</Root>");
XDocument xDoc2 = XDocument.Parse(#"<Root>
<LeafA>
<a>item2</a>
</LeafA>
<LeafA>
<b>item4</b>
</LeafA>
</Root>");
Merge(xDoc1.Root, xDoc2.Root);
so far i have
void Merge(XElement left, XElement right)
{
foreach (var node in right.Elements())
{
if (left.Element(node.Name.LocalName) == null)
{
left.Add(node);
}
}
foreach (var x in right.Elements().Where(r => left.Element(r.Name.LocalName) != null))
{
Merge(left.Element(x.Name.LocalName),x);
}
}
This gives me the output of
<Root>
<LeafA>
<a>item1</a>
<b>item4</b>
</LeafA>
<LeafA>
<b>item3</b>
</LeafA>
</Root>
but it has to be
<Root>
<LeafA>
<a>item1</a>
<a>item2</a>
</LeafA>
<LeafA>
<b>item3</b>
<b>item4</b>
</LeafA>
</Root>
This solved my problem:
public static void Merge(XElement left, XElement right)
{
foreach (XElement node in right.Elements())
{
int num = MergeXml.NodeWithSameNameAtSameHierarchyLevel(left, node);
if (num == 0)
{
left.Add(node);
}
else
{
if (MergeXml.IsFirstIteration(left, right) && !node.HasElements)
{
left.Add(node);
}
else
{
if (num == 1)
{
MergeXml.CheckDescandants(left, node);
}
else
{
if (node.Descendants().Any<XElement>() && node.Descendants().First<XElement>().Name.LocalName.Equals(node.Name.LocalName))
{
MergeXml.CheckDescandants(left, node);
}
else
{
int num2 = node.ElementsBeforeSelf().Count((XElement x) => x.Name.LocalName.Equals(node.Name.LocalName));
foreach (XElement current in node.Elements())
{
if (current.HasElements)
{
if (MergeXml.ItemNodeExistInLeftFile(left, node, num2) || MergeXml.ItemNodeDescandandsDontHaveAnyElements(current))
{
MergeXml.CheckDescandants(left, current, num2);
}
else
{
(
from x in left.Elements()
where x.Name.LocalName.Equals(node.Name.LocalName)
select x).ElementAt(num2).Add(current);
}
}
else
{
(
from x in left.Elements()
where x.Name.LocalName.Equals(node.Name.LocalName)
select x).ElementAt(num2).Add(current);
}
}
}
}
}
}
}
}
public static XDocument MergeXmlFiles(List<XDocument> docs)
{
MergeXml.Merge(docs[0].Root, docs[1].Root);
MergeXml.Merge(docs[0].Root, docs[2].Root);
return docs[0];
}
private static void CheckDescandants(XElement left, XElement node)
{
if (node.Descendants().Count((XElement x) => x.HasElements) > 0)
{
MergeXml.Merge(left.Element(node.Name.LocalName), node);
return;
}
if (left.Element(node.Name.LocalName) != null)
{
if (node.HasElements)
{
left.Element(node.Name.LocalName).Add(node.Descendants());
return;
}
left.Element(node.Name.LocalName).Add(node);
return;
}
else
{
if (node.HasElements)
{
left.Add(node.Descendants());
return;
}
left.Add(node);
return;
}
}
private static void CheckDescandants(XElement left, XElement node, int recursivCallIndex)
{
if (node.Descendants().Count((XElement x) => x.HasElements) > 0)
{
MergeXml.Merge(left.Elements().ElementAt(recursivCallIndex).Element(node.Name.LocalName), node);
return;
}
IEnumerable<XElement> source =
from x in left.Elements().ElementAt(recursivCallIndex).Descendants()
where x.Name == node.Name
select x;
if (source.Count<XElement>() > 0)
{
source.ElementAt(0).Add(node.Descendants());
return;
}
left.Elements().ElementAt(recursivCallIndex).Add(node);
}
private static bool IsFirstIteration(XElement left, XElement right)
{
return left.Parent == null && right.Parent == null;
}
private static bool ItemNodeDescandandsDontHaveAnyElements(XElement item)
{
return item.Descendants().Count((XElement x) => x.HasElements) == 0;
}
private static bool ItemNodeExistInLeftFile(XElement left, XElement node, int positionNodeInXmlIndex)
{
return left.Elements().ElementAt(positionNodeInXmlIndex).Element(node.Name.LocalName) != null;
}
private static int NodeWithSameNameAtSameHierarchyLevel(XElement left, XElement node)
{
if (!left.Descendants().Any<XElement>())
{
return 0;
}
if (left.Descendants().Count((XElement x) => x.Name.LocalName.Equals(node.Name.LocalName)) == 0)
{
return 0;
}
return left.Descendants().Count((XElement x) => x.Name.LocalName.Equals(node.Name.LocalName) && DivideXml.HasSameParentName(x, node));
}
Related
I created a custom linked list on a whiteboard, for learning purposes.
CustDoublyLinkedList class with the nested Node class, but when it is time to insert, at the specified index method must loop through until it get to an index to insert. I want to insert directly without using loop as my Add or PushFront methods work.
I also added some more method like IndexOf and Contain methods for the list
CustDoublyLinkedList<int> myList = new();
myList.Add(12);
myList.Add(13);
myList.Add(14);
myList.Add(45);
myList.Add(28);
myList.Add(120);
myList.PushFront(32);
myList.Insert(3,1500);
for (int i = 0; i < myList.Count; i++)
{
Console.WriteLine(myList[i]);
}
class CustDoublyLinkedList<T>
{
private class Node
{
public T Element { get; set; }
public Node NextNode { get; set; }
public Node PrevNode { get; set; }
public Node(T data)
{
this.Element = data;
this.PrevNode = null;
this.NextNode = null;
}
public Node(T data, Node prevNode): this(data)
{
prevNode.NextNode = this;
}
public Node(T data, Node prevNode, Node nextNode) : this(data, prevNode)
{
nextNode.PrevNode = this;
}
}
private Node head;
private Node tail;
private int counter;
public CustDoublyLinkedList()
{
this.head = null;
this.tail = null;
this.counter = 0;
}
public void Insert(int index, T item)
{
if (index == 0)
{
throw new ArgumentOutOfRangeException("You Can Push with PushFront Method at Index: " + index);
}
if (index < 0 || index >= this.counter)
{
throw new ArgumentOutOfRangeException("invalid Index: " + index);
}
Node newNode = new(item);
Node currentNode = this.head;
for (int i = 0; i < index - 1; i++)
{
currentNode = currentNode.NextNode;
}
newNode.NextNode = currentNode.NextNode;
newNode.PrevNode = currentNode.PrevNode;
currentNode.NextNode = newNode;
this.counter++;
}
public void Add(T item)
{
if (this.head == null)
{
this.head = new(item);
this.tail = this.head;
}
else
{
Node newNode = new(item, this.tail);
this.tail = newNode;
}
this.counter++;
}
public void PushFront(T item)
{
Node newNode = new(item);
newNode.NextNode = this.head;
newNode.PrevNode = null;
if(this.head != null)
{
this.head.PrevNode = newNode;
}
this.head = newNode;
this.counter++;
}
public bool Contain(T item)
{
int index = IndexOf(item);
if (index != -1)
{
return true;
}
return false;
}
public int IndexOf(T item)
{
Node currentNode = this.head;
int index = 0;
while(currentNode != null)
{
if (object.Equals(currentNode.Element, item))
{
return index;
}
currentNode = currentNode.NextNode;
index++;
}
return -1;
}
public int Count
{
get { return this.counter; }
}
public T this[int index]
{
get
{
if (index < 0 || index >= this.counter)
{
throw new IndexOutOfRangeException("Invalid Index: " + index);
}
Node currentNode = this.head;
for (int i = 0; i < index; i++)
{
currentNode = currentNode.NextNode;
}
return currentNode.Element;
}
set
{
if (index < 0 || index >= this.counter)
{
throw new IndexOutOfRangeException("Invalid Index: " + index);
}
Node currentNode = this.head;
for (int i = 0; i < index; i++)
{
currentNode = currentNode.NextNode;
}
currentNode.Element = value;
}
}
}
You are looking for a Skip List
With this you can drive your insert requirement to O(log N) on average while still maintaining a linked list structure
I have a created a Node Builder to fetch how n elements are connected to one another. It is a parent child hierarchy represented in Node Tree.
I am using tree builder like below code to find best two chains.
Below is the code:
public class NodeBuilder
{
private readonly List<IItem> _nestedItems;
private readonly IFactory<IItem> _factory;
private readonly NodeEqualityComparer _comparer;
private readonly List<Node> _nodes;
private WeightedComparer _weightedComparer;
private NodeComparer _nodeComparer;
private readonly NodeItemComparer _nodeItemComparer;
public NodeBuilder(List<IItem> nestedItems, IFactory<IItem> factory)
{
_nestedItems = nestedItems;
_factory = factory;
_comparer = new NodeEqualityComparer();
_nodeComparer = new NodeComparer();
_nodes = new List<Node>();
_weightedComparer=new WeightedComparer();
_nodeItemComparer = new NodeItemComparer(_factory.Comparer);
}
public IEnumerable<List<int>> GetTopChains(int collections)
{
if (_nodes.Count == 0) BuildNodes(collections);
var collection= GetIndexes().ToList();
collection.Sort(_weightedComparer);
return collection.Take(collections);
}
public class WeightedComparer : IComparer<List<int>>
{
public int Compare(List<int> x, List<int> y)
{
if (x == y) return 0;
if (x == null) return 1;
if (y == null) return -1;
return y.Count - x.Count;
}
}
private IEnumerable<List<int>> GetIndexes()
{
Dictionary<IItem,List<int>> indexers = new Dictionary<IItem, List<int>>();
_nodes.Sort(_nodeItemComparer);
foreach (var node in _nodes)
{
List< int> indexs=new List<int>();
int currSize = node.ChainSize;
var temp = node;
while (temp != null)
{
int index = _nestedItems.IndexOf(temp.Item);
if (index != -1) indexs.Add(index);
currSize--;
var temps = new List<Node>(temp.Childs.Where(x => x.ChainSize == currSize));
temps.Sort(_nodeComparer);
Dictionary<Node,List<int>> subIndexes = new Dictionary<Node, List<int>>();
if (!temps.Any()) temp = null;
foreach (var subTemp in temps)
{
var key = subTemp.Item;
if (indexers.ContainsKey(key))
{
var newList = new List<int>();
newList.AddRange(indexs);
newList.AddRange(indexers[key]);
subIndexes.Add(subTemp, newList);
}
if (subIndexes[subTemp].Count == node.ChainSize)
{
temp = subTemp;
indexers.Remove(subTemp.Item);
}
else
{
temp = null;
}
}
}
indexs = indexs.Distinct().ToList();
indexers.Add(node.Item,indexs);
}
return indexers.Values;
}
private void BuildNodes(int collections)
{
int total = _factory.TotalItems;
for (int i = collections * _factory.TotalItems - 1; i >= 0; i--)
{
var searchNode = new Node(_nestedItems[i], _factory.EqualityComparer);
Node node1 = _nodes.SingleOrDefault(x => _comparer.Equals(x, searchNode));
if (node1 == null)
{
node1 = searchNode;
node1.ChainSize = total;
_nodes.Add(node1);
}
}
for (int i = 0; i < collections * _factory.TotalItems; i++)
{
var searchNode = new Node(_nestedItems[i], _factory.EqualityComparer);
Node node1 = _nodes.SingleOrDefault(x => _comparer.Equals(x, searchNode));
for (int j = 0; j < collections * _factory.TotalItems; j++)
{
searchNode = new Node(_nestedItems[j], _factory.EqualityComparer);
Node node2 = _nodes.SingleOrDefault(x => _comparer.Equals(x, searchNode));
if (node2 == null)
{
node2 = searchNode;
_nodes.Add(node2);
}
if (_nestedItems[i].Constraint(_nestedItems[j]))
{
if (node1 != null)
{
int temp = node1.ChainSize - 1;
node2.ChainSize = temp;`enter code here`
if (!node1.Childs.Contains(node2, new NodeEqualityComparer()))
node1.Childs.Add(node2);
}
}
}
}
}
}
public class NodeItemComparer:IComparer<Node>
{
private readonly IComparer<IItem> _factoryComparer;
public NodeItemComparer(IComparer<IItem> factoryComparer)
{
_factoryComparer = factoryComparer;
}
public int Compare(Node x, Node y)
{
if (x == null & y == null) return 0;
if (x == y) return 0;
if (x == null) return 1;
if (y == null) return -1;
return _factoryComparer.Compare(y.Item, x.Item);
}
}
public class NodeComparer:IComparer<Node>
{
public int Compare(Node x, Node y)
{
if (x == null & y == null) return 0;
if (x == y) return 0;
if (x == null) return 1;
if (y == null) return -1;
return y.ChainSize - x.ChainSize;
}
}
public class NodeEqualityComparer : IEqualityComparer<Node>
{
public bool Equals(Node x, Node y)
{
if (x == null & y == null) return true;
if (x == y) return true;
if (x != y) return false;
return x.Equals(y);
}
public int GetHashCode(Node obj)
{
return obj.GetHashCode();
}
}
public class Node : IEquatable<Node>
{
public IItem Item { get; }
private readonly IEqualityComparer<IItem> _comparer;
public int ChainSize { get; set; }
public IList<Node> Childs { get; private set; }
public Node(IItem item, IEqualityComparer<IItem> comparer)
{
Item = item;
_comparer = comparer;
Childs = new List<Node>();
}
public override string ToString()
{
return Item.ItemName;
}
public bool Equals(Node other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return _comparer.Equals(Item, other.Item);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Node)obj);
}
public override int GetHashCode()
{
return (Item != null ? Item.GetHashCode() : 0);
}
public static bool operator ==(Node left, Node right)
{
return Equals(left, right);
}
public static bool operator !=(Node left, Node right)
{
return !Equals(left, right);
}
}
I am looking for a ways to traverse the tree and find two hierarchical connected items.
I have a linkedlist class like follows:
public class DbNode<T>
{
private T _data;
private DbNode<T> _prev;
private DbNode<T> _next;
public T Data
{
get { return this._data; }
set { this._data = value; }
}
public DbNode<T> Prev
{
get { return this._prev; }
set { this._prev = value; }
}
public DbNode<T> Next
{
get { return this._next; }
set { this._next = value; }
}
public DbNode(T data, DbNode<T> prev, DbNode<T> next)
{
this._data = data;
this._prev = prev;
this._next = next;
}
public DbNode(T data, DbNode<T> prev)
{
this._data = data;
this._prev = prev;
this._next = null;
}
public DbNode(DbNode<T> next)
{
this._data = default(T);
this._next = next;
this._prev = null;
}
public DbNode(T data)
{
this._data = data;
this._prev = null;
this._next = null;
}
public DbNode()
{
this._data = default(T);
this._prev = null;
this._next = null;
}
}
public class DbLinkedList<T>
{
private DbNode<T> _head;
public DbNode<T> Head
{
get { return this._head; }
set { this._head = value; }
}
public DbLinkedList()
{
Head = null;
}
public T this[int index]
{
get
{
return this.GetItemAt(index);
}
}
public bool IsEmpty()
{
return Head == null;
}
public T GetItemAt(int i)
{
if (IsEmpty())
{
Console.WriteLine("The double linked list is empty.");
return default(T);
}
DbNode<T> p = new DbNode<T>();
p = Head;
if (0 == i)
{
return p.Data;
}
int j = 0;
while (p.Next != null && j < i)
{
j++;
p = p.Next;
}
if (j == i)
{
return p.Data;
}
else
{
Console.WriteLine("The node dose not exist.");
return default(T);
}
}
public int Count()
{
DbNode<T> p = Head;
int length = 0;
while (p != null)
{
length++;
p = p.Next;
}
return length;
}
public void Clear()
{
this.Head = null;
}
public void AddAfter(T item, int i)
{
if (IsEmpty() || i < 0)
{
Console.WriteLine("The double linked list is empty or the position is uncorrect.");
return;
}
if (0 == i)
{
DbNode<T> newNode = new DbNode<T>(item);
newNode.Next = Head.Next;
Head.Next.Prev = newNode;
Head.Next = newNode;
newNode.Prev = Head;
return;
}
DbNode<T> p = Head;
int j = 0;
while (p != null && j < i)
{
p = p.Next;
j++;
}
if (j == i)
{
DbNode<T> newNode = new DbNode<T>(item);
newNode.Next = p.Next;
if (p.Next != null)
{
p.Next.Prev = newNode;
}
newNode.Prev = p;
p.Next = newNode;
}
else
{
Console.WriteLine("The position is uncorrect.");
}
}
public void AddBefore(T item, int i)
{
if (IsEmpty() || i < 0)
{
Console.WriteLine("The double linked list is empty or the position is uncorrect.");
return;
}
if (0 == i)
{
DbNode<T> newNode = new DbNode<T>(item);
newNode.Next = Head;
Head.Prev = newNode;
Head = newNode;
return;
}
DbNode<T> n = Head;
DbNode<T> d = new DbNode<T>();
int j = 0;
while (n.Next != null && j < i)
{
d = n;
n = n.Next;
j++;
}
if (n.Next == null)
{
DbNode<T> newNode = new DbNode<T>(item);
n.Next = newNode;
newNode.Prev = n;
newNode.Next = null;
}
else
{
if (j == i)
{
DbNode<T> newNode = new DbNode<T>(item);
d.Next = newNode;
newNode.Prev = d;
newNode.Next = n;
n.Prev = newNode;
}
}
}
public void AddLast(T item)
{
DbNode<T> newNode = new DbNode<T>(item);
DbNode<T> p = new DbNode<T>();
if (Head == null)
{
Head = newNode;
return;
}
p = Head;
while (p.Next != null)
{
p = p.Next;
}
p.Next = newNode;
newNode.Prev = p;
}
public T RemoveAt(int i)
{
if (IsEmpty() || i < 0)
{
Console.WriteLine("The double linked list is empty or the position is uncorrect.");
return default(T);
}
DbNode<T> q = new DbNode<T>();
if (0 == i)
{
q = Head;
Head = Head.Next;
Head.Prev = null;
return q.Data;
}
DbNode<T> p = Head;
int j = 0;
while (p.Next != null && j < i)
{
j++;
q = p;
p = p.Next;
}
if (i == j)
{
p.Next.Prev = q;
q.Next = p.Next;
return p.Data;
}
else
{
Console.WriteLine("The position is uncorrect.");
return default(T);
}
}
public int IndexOf(T value)
{
if (IsEmpty())
{
Console.WriteLine("The list is empty.");
return -1;
}
DbNode<T> p = new DbNode<T>();
p = Head;
int i = 0;
while (p.Next != null && !p.Data.Equals(value))
{
p = p.Next;
i++;
}
return i;
}
public void Reverse()
{
DbLinkedList<T> tmpList = new DbLinkedList<T>();
DbNode<T> p = this.Head;
tmpList.Head = new DbNode<T>(p.Data);
p = p.Next;
while (p != null)
{
tmpList.AddBefore(p.Data, 0);
p = p.Next;
}
this.Head = tmpList.Head;
tmpList = null;
}
public string ReverseByPrev()
{
DbNode<T> tail = GetNodeAt(Count() - 1);
StringBuilder sb = new StringBuilder();
sb.Append(tail.Data.ToString() + ",");
while (tail.Prev != null)
{
sb.Append(tail.Prev.Data + ",");
tail = tail.Prev;
}
return sb.ToString().TrimEnd(',');
}
private DbNode<T> GetNodeAt(int i)
{
if (IsEmpty())
{
Console.WriteLine("The list is empty.");
return null;
}
DbNode<T> p = new DbNode<T>();
p = this.Head;
if (0 == i)
{
return p;
}
int j = 0;
while (p.Next != null && j < i)
{
j++;
p = p.Next;
}
if (j == i)
{
return p;
}
else
{
Console.WriteLine("The node does not exist.");
return null;
}
}
public T Fisrt()
{
return this.GetItemAt(0);
}
public T Last()
{
return this.GetItemAt(this.Count() - 1);
}
}
And I alse have a class as Product which contains properties:ProductID and ProductValue:
public class Product
{
private byte _productID;
public byte ProductID
{
get { return _productID; }
set
{
_productID = value;
NotifyPropertyChanged("ProductID");
}
}
private UInt16 _productValue;
public UInt16 ProductValue
{
get { return _productValue; }
set
{
_productValue = value;
NotifyPropertyChanged("ProductValue");
}
}
}
I have another listbox to which I want to add the Product when I click the TreeView:
MyLinkList<Product> myLinkList = new MyLinkList<Product>();
private void MenuItem_OnClick(object sender, RoutedEventArgs e)
{
var item = this.TreeView.SelectedItem as Product;
listbox.Items.Add(item);
myLinkList.Append(item);
}
Now the problem is I want to modify the item's property selected to add based on the former one. For example: if the former one's ProductID is 1, then this SelectedItem.ProductValue = FormerItem.ProductValue + 1, how I suppose to do this? Thanks!
I want to randomly generate trees (not BST) for unit testing of my code. I have tried it in a number of ways but somehow after generation of 3 -4 trees there is an exception or code goes into infinite loop. I am using random numbers for edges and node values.
I have also tried queue approach where I fill up the queue with random numbers and then dequeue nodes and randomly select the old node from the existing items in the queue and then connect this new node.
Does anybody know how to do this in C# in more better and succinct way?
EDIT
public class Tree
{
public Node Root { get; private set; }
public readonly Dictionary<long, Node> Nodes = new Dictionary<long, Node>();
public readonly Dictionary<string, long> SumDictionary = new Dictionary<string, long>();
public readonly Dictionary<long, long> FDictionary = new Dictionary<long, long>
{
{0, 1},
{1, 1}
};
public long Query(long n)
{
long s = 0;
Dfs();
for (int i = 1; i <= n; i++)
{
for (int j = i; j <= n; j++)
{
var lvalue = GetLValue(i, j);
if (i != j)
{
lvalue *= 2;
}
s += lvalue;
if (s >= Mod)
{
s %= Mod;
}
}
}
return s;
}
private long GetLValue(int a, int b)
{
var key = string.Format("{0}-{1}", a, b);
if (SumDictionary.ContainsKey(key))
{
return Fvalue(SumDictionary[key]);
}
var aKey = string.Format("{0}-{1}", 1, a);
var bKey = string.Format("{0}-{1}", 1, b);
var sumA = SumDictionary[aKey];
var sumB = SumDictionary[bKey];
var lca = Lca(a, b);
if (lca != a && lca != b)
{
return Fvalue(sumA + sumB - SumDictionary[string.Format("{0}-{1}", lca, lca)]);
}
long bigSum, smallSum;
if (sumA > sumB)
{
bigSum = sumA;
smallSum = sumB;
}
else
{
bigSum = sumB;
smallSum = sumA;
}
var sumAtoB = bigSum - (smallSum - Nodes[smallSum].Value);
return Fvalue(sumAtoB);
}
public void AddNode(long a, long b)
{
Node nodea, nodeb;
if (Nodes.ContainsKey(a))
{
nodea = Nodes[a];
}
else
{
nodea = new Node { Value = a };
Nodes.Add(a, nodea);
}
if (Nodes.ContainsKey(b))
{
nodeb = Nodes[b];
}
else
{
nodeb = new Node { Value = b };
Nodes.Add(b, nodeb);
}
nodea.ReachableNodes.Add(b, nodeb);
nodeb.ReachableNodes.Add(a, nodea);
if (Root == null)
{
Root = nodea;
}
}
public long? Lca(int a, int b)
{
bool found = false;
return TraverseForLca(Root, null, a, b, ref found);
}
private long? TraverseForLca(Node node, Node prev, long a, long b, ref bool found)
{
if (node == null)
{
return null;
}
if (node.Value == a)
{
return a;
}
if (node.Value == b)
{
return b;
}
long? f = null;
foreach (KeyValuePair<long, Node> reachableNode in node.ReachableNodes)
{
var n = reachableNode.Value;
if (prev != null && n.Value == prev.Value)
{
continue;
}
long? lca = TraverseForLca(n, node, a, b, ref found);
if (found)
{
return lca;
}
if (lca != null && f == null)
{
f = lca;
}
else if (lca != null)
{
found = true;
return node.Value;
}
}
return f;
}
public void Dfs()
{
TravelForDfs(Root, null, 0);
}
private void TravelForDfs(Node node, Node prev, long recSum)
{
if (node == null)
{
return;
}
var key = string.Format("{0}-{1}", prev != null ? prev.Value : node.Value, node.Value);
var iKey = string.Format("{0}-{1}", node.Value, node.Value);
var weight = node.Weight;
if (weight >= Mod)
{
weight %= Mod;
}
if (!SumDictionary.ContainsKey(iKey))
{
SumDictionary.Add(iKey, weight);
}
weight = recSum + node.Weight;
if (weight >= Mod)
{
weight %= Mod;
}
foreach (KeyValuePair<long, Node> reachableNode in node.ReachableNodes)
{
var n = reachableNode.Value;
if (prev != null && n.Value == prev.Value)
{
if (!SumDictionary.ContainsKey(key))
{
SumDictionary.Add(key, weight);
}
continue;
}
if (!SumDictionary.ContainsKey(key))
{
SumDictionary.Add(key, weight);
}
TravelForDfs(n, node, weight);
}
}
public long Fvalue(long n)
{
if (n == 1 || n == 0)
{
return 1;
}
long a, b;
if (FDictionary.ContainsKey(n - 1))
{
a = FDictionary[n - 1];
}
else
{
a = Fvalue(n - 1);
if (!FDictionary.ContainsKey(n - 1))
{
FDictionary.Add(n - 1, a);
}
}
if (FDictionary.ContainsKey(n - 2))
{
b = FDictionary[n - 2];
}
else
{
b = Fvalue(n - 2);
if (!FDictionary.ContainsKey(n - 2))
{
FDictionary.Add(n - 2, b);
}
}
if (!FDictionary.ContainsKey(n))
{
FDictionary.Add(n, a + b);
}
var s = a + b;
if (s >= Mod)
{
s %= Mod;
}
return s;
}
}
It should just generate a tree
Does this tree meet your requirements?
public class TreeNode<T>
{
public T Value { get; set; }
public List<TreeNode<T>> Childs { get; }
public TreeNode()
{
Childs = new List<TreeNode<T>>();
}
}
public class TreeGenerator
{
private readonly int maxChilds;
private readonly Random rnd = new Random();
public TreeGenerator(int maxChilds)
{
this.maxChilds = maxChilds;
}
public TreeNode<T> CreateTree<T>(int maxDepth, Func<T> valueGenerator)
{
var node = new TreeNode<T>();
node.Value = valueGenerator();
if (maxDepth > 0)
{
var childsCount = rnd.Next(maxChilds);
for (var i = 0; i < childsCount; ++i)
node.Childs.Add(CreateTree(maxDepth - 1, valueGenerator));
}
return node;
}
public static void Demo()
{
var rnd = new Random();
var generator = new TreeGenerator(3 /* max childs count*/);
var tree = generator.CreateTree(4 /*max depth*/, () => rnd.Next() /*node value*/);
}
}
UPDATE
I don´t want you to do my Work and write code for me I just wanted a nurge in the right Direction!
So I have to be more specific with my Problem, give me a chance to do some work on this and I will update my question with the results ;-)
UPDATE 2
I´ve solved my Problem with Roslyn maybe not very elegant but it work for my needs, here is the code ;-)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;
namespace ParserTest
{
public class MyParser
{
private int _currentLevel = 1;
public void TestMethod()
{
string testString =
#" if(#ISEMPTY(temp.tis_filterstatus2))
{
tis_datasheet_selection.is_selected = 'Y'
}
else
{
if(#ISEMPTY(temp.tis_programmtyp_filter)) { }
else
{
AND tis_programme_v.type = '#SUB(temp.tis_programmtyp_filter)'
}
if(#ISEMPTY(temp.tis_programmfilter)) { }
else
{
AND tis_programme_v.programm LIKE '#SUB(temp.tis_programmfilter)%'
}";
var result = this.Parse(testString);
var finalResult = this.GenerateDsl(result);
}
public List<IfStatement> Parse(string strToParse)
{
var result = new List<IfStatement>();
var syntaxTree = SyntaxTree.ParseText(#"using System;class C{static void M(){" + strToParse + "}}");
var rootNodes = syntaxTree.GetRoot().DescendantNodes().Where(getRootNodes);
result = rootNodes.Select(n => ToIfStatement(n, null)).ToList();
ApplyNestingLevel(result);
return result;
}
private string GenerateDsl(List<IfStatement> list)
{
var sb = new StringBuilder();
foreach(var ifStmt in list)
{
IfStatementToDsl(ifStmt, sb);
}
return sb.ToString();
}
private string IfStatementToDsl(IfStatement ifStmt, StringBuilder sb)
{
string sqr = "";
for (int i = 0; i < ifStmt.Level; i++)
{
sqr += "'";
}
sb.Append("#IF(");
sb.Append(ifStmt.Condition.ApplyLevel(ifStmt.Level) + "," + sqr);
sb.Append(ifStmt.Statement.ApplyLevel(ifStmt.Level));
if(ifStmt.Childs.Count > 0)
{
foreach(var c in ifStmt.Childs)
{
IfStatementToDsl(c, sb);
}
}
sb.Append(sqr + "," + sqr);
if(ifStmt.Else != null)
{
sb.Append(ifStmt.Else.Statement.ApplyLevel(ifStmt.Level));
foreach(var c in ifStmt.Else.Childs)
{
IfStatementToDsl(c, sb);
}
}
sb.Append(sqr + ")");
return sb.ToString();
}
#region Parsing-Methods
private IfStatement ToIfStatement(SyntaxNode node, SyntaxNode parent)
{
var ifNode = (IfStatementSyntax)node;
var ifStmt = new IfStatement
{
Condition = ifNode.Condition.ToString(),
Statement = GetIfStatement(ifNode),
Childs = GetIfChilds(ifNode)
};
if (ifNode.Else != null)
{
ifStmt.Else = new ElseStatement
{
Statement = GetElseStatement(ifNode.Else),
Childs = GetElseChilds(ifNode.Else)
};
}
return ifStmt;
}
private List<IfStatement> GetIfChilds(IfStatementSyntax node)
{
var childs = node.Statement.DescendantNodes().Where(n => WhereIfNodes(n, node));
return childs.Select(n => ToIfStatement(n, node)).ToList();
}
private List<IfStatement> GetElseChilds(ElseClauseSyntax node)
{
var childs = node.Statement.DescendantNodes().Where(n => WhereElseNodes(n, node));
return childs.Select(n => ToIfStatement(n, node)).ToList();
}
private string GetIfStatement(IfStatementSyntax node)
{
var result = node.Statement.DescendantNodes().Where(n => WhereIfStatement(n, node));
string returnValue = "";
foreach (var n in result)
{
returnValue += n.ToString();
}
return returnValue.CleanString();
}
private string GetElseStatement(ElseClauseSyntax node)
{
var result = node.Statement.DescendantNodes().Where(n => WhereElseStatement(n, node));
string returnValue = "";
foreach (var n in result)
{
returnValue += n.ToString() + " ";
}
return returnValue.CleanString();
}
private void ApplyNestingLevel(List<IfStatement> list)
{
foreach (var item in list)
{
item.Level = _currentLevel;
if (item.Childs.Count > 0 || (item.Else != null && item.Else.Childs.Count > 0))
{
_currentLevel++;
}
ApplyNestingLevel(item.Childs);
if (item.Else != null)
{
ApplyNestingLevel(item.Else.Childs);
}
}
}
#endregion
#region Linq Where-Conditions
private bool WhereIfNodes(SyntaxNode node, IfStatementSyntax parent)
{
if(node.Kind == SyntaxKind.IfStatement && (node.Parent.Parent == parent))
{
return true;
}
return false;
}
private bool WhereElseNodes(SyntaxNode node, ElseClauseSyntax parent)
{
if (node.Kind == SyntaxKind.IfStatement && (node.Parent.Parent == parent))
{
return true;
}
return false;
}
private bool WhereIfStatement(SyntaxNode node, IfStatementSyntax parent)
{
if ((node.Kind == SyntaxKind.ExpressionStatement || node.Kind == SyntaxKind.LocalDeclarationStatement)
&& (node.Parent.Parent == parent))
{
return true;
}
return false;
}
private bool WhereElseStatement(SyntaxNode node, ElseClauseSyntax parent)
{
if ((node.Kind == SyntaxKind.ExpressionStatement || node.Kind == SyntaxKind.LocalDeclarationStatement)
&& (node.Parent.Parent == parent))
{
return true;
}
return false;
}
private Func<SyntaxNode, bool> getRootNodes =
n => n.Kind == SyntaxKind.IfStatement &&
(n.Parent.Parent.Kind != SyntaxKind.ElseClause && n.Parent.Parent.Kind != SyntaxKind.IfStatement);
#endregion
}
public class IfStatement
{
public int Level { get; set; }
public string Condition { get; set; }
public string Statement { get; set; }
public ElseStatement Else { get; set; }
public List<IfStatement> Childs { get; set; }
}
public class ElseStatement
{
public string Statement { get; set; }
public List<IfStatement> Childs { get; set; }
}
public static class Ext
{
public static string CleanString(this string value)
{
return value.Replace("\t", "").Replace("\n", "").Replace("\r", "");
}
public static string ApplyLevel(this string value, int level)
{
int multiplier = level * 2;
if (level == 0)
multiplier = 1;
var sb = new StringBuilder(multiplier);
for (int i = 0; i < multiplier; i++)
{
sb.Append("'");
}
return value.Replace("'", sb.ToString());
}
}
}
I have to write if-else Statements in a Domain-Specific-Language which is really a pain in the ass!
(The DSL is from a Third-Party-Tool which I have to use to generate WHERE-Statements for SQL-Queries)
Syntax:
#IF(#ISEMPTY(#SUB(temp.last_name))),'if true','else')
#SUB() reads a textboxvalue
Sample:
#IF(#ISEMPTY(#SUB(temp.last_name))),'','account_contact.last_name = ''DOE'' ')
you have to double your single-quotes in the else statement and if you want to nest different "if-else" every time you go a level deeper you have to double the doubled single-quotes!
You see it´s not very simple to write if you have complicated contitions...
So I thought I write a parser that transforms a normal if-else statement to this DSL-Syntax!
The Parser should create objects of this class:
public class IfCondition
{
public int ID { get; set; }
public int ParentID { get; set; }
public int Level { get; set; }
public string Condition { get; set; }
public string Content { get; set; }
public string ElseContent { get; set; }
}
based on a Collection of this Objects I could generate the DSL-Statements!
So my Problem is I really don´t have a clue, how to parse a String like this:
IF(#ISEMPTY(#SUB(temp.last_name))) { }
ELSE
{
IF(#SUB(temp.test) = 'Y')
{
account_contact.last_name = 'DOE'
}
ELSE
{
account_contat.first_name = "JOHN"
}
}
can somebody give me a nudge in the right direction?
If you use Roslyn for syntax rewritting. Not to just write about what you can do, here is an easy example.
Basically how it works. You create a syntax tree for your code and then use predefined visitors to visit those nodes you want to rewrite, you replace them by valid C# code and then you can compile this tree and make it work.
EDIT:
Another, more reliable source with an example