private void GenerateButton_Click(object sender, RoutedEventArgs e)
        {
            var listRand = new ListRand();

            // Let's have some fun with TPL
            var nums = Enumerable.Range(0, NODES_COUNT-1).ToArray();

            // Just a balanced partitioner
            var partitioner = Partitioner.Create(nums, true);

            var nodes = partitioner.AsParallel().Select(i =>
            {
                var newNode = new ListNode
                {
                    Id = Guid.NewGuid(),
                    Data = string.Format("Node{0} Data", i)
                };

                return newNode;
            }).ToList();

            var rand = new Random(Environment.TickCount);

            ListNode previous = null;
            foreach (var node in nodes)
            {
                node.Previous = previous;
                node.Random = nodes[rand.Next(0, nodes.Count)];

                if (previous != null)
                {
                    previous.Next = node;
                }

                previous = node;
            }

            listRand.Count = nodes.Count;
            listRand.Head = nodes.First();
            listRand.Tail = nodes.Last();

            _lastListRand = listRand;

            PrintList(listRand, GeneratedListTextBox);
        }
Ejemplo n.º 2
0
        // Changed to just a stream to make it possible to deserialize from memory stream
        public void Deserialize(Stream stream)
        {
            // Again, we do not going to manage the stream here since it was initialized somewhere outside.
            // The only we can do here is to catch the errors while reading to rethrow with meaningful message.
            var reader = new StreamReader(stream);

            var serializedString = reader.ReadToEnd();

            // Just a simple regex matching the pattern like
            //'Id:a5c2e13e-85af-40b8-9633-4c9e1c001f62;Prev:00000000-0000-0000-0000-000000000000;Next:59bee4b3-645c-4184-9502-508d5d23096d;Rand:59bee4b3-645c-4184-9502-508d5d23096d;Data:Node1 Data'
            var regex = new Regex(@"((Id:[;:\w\d\s-]+?);[\s])", RegexOptions.Multiline);

            var nodeStrings = new List<string>();

            var matches = regex.Matches(serializedString).OfType<Match>();
            foreach (var match in matches)
            {
                // Groups[0] - whole match; Groups[1] - outer group (equal to whole match; seems redundant); Groups[2] - w/o trailing ';' and linebreak
                var matchWithoutTrailingSemicolon = match.Groups[2].Value;

                nodeStrings.Add(matchWithoutTrailingSemicolon);
            }

            var nodes = new List<ListNode>(nodeStrings.Count);

            // Creating the cross nodes references Dixtionary. Using the Tuple for simplicity
            // Assuming the Tuple of Previous; Next; Random node ids
            var references = new Dictionary<Guid, Tuple<Guid, Guid, Guid>>();

            // Just a simple Regex to extract field values
            var idRegex = new Regex("Id:(.+?);");
            var prevRegex = new Regex("Prev:(.+?);");
            var nextRegex = new Regex("Next:(.+?);");
            var randRegex = new Regex("Rand:(.+?);");
            var dataRegex = new Regex("Data:(.+?)$");

            nodeStrings.ForEach(ns =>
            {
                // I know it is BAD to not check IsMatch and Groups count
                // It is not needed in case of such simple task. Just ommiting the flood of If... Else.
                var id = Guid.Parse(idRegex.Match(ns).Groups[1].Value);
                var prevId = Guid.Parse(prevRegex.Match(ns).Groups[1].Value);
                var nextId = Guid.Parse(nextRegex.Match(ns).Groups[1].Value);
                var randId = Guid.Parse(randRegex.Match(ns).Groups[1].Value);
                var data = dataRegex.Match(ns).Groups[1].Value;

                nodes.Add(new ListNode { Id = id, Data = data });
                references.Add(id, new Tuple<Guid, Guid, Guid>(prevId, nextId, randId));
            });

            nodes.ForEach(n =>
            {
                // There should be a value with given Id in Dictionary
                // For safety we can add a check and skip if there no value in Dictionary
                var reference = references[n.Id];

                // If Previous Id is Guid.Empty, then this node is a head and Previous reference should be void
                if (reference.Item1 != Guid.Empty)
                {
                    n.Previous = nodes.Single(o => o.Id == reference.Item1);
                }
                else
                {
                    // Assign the Head reference here
                    this.Head = n;
                }

                // If Next Id is Guid.Empty, then this node is a Tail and Previous reference should be void
                if (reference.Item2 != Guid.Empty)
                {
                    n.Next = nodes.Single(o => o.Id == reference.Item2);
                }
                else
                {
                    // Assign the Tail reference here
                    this.Tail = n;
                }

                n.Random = nodes.Single(o => o.Id == reference.Item3);
            });

            this.Count = nodes.Count;
        }