Category Archives: C#

Finding first unique number.

Introduction

Recently I took a test to find the first unique number in an array.  I did manage to produce the right answer but it was computationally too expensive.  This post is the result of looking into alternatives

Original Solution

var y = numberArray.GroupBy(z => z).Where(z => z.Count() == 1)
                                   .Select(z => z.Key).ToList();
 if (y.Count > 0) actual = y[0];

Alternatives

I asked for help on Stack Overflow as I wanted to see how other devs approached the solution and the following are alternatives where suggested.

  1. Change from y.Count to y.Any
  2. numberArray.GroupBy(g => g).Where(w => w.Count() == 1).Select(s =>    s.Key).FirstOrDefault();
  3. numberArray.ToLookup(x => x).First(x => x.Count() == 1).Key;
  4. numberArray.GroupBy(x => x).First(x => x.Count() == 1).Key;

In order to make head or tail of the speed difference I decided to run some tests, the template for each test is.

    var sw = new System.Diagnostics.StopWatch2() { ShowStatsForEachLoop = false };
    int actual = 0;
    //////////////////////////////////////
    sw.Restart();
    sw.Start();
    for (int i = 0; i < Iterations; i++)
    {
       ///
         Find comparison here
       ///
        sw.RestartAndLog();
    }
    sw.Stop();

Test Results

All solutions where run 50 times with an array of 9 numbers the last number being the unique number.
The results below record the average number of CPU ticks for each test.

Ticks
   Min   Max     Avg  Result
    2  14502     584  -3     Original
    2    919      40  -3     if (y.Any()) actual = y[0];
    2   1423      60  -3     a.GroupBy(g => g).Where(w => w.Count() == 1)
                                            .Select(s => s.Key)
                                            .FirstOrDefault();
    2   1553      65  -3     a.ToLookup(i => i).First(i => i.Count() == 1).Key;
    2    317      15  -3     a.GroupBy(i => i).First(i => i.Count() == 1).Key;
    1     4        2  -3     Traditional method.

Conclusion

If using LINQ switching to use .Any() was surprising how big a difference it made.
The other surprise was the difference between .GroupBy() and .ToLookup()

Using a traditional nested-loop produces very much faster results.


actual = -1;
for (int a = 0; a < numberArray.Length; a++) {
    bool unique = true;
    for (int b = 0; b < numberArray.Length; b++) {
        if (a == b)
        continue;
        if (numberArray[a] == numberArray[b]) {
            unique = false;
            break;
        }
    }
    if (unique) {
        actual = numberArray [a];
        break;
    }
}

Source Code

The source code can be found on gitHub @ https://github.com/hungrydev/FirstUniqueNumberExporation

 Acknowledgments

Git hub user Momenso for implementing the traditional method.

Those who responded to my StackOverflow question http://stackoverflow.com/questions/24603994/find-first-unique-number/24629083#24629083

 

 

Advertisements

Generating random phrases

Introduction

Some times when I am testing applications I have need random sentences or text files to be generated on the fly of various lengths.  This post will show how one way to do that.

Generating the Sentences

To generate a sentence the following steps need to be taken.

  1. Split a list of words
  2. Take a word at random from the list and put in collection.
  3. Repeat step 2 until you have enough words for you sentence.
  4. Repeat steps 2 and 3 for number of sentences and paragraphs that you require.

A more detailed description generating test sentences can be found at http://www.dotnetperls.com/random-paragraphs-sentences

Usage

I have published a package on NUGET for ease of use at https://www.nuget.org/packages/System.Diagnostics.TestData/

var target = new RandomText();
const int numberParagraphs = 1;
const int minSentences = 4;
const int maxSentences = minSentences;
const int minWords = 4;
const int maxWords = minWords;
target.AddContentParagraphs(numberParagraphs, minSentences, maxSentences, minWords, maxWords);
//Get your randomly generated phrase from here
string randomPhrase = target.Content;
References

http://www.dotnetperls.com/random-paragraphs-sentences – where the core part of the code came from.

 

 

MSMQ counting comparisions

Introduction

Recently I needed to create a means of visually monitoring the number of messages in multiple message queues.  This should of been relatively simple, create a UI to display the result from myMessageQueue.Count(), however the count method does not exist as part of the message queue class.
This post looks at the various different methods that you can use to count.

Cursor Method

