Posts tagged ‘C#.NET’

Brute force solution to a birthday riddle

At one point a long time ago, one of my college professors asked our class how many people it would take to put in a room before the probability that two of the people had the same birthday was greater than or equal to 50 percent, took guesses from a few of us students, and then told us the answer was 12. Coming from a professor, this had to be true.

That answer has not sat well with me lo these many years since my drinking days, so sitting here with nothing else to do, I decided to try a little Monte Carlo problem solving.

Here is my VS 2008 C# console application code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Birthdays
{
    class Program
    {
        static int numberOfRuns;
        static int[] numberOfPeople;
        static List<int> birthdays;
        static Random rand;
 
        static int GetABirthday()
        {
            int b;
            int maxDays = (rand.Next(1, 5) == 1) ? 367 : 366;
 
            b = rand.Next(1, maxDays);
 
            return b;
        }
 
        static void Main(string[] args)
        {
            rand = new Random();
 
            Console.WriteLine("Birthdays application");
 
            Console.Write("How many times would you like to run a birthday search? ");
            string s = Console.ReadLine();
            numberOfRuns = Convert.ToInt32(s);
 
            numberOfPeople = new int[367];
            for (int i = 0; i < 367; i++)
            {
                numberOfPeople[i] = 0;
            }
 
            Boolean leaveLoop;
            int b;
            int leapDayMatches = 0;
            int leapDayBirthdays = 0;
            int totalBirthdays = 0;
            for (int i = 1; i <= numberOfRuns; i++)
            {
                birthdays = new List<int>();
                leaveLoop = false;
                while (!leaveLoop)
                {
                    b = GetABirthday();
                    totalBirthdays++;
                    if (b == 366)
                    {
                        leapDayBirthdays++;
                    }
                    if (birthdays.Contains(b))
                    {
                        numberOfPeople[birthdays.Count() + 1]++;
                        leaveLoop = true;
                        if (b == 366)
                        {
                            leapDayMatches++;
                        }
                    }
                    else
                    {
                        birthdays.Add(b);
                    }
                }
            }
 
            Console.WriteLine();
            Console.WriteLine("Breakdown of number of people required:");
            int ctr = 0;
            for (int i = 2; i <= 366; i++)
            {
                if (numberOfPeople[i] != 0)
                {
                    ctr += numberOfPeople[i];
                    Console.WriteLine(string.Format("{0} people: {1} ({2:P})", i, 
                                        numberOfPeople[i], ctr * 1.0 / numberOfRuns));
                }
            }
            Console.WriteLine(string.Format("Total birthdays generated: {0}", 
                                                totalBirthdays));
            Console.WriteLine(string.Format("Leap day birthdays: {0}", 
                                                leapDayBirthdays));
            Console.WriteLine(string.Format("Leap day matches: {0}", 
                                                leapDayMatches));
            Console.WriteLine();
            Console.WriteLine("Strike any key to end the program");
            Console.ReadKey();
        }
    }
}

The answer yielded by the above code is 23, as any meaningful sample size plugged into the program above will demonstrate.

Of course, we did not have the internet back then, but now a quick Google search yields plenty of discussion of the theory and math behind the puzzle. If you are interested, click this link.

Subversion operations on Visual Studio 2008 solution take forever

Well, not literally, just a very very long time.

Our Subversion source repository has grown to be quite sizable over the past couple of years. We have always used TortoiseSVN and VisualSVN to tame this beast, and it has usually not let us down.

However, a while back, something bad happened to a VS 2008 solution in the repository. When launching the solution, the refresh of the version control status indicators next to the files in the solution take a very long time to appear and/or refresh, and any kind of operation done on the solution file (such as update, repo browser, etc.) goes back to the root of the whole repository instead of working with the folder where the solution file lives.

Strangely enough, operations done on any of the components inside of the solution does the right thing. In other words, if I update a project in the solution from Visual Studio, it works lightning fast.

I finally got tired of wasting 2 to 10 minutes per operation on the solution and studied this problem by comparing this malfunctioning solution with one that appears to do what you would expect it to. One thing I noticed right away was that the speedy project contained the following lines at the bottom of the solution file (opened in your favorite text editor, of course):

    GlobalSection(ExtensibilityGlobals) = postSolution
        VisualSVNWorkingCopyRoot =
    EndGlobalSection
    GlobalSection(SubversionScc) = preSolution
        Svn-Managed = True
        Manager = AnkhSVN - Subversion Support for Visual Studio
    EndGlobalSection

I added these lines to the bottom of my sluggish solution file and re-opened it, and I now predict explosive advances in my productivity. Or at least more time for tweeting.

Now all I need to do is figure out how to remove these disabled “DSL Tools”, “Text Transformation”, “Workflow”, and “ANTS 4” menu items from my VS 2008. Anyone have any ideas? (EDIT: John Boker has found the solution, see the comments.)

EDIT, PART DEUX: I tried this fix on a different existing Visual Studio project on 9/23/2009, and of course it didn’t work. I studied the problem a bit more, and found that if I added the GlobalSection(SubversionSCC) section that I have already inserted into the code block above, it did the trick for me. (Even though I am not actually using AnkhSVN, I am using TortoiseSVN, so I am guessing the Manager line is not important. However, I have left it in there for completeness.)

NetCFSvcUtil and Windows 7

So I have, for the most part, got the new development machine all set up and running pretty well. But ah, there is always a fly in the ointment…

I have a Windows Mobile client application that talks to a WCF service to move data back and forth. I have been using a batch file that I created that ran the NetCFSvcUtil.exe program included in the Power Toys for .NET Compact Framework 3.5. This tool reads information from the provided URL of the web service and creates C# or VB.NET source files that can be included in your project.

And of course, this utility program does not work on my shiny new Windows 7 RC machine, it gives the following error:

Attempting to download metadata from 'http://www.site.net/Service.svc'
using WS-Metadata Exchange or DISCO.
Error: An error occurred in the tool.
Error: Error in the application.

Some searching for this problem yielded the following posts:

NetCFSvcUtil.exe and Windows 7

Ambiguous error message from NetCFSvcUtil.exe

These links appear to indicate that the NetCFSvcUtil does not work on Windows 7 and there is no workaround just yet. And now I have a nice shiny new VirtualBox Windows XP image that contains installs of the .NET Compact Framework 3.5 with the Power Toys, and a copy of my old batch files, along with a shared folder that I can grab the files when I need them. Thanks Microsoft!

However, it appears that Microsoft does not have the market cornered on “D’oh!” backwards compatibility moments. It appears that some users have had some issues with the load times of Firefox 3.5, and believe it or not, removing the cookies and temporary internet files associated with IE can actually help. I will give you a link to look at while you ponder this interesting nugget.

The Firefox 3.5 fiasco

I guess you could say that Mozilla is a big believer in the More Randomer theory.

When 5.95 does not equal 5.95

People like nicely formatted numbers on their reports and web pages. For example, if I needed to display the results of a division where the dividend is 1 and the divisor is 3, typically I would display that as 0.3 (the number formatted to 1 decimal place) instead of 0.3333333.

So imagine my surprise when I had a single detail line in my report where a value is shown as 6.0, but in the total line right below it (which utilizes the same data since there is only the one detail line), the same value is displayed as 5.9.

We finally tracked the problem down to a conversion between a float to a double. It appears that the .NET runtime is not able to take a float value of 5.95 and convert it exactly to a double of 5.95, the conversion sets the double to 5.94999980926514. As a result, when this value was sent into the string formatting function, the value would round down instead of rounding up. Keep in mind that the divisions actually come out right, whether they are floats or doubles. As I stepped through the code, all looked well since the float variable was calculating as 5.95 (119 divided by 20), but this was of course before the conversion and formatting.

As I think about it, I was pretty lucky to find this little glitch, as it will only manifest itself when for certain dividends when the divisor is a multiple of 20. (The 1 decimal place round off error happens at multiples of 0.05, or 1 / 20.) Feeling interested, I decided to do a little experimentation. I am married and over the hill, what else am I going to do on a Friday night?

I set up a .NET C# console application to test out the divisions, conversions, and string formatting, and reporting on when the formatted string of the double varies from the formatted string of the float converted to a double. The divisor would loop from 20 to 1000 by 20, and the dividend would loop from 1 to 1000. The final results were:

Divisions tested: 50000
Divisions failed: 916
Failure percentage: 1.83 %

As expected, the divisor of 20 shows the most variations, and dropped off to only 4 variations with a divisor of 1000 (at 350, 450, 650, and 950).

The moral of the story is when it comes to floats, just say no. We went into the code and removed all the float variables and casts and changed them all to doubles.