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*/);
}
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed yesterday.
Improve this question
For expert in algorithm and C#.
The goal is to divide the 50 people into 10 tables. So 5 people per table. Each person has 2 minutes to introduce themselves to the 4 others. Once everyone has introduced themselves, everyone changes tables. And that in 10 rounds. Two people cannot meet twice
Here's the code I have done :
internal class Program
{
private static void Main(string[] args)
{
int biggestNumberOfGroupCreated = 0;
List<Group> biggestGroupes = new List<Group>();
Start:
// Créer une liste de toutes les personnes
List<int> people = new List<int>();
List<Group> groups = new List<Group>();
List<PersonAlreadyUsed> PeopleAlreadyUsed = CreateListPersonAlreadyUsed();
// Generate person name from 1 to 50
for (int i = 0; i < 50; i++)
{
people.Add(i);
}
List<Couple> couples = new();
GenerateCouples(couples);
//Generate 10 rounds
for (int round = 0; round < 10; round++)
{
ResetAlreadyUsedPeople(PeopleAlreadyUsed);
for (int table = 0; table < 9; table++)
{
Group groupe = new();
for (int chair = 0; chair < 5; chair++)
{
if (chair == 0)
{
int randomElement = GetRandomElement(PeopleAlreadyUsed);
groupe.users[chair] = people[randomElement];
Console.WriteLine($"First seated person {people[randomElement]} for round : {round} in table : {table}");
var alreadyUsed = PeopleAlreadyUsed.FirstOrDefault(x => x.Person == randomElement);
alreadyUsed.AlreadyUsed = true;
}
else
{
bool CanBeAdd = false;
int MemoUser = 0;
int u = 0;
int cptInWhileLoop = 0;
while (!CanBeAdd)
{
bool ret = false;
//Check if the new people can be added
for (int c = 0; c < chair; c++)
{
MemoUser = u;
ret = CheckedIfCanBeAdd(u, groupe.users[c], couples);
if (ret == false)
{
break;
}
}
CanBeAdd = ret;
u = GetUnusedPerson(PeopleAlreadyUsed, cptInWhileLoop);
if (u == -1)
{
Console.WriteLine($"All person already used {groups.Count}");
if (groups.Count > biggestNumberOfGroupCreated)
{
biggestNumberOfGroupCreated = groups.Count;
biggestGroupes = new();
foreach (var g in groups)
{
biggestGroupes.Add(g);
}
}
goto Start;
}
cptInWhileLoop++;
}
if (CanBeAdd == true)
{
groupe.users[chair] = MemoUser;
var personAlreadyUsed = PeopleAlreadyUsed.FirstOrDefault(x => x.Person == MemoUser);
personAlreadyUsed.AlreadyUsed = true;
}
}
}
groups.Add(groupe);
}
}
}
private static void GenerateCouples(List<Couple> couples)
{
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 50; j++)
{
if (i != j)
{
couples.Add(new Couple { x = i, y = j, Affected = false });
}
}
}
}
private static int GetUnusedPerson(List<PersonAlreadyUsed> personneDejUtilisees, int cptInWhileLoop)
{
var unusedPeople = personneDejUtilisees.Where(x=>x.AlreadyUsed==false).ToList();
if (unusedPeople.Count==0)
{
return -1;
}
// Retrieve a random element from the list using the random index
try
{
var randomPerson = unusedPeople[cptInWhileLoop];
return randomPerson.Person;
}
catch (Exception)
{
return -1;
}
}
private static void ResetAlreadyUsedPeople(List<PersonAlreadyUsed> personAlreadyUsed)
{
for (int i = 0; i < 50; i++)
{
personAlreadyUsed[i].AlreadyUsed = false;
}
}
private static List<PersonAlreadyUsed> CreateListPersonAlreadyUsed()
{
List < PersonAlreadyUsed > people = new();
for (int i = 0; i < 50; i++)
{
PersonAlreadyUsed dejUtilisee = new() { Person = i, AlreadyUsed = false };
people.Add(dejUtilisee);
}
return people;
}
private static bool CheckedIfCanBeAdd(int p, int v, List<Couple> couples)
{
bool ret = false;
if (p != v)
{
var comb1 = couples.FirstOrDefault(c => c.x == p && c.y == v);
var comb2 = couples.FirstOrDefault(c => c.x == v && c.y == p);
if (comb1.Affected == false && comb2.Affected == false)
{
ret = true;
comb1.Affected = true;
comb2.Affected = true;
}
}
return ret;
}
private static int GetRandomElement(List<PersonAlreadyUsed> personAlreadyUsed)
{
Random rand = new Random();
var peronStillAvailble = personAlreadyUsed.Where(x=>x.AlreadyUsed==false).ToList();
int randomIndex = rand.Next(peronStillAvailble.Count);
int randomElement = peronStillAvailble[randomIndex].Person;
return randomElement;
}
private static void AddCouple(Group groupe, List<Couple> couples)
{
foreach (var u1 in groupe.users)
{
foreach (var u2 in groupe.users)
{
if (u1 != u2)
{
var comb1 = couples.FirstOrDefault(c => c.x == u1 && c.y == u2);
var comb2 = couples.FirstOrDefault(c => c.x == u2 && c.y == u1);
comb1.Affected = true;
comb2.Affected = true;
}
}
}
}
}
public class PersonAlreadyUsed
{
public int Person { get; set; } =0;
public bool AlreadyUsed { get; set; }=false;
}
public class Couple
{
public int x { get; set; }
public int y { get; set; }
public bool Affected { get; set; }
}
public class Group
{
public int[] users { get; set; } = new int[5];
}
It seems that there is no solution.
Do you confirm?
How can I swap two elements of a two-linked list(by switching links)? I realized that I need to consider four cases: change with the first / last elements, change neighboring elements, and all other cases.
The cell structure is as follows:
public class Item<T>
{
private T _Data;
private Item<T> _Next;
private Item<T> _Prev;
public T Value
{
get { return _Data; }
set { this._Data = value; }
}
public Item(T Data)
{
this._Data = Data;
}
public Item()
{
this._Data = default;
}
public Item<T> Next
{
get { return this._Next; }
set { this._Next = value; }
}
public Item<T> Prev
{
get { return this._Prev; }
set { this._Prev = value; }
}
}
This is an implementation attempt. What's wrong?(Here I also do insert sort, but it all depends on the exchange of two elements)
public override D_List<T> Sorting(D_List<T> a)
{
for (int top = 1; top < a.Count; top++)
{
int k = top;
while (k > 0 && a[k-1] > a[k])
{
k--;
}
if (k == 0)
{
a[top].Prev.Next = a[top].Next;
a[top].Next.Prev = a[top].Prev;
a[top].Next = a[k];
a[top].Prev = null;
a[k].Prev = a[top];
}
else if(k == a.Count - 2)
{
a[k].Prev.Next = a[top];
a[top].Prev = a[k].Prev;
a[k].Next = null;
a[k].Prev = a[top];
}
else if(k+1 == top)//стоят подряд
{
a[k].Prev.Next = a[top];
a[top].Prev = a[k].Prev;
a[k].Next = a[top].Next;
a[top].Next = a[k];
a[k].Next.Prev = a[k];
}
else
{
a[k].Prev = a[top];
a[top].Prev.Next = a[top].Next;
a[top].Next.Prev = a[top].Prev;
a[top].Prev = a[k].Prev;
a[top].Next = a[k];
a[top].Next.Prev = a[top];
}
}
return a;
}
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!
The file I'm trying to read is presented in the format below. How using c# can I read this file to extract property values? Are there any libraries I can leverage?
"AppState"
{
"appid" "244210"
"Universe" "1"
"name" "Assetto Corsa"
"StateFlags" "4"
"installdir" "assettocorsa"
"LastUpdated" "1469806809"
"UpdateResult" "0"
"SizeOnDisk" "23498042501"
"buildid" "1251512"
"LastOwner" "76561198018619129"
"BytesToDownload" "11541616"
"BytesDownloaded" "11541616"
"AutoUpdateBehavior" "0"
"AllowOtherDownloadsWhileRunning" "0"
"UserConfig"
{
"language" "english"
}
"MountedDepots"
{
"228983" "8124929965194586177"
"228984" "3215975441341951460"
"228985" "5758075142805954616"
"228990" "1829726630299308803"
"229002" "7260605429366465749"
"244211" "3837890045968273966"
}
"InstallScripts"
{
"0" "_CommonRedist\\vcredist\\2010\\installscript.vdf"
"1" "_CommonRedist\\vcredist\\2012\\installscript.vdf"
"2" "_CommonRedist\\vcredist\\2013\\installscript.vdf"
"3" "_CommonRedist\\DirectX\\Jun2010\\installscript.vdf"
"4" "_CommonRedist\\DotNet\\4.0\\installscript.vdf"
}
}
So I don't know if you still need it, but I wrote it myself.
Here is my code.
In my tests it worked perfectly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Steam_acf_File_Reader
{
class AcfReader
{
public string FileLocation { get; private set; }
public AcfReader(string FileLocation)
{
if (File.Exists(FileLocation))
this.FileLocation = FileLocation;
else
throw new FileNotFoundException("Error", FileLocation);
}
public bool CheckIntegrity()
{
string Content = File.ReadAllText(FileLocation);
int quote = Content.Count(x => x == '"');
int braceleft = Content.Count(x => x == '{');
int braceright = Content.Count(x => x == '}');
return ((braceleft == braceright) && (quote % 2 == 0));
}
public ACF_Struct ACFFileToStruct()
{
return ACFFileToStruct(File.ReadAllText(FileLocation));
}
private ACF_Struct ACFFileToStruct(string RegionToReadIn)
{
ACF_Struct ACF = new ACF_Struct();
int LengthOfRegion = RegionToReadIn.Length;
int CurrentPos = 0;
while (LengthOfRegion > CurrentPos)
{
int FirstItemStart = RegionToReadIn.IndexOf('"', CurrentPos);
if (FirstItemStart == -1)
break;
int FirstItemEnd = RegionToReadIn.IndexOf('"', FirstItemStart + 1);
CurrentPos = FirstItemEnd + 1;
string FirstItem = RegionToReadIn.Substring(FirstItemStart + 1, FirstItemEnd - FirstItemStart - 1);
int SecondItemStartQuote = RegionToReadIn.IndexOf('"', CurrentPos);
int SecondItemStartBraceleft = RegionToReadIn.IndexOf('{', CurrentPos);
if (SecondItemStartBraceleft == -1 || SecondItemStartQuote < SecondItemStartBraceleft)
{
int SecondItemEndQuote = RegionToReadIn.IndexOf('"', SecondItemStartQuote + 1);
string SecondItem = RegionToReadIn.Substring(SecondItemStartQuote + 1, SecondItemEndQuote - SecondItemStartQuote - 1);
CurrentPos = SecondItemEndQuote + 1;
ACF.SubItems.Add(FirstItem, SecondItem);
}
else
{
int SecondItemEndBraceright = RegionToReadIn.NextEndOf('{', '}', SecondItemStartBraceleft + 1);
ACF_Struct ACFS = ACFFileToStruct(RegionToReadIn.Substring(SecondItemStartBraceleft + 1, SecondItemEndBraceright - SecondItemStartBraceleft - 1));
CurrentPos = SecondItemEndBraceright + 1;
ACF.SubACF.Add(FirstItem, ACFS);
}
}
return ACF;
}
}
class ACF_Struct
{
public Dictionary<string, ACF_Struct> SubACF { get; private set; }
public Dictionary<string, string> SubItems { get; private set; }
public ACF_Struct()
{
SubACF = new Dictionary<string, ACF_Struct>();
SubItems = new Dictionary<string, string>();
}
public void WriteToFile(string File)
{
}
public override string ToString()
{
return ToString(0);
}
private string ToString(int Depth)
{
StringBuilder SB = new StringBuilder();
foreach (KeyValuePair<string, string> item in SubItems)
{
SB.Append('\t', Depth);
SB.AppendFormat("\"{0}\"\t\t\"{1}\"\r\n", item.Key, item.Value);
}
foreach (KeyValuePair<string, ACF_Struct> item in SubACF)
{
SB.Append('\t', Depth);
SB.AppendFormat("\"{0}\"\n", item.Key);
SB.Append('\t', Depth);
SB.AppendLine("{");
SB.Append(item.Value.ToString(Depth + 1));
SB.Append('\t', Depth);
SB.AppendLine("}");
}
return SB.ToString();
}
}
static class Extension
{
public static int NextEndOf(this string str, char Open, char Close, int startIndex)
{
if (Open == Close)
throw new Exception("\"Open\" and \"Close\" char are equivalent!");
int OpenItem = 0;
int CloseItem = 0;
for (int i = startIndex; i < str.Length; i++)
{
if (str[i] == Open)
{
OpenItem++;
}
if (str[i] == Close)
{
CloseItem++;
if (CloseItem > OpenItem)
return i;
}
}
throw new Exception("Not enough closing characters!");
}
}
}