When I searched for a solution most of the comments where using cursors.  This was the method that I initially used but when I had about > 35,000 messages I found the count to be wildly erratic. The more messages you have in your queue the longer this method will take to count. For a full description of using cursors with MSMQ have a look on Microsoft http://support.microsoft.com/kb/178516.

private MessageQueue _messageQueue;
private int CountCursor()
{
    _messageQueue = new MessageQueue(".\\private$\\pingpong", QueueAccessMode.Peek);
    int count = 0;
    Cursor cursor = _messageQueue.CreateCursor();
    Message m = CursorPeekWithoutTimeout(cursor, PeekAction.Current);
    if (m != null)
    {
        count = 1;
        while ((m = CursorPeekWithoutTimeout(cursor, PeekAction.Next)) != null)
        {
            count++;
        }
        if (m != null) m.Dispose();
    }
    cursor.Dispose();
    return count;
}
protected Message CursorPeekWithoutTimeout(Cursor cursor, PeekAction action)
{
    Message ret = null;
    try
    {
        ret = _messageQueue.Peek(new TimeSpan(1), cursor, action);
    }
    catch (MessageQueueException mqe)
    {
        if (mqe.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
        {
            throw;
        }
    }
    return ret;
}

GetAllMessages Method

GetAllMessages returns a static copy of the messages in the queue, this is fine for small one off counts. In the real world you could have several hundred thousand large messages in the queue so to reduce the amount of information bought back we need to set up a message filter. The more messages you have in your queue the longer this method will take to count.

var _messageQueue = new MessageQueue(".\\private$\pingpong", QueueAccessMode.Peek);
var countFilter = new MessagePropertyFilter
                        {
                            AdministrationQueue = false,
                            ArrivedTime = false,
                            CorrelationId = false,
                            Priority = false,
                            ResponseQueue = false,
                            SentTime = false,
                            Body = false,
                            Label = false,
                            Id = false
                        };
_messageQueue.MessageReadPropertyFilter = countFilter;
return _messageQueue.GetAllMessages().Length;

GetEnumerator2 Method

GetEnumerator2 returns a dynamic list of messages in the queue.  The more messages you have in your queue the longer this method will take to count.

var _messageQueue = new MessageQueue(".\\private$\pingpong", QueueAccessMode.Peek);
var x = _messageQueue.GetMessageEnumerator2();
int iCount = 0;
while (x.MoveNext())
{
   iCount++;
}
return iCount;

PowerShell (WMI) Method

This is by fastest method by far taking about 20ms regardless of how may messages there are to count. This is the only method for counting the message queues on other machines that you have access to.  It requires power shell to be installed on your machine.

private int GetPowerShellCount()
{
    return GetPowerShellCount(".\\private$\pingpong", Environment.MachineName, "", "");
}
private  int GetPowerShellCount(string queuePath, string machine,string username, string password)
{
    var path = string.Format(@"\\{0}\root\CIMv2", machine);
    ManagementScope scope;
    if (string.IsNullOrEmpty(username))
    {
            scope = new ManagementScope(path);
    }
    else
    {
        var options = new ConnectionOptions {Username = username, Password = password};
        scope = new ManagementScope(path, options);
    }
    scope.Connect();
    if (queuePath.StartsWith(".\\")) queuePath=queuePath.Replace(".\\",string.Format("{0}\\",machine));
    
    string queryString = String.Format("SELECT * FROM Win32_PerfFormattedData_msmq_MSMQQueue");
    var query = new ObjectQuery(queryString);
    var searcher = new ManagementObjectSearcher(scope, query);
    IEnumerable<int> messageCountEnumerable =
        from ManagementObject queue in searcher.Get()
        select (int)(UInt64)queue.GetPropertyValue("MessagesInQueue");
    //IEnumerable<string> messageCountEnumerable =
    //  from ManagementObject queue in searcher.Get()
    //  select (string)queue.GetPropertyValue("Name");
    var x = messageCountEnumerable.First();
    return x;
}

Testing

I decided to create a test that would count the messages and count the timing for the messages to be counted. To run the tests included in source code you need to create a private MSMQ on your machine, the name of the queue does not matter as the application will use the first private queue it finds. The test application needs to run as an administrator as you will be purging the message queue before each tests start.

MSMQcounts

Source Code

The source code can be found on GitHub @ https://github.com/hungrydev/MessageQueueCounts.

References

Post History

This article is a copy of a post I wrote on the Code Project website and can be found here along with the source code.