Wednesday, February 8, 2012

FizzBuzz

Apparently, the "FizzBuzz" problem is a common programming interview question. I came across it while reading You Can't Teach Height - Measuring Programmer Competence via FizzBuzz on Scott Hanselman's blog.

The "FizzBuzz" problem is:
Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.
After reading this, my first thought was to write code to solve the problem. Funny that the end of Hansleman's post states:
One other thing that's amazing to me ... is that some of the programmers who read these blogs feel the need to actually solve the FizzBuzz problem.
They've completely - no, I need a work with more oomph - utterly? missed the point.
I'm pretty sure the point of his post is just that an interviewer should ask the applicant to show what he/she can do, rather than just talk about it. I agree with this. And I always have a better feeling about a place where I interview if they at least have me provide code samples and have me talk about them.

But I've got to agree with one of the commenters:
Missed the point?? Developers are problem-solvers - OF COURSE we're going to try to code a solution! :-)
I love puzzles. So I tried coding it without looking up anything, then compiling to see if it worked. I first used a switch/case statement, so that if a number was both a multiple of 3 and 5, it would fall through both and output "FizzBuzz" without needing a separate case to handle both, something like this:

switch (i)
{
    case i % 3 == 0:
        Console.WriteLine("Fizz");
    case i % 5 == 0:
        Console.WriteLine("Buzz");
    default:
        Console.WriteLine(i);
}

Whoops. C# only allows constants in switch/case statements, and it doesn't support break fall-throughs, either (need to use "goto"!). So I tried to mimic it with regular if/then statements. But at the same time, I also had the idea to make it a method, so I ended up with this:

using System;
using System.Collections;
using System.Text;

namespace FizzBuzz
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (string i in fizzBuzz())
            {
                Console.WriteLine(i);
            }

            Console.ReadLine();
        }

        private static IEnumerable fizzBuzz()
        {
            bool isReplaced = false;

            for (int i = 1; i < 101; i++)
            {
                if (i % 3 == 0)
                {
                    yield return "Fizz";
                    isReplaced = true;
                }

                if (i % 5 == 0)
                {
                    yield return "Buzz";
                    isReplaced = true;
                }

                if (!isReplaced)
                {
                    yield return i.ToString();
                }

                isReplaced = false;
            }
        }
    }
}
This works, but for numbers like 15, it outputs Fizz and Buzz on two separate lines. It would be better off combining the 3 and 5 multiple case first, and having one if/else statement.

By the way, this doesn't loop twice - it starts the loop in main, goes into the fizzBuzz method, runs the logic until it gets to a "yield" statement, then finishes the loop in main, then runs the next iteration of the loop. It then picks up where it left off in the fizzBuzz method. This approach would let you format each string iteration differently if you wanted to (i.e. having the word "Fizz" output in green).

So my next thought was to compare my solution to others. I found this, which has a number of solutions in many different languages (none use the enumerable interface idea).

The Articulating Ideas blog has a really interesting post on efficient ways to solve the problem using C# - the bitwise operator one is very interesting (and a bit beyond my current coding skills):

string[] messages = new string[]{null, "Fizz", "Buzz", "FizzBuzz"};
int acc = 810092048; //11 00 00 01 00 10 01 00 00 01 10 00 01 00 00
int c = 0;
for (int i=1; i < = N; ++i)  {
    c = acc & 3;
    result += (c > 0 ? messages[c] : i.ToString()) + ", ";
    acc = acc >> 2 | c < < 28;
}


I'm surprised that this solution wasn't the clear winner (it tied another very slick version that doesn't use modulo, and was only a little faster than another using modulo). Division is usually the most expensive math operation, and shifting bits lets you get around that very cleverly (if you are clever enough to know how to use it...).

It really is true that 100 different programmers will come up with 100 different solutions to the same problem.

Saturday, February 4, 2012

C# "??" operator

I just ran across something I hadn't seen before - a two question mark operator. I found it in the AccountMembership service method in the default AccountModel.cs file that's used when you start a new ASP.NET MVC 3 project. Here's the line of code:
_provider = provider ?? Membership.Provider;
I did a little research and found it's just a shortcut for this, using an iif/conditional:
_provider = provider != null ? provider : Membership.Provider;
which of course is a shortcut for this regular if statement:
if(provider != null) {
     _provider = provider;
} else {
     _provider = Membership.Provider;
}

More info here: http://msdn.microsoft.com/en-us/library/ms173224.aspx
Very cool. I love the terseness of C#.

Thursday, October 13, 2011

Not happy with .NET's FileSystemWatcher

I created a Windows Service to watch for a specific file, which heavily relies on the FileSystemWatcher class. I'm not sure it was worth the hassle over using Timer to just check for the file at a certain interval.

FileSystemWatcher fires an event when a file is created, which is great, except that it seems that it fires the millisecond the file starts to be created (acting more like a "Creating" event...). This was causing problems for me, because my relatively small file was apparently still being written to while I was trying to send it as an attachment and subsequently delete it. There is no "ReallyDoneBeingCreated" event. There is a "Change" event, but that was causing me even more problems.

I ended up adding "Thread.Sleep(30000)" (waits for 30 seconds) after it sees there is a new file. This is crap. I HATE doing stuff like this, but it works, since it takes about a second to create the file in my case. The only other thing I could think of doing is having some crazy recursive try/catch loop that fails, tries again and again until it succeeds. This is ugly, too, but would probably be better if the file size was unknown.

My kludge is upsetting me to the point that I may just end up re-writing the code to use a timer interval to check for a new file, but that is a bit backwards,  too. Can't win. Anybody know of a better way of doing this?

Friday, September 9, 2011

Converting a QuickTime .mov (ProRes codec) to a Windows AVI

On the phone last month to our video production agency, I told them I could work with any video format. Yesterday I was afraid they had proved me wrong.

They sent me a QuickTime .mov encoded with the ProRes codec. This was their source format, and the goal was to ensure no loss of quality on their side, so this wasn't just some crazy attempt on their part to trip me up :-). In any case, I figured any standard video converter (like AVC) could handle this, but nothing I tried worked. I then remembered the amazing FFMPEG from my DVR-building days, and was sure this could easily do the conversion if I could just figure out the correct command-line args. Still no luck. I kept getting the error, "swScalar: Unknown format is not supported as input pixel format". Some searching provided some clues that this was due to mapping, so based on a forum post suggestion, I tried adding the flags, "-map 0:0 -map 0:1". I then got a "codec type mismatch error". I installed the ProRes QuickTime decoder, but this didn't help either.

Finally, I happened upon the following solution:

- install AviSynth (http://avisynth.org/mediawiki/Main_Page)
- add the QTSource dll to AviSynths "plugins" directory (http://www.tateu.net/software/dl.php?f=QTSource)
- install VirtualDub (http://www.virtualdub.org/)

Then you just need to write an AviSynth script in the same directory as the video file and name it with an ".avs" extension:
QTInput("C:\test.mov", audio=1)
BicubicResize(720,486,0.1,1.00).AssumeFPS(29.97)

(BTW, the documentation for QTSource says to use audio=true, but AviSynth was having none of that.)

- open the .avs file as if it was a video in VirtualDub
- save as .avi

Whew. I was about five minutes away from admitting defeat and asking them for a different format. Aside from bruising my ego a bit, this would have wasted at least another day or two that I didn't have to spare.

Thursday, July 28, 2011

C# recursive file counter

I am constantly surprised with how easy .NET makes things sometimes. I needed a quick recursive file counter output to a report, and was able to write this in just a few minutes, using some new methods available in .NET 4 (EnumerateFiles/Directories) (UPDATE: not sure what I was thinking here - .GetFiles()/.GetDirectories() provides pretty much the same thing - array vs. generic list):

static void Main(string[] args)
{
   string startingDir = @"C:\files";
   string reportFile = @"C:\file_count.txt";

   using (StreamWriter report = new StreamWriter(reportFile))
   {
        countFiles(startingDir, report);
   }
}

private static void countFiles(string dir, StreamWriter report) {
   DirectoryInfo directory = new DirectoryInfo(dir);
   IEnumerable<FileInfo> files = directory.EnumerateFiles();
   IEnumerable<DirectoryInfo> dirs = directory.EnumerateDirectories();

   report.WriteLine(String.Format("{0}: {1}", dir, files.Count()));

   foreach (var d in dirs)
   {
        countFiles(d.FullName, report);
   }
}


It works very quickly (100,000 files in as much as 8 directories deep in less than 30 seconds on a modest machine), and couldn't have been more straightforward to write.

BTW, if all you need is just a total file count, this works well:

DirectoryInfo d = new DirectoryInfo(startingDir);
int totalCount = d.EnumerateFiles("*.*", SearchOption.AllDirectories).Count();


After thinking about this some more, I wonder if this may even be easier/more efficient with LINQ. I've got to try that for fun, and check the performance of each.

Wednesday, July 20, 2011

Graphical Saccades

My son is working through some vision issues, and one of the exercises his vision therapist has him do is called "saccades", basically quick movements of the eyes in the same direction. She gave us a web site that had an animated gif that sequentially displayed a bunch of lines of numbers, at varying distances apart.

This was quite boring for my son, so my wife had an idea for me to make a version of this with pictures of things that he liked. He absolutely LOVES this version of the "game", and wants to play it all the time!

The exercise randomly displays 20 images at varying distances (five lines with four images per line), and can include the same image more than once. The speed can be adjusted before the run, or in progress.

From what I understand, the important part of the exercise is just to track and identify sequentially revealed items at the same pace, but at varying distances apart. I would love to hear from any vision therapists out there, though, to make sure that this is correct, and that a graphical version still satisfies the objective. Our therapist is out for a few weeks, so I can't ask her about it now, but I'll update the post when I get any new information.

If you want to try it out yourself, here's a zip file (under the Google Docs icon, click "File" --> "Download Original") with the code and a few sample images. It's set up to go with 30 random images, but it's easily customizable if you want to use your own images, or add more. To run it, just unzip the .zip file, and double-click on the .html file that best fits your screen.

In the meantime, I'm working on getting the exercise set up on its own web site, but I'm having a hard time finding a free web site provider that allows HTML.

Technically, this was a breeze to do with jQuery. I define an array of images, and use code similar to JavaScript built-in "setTimeout", but with the ability to adjust the interval in progress (thanks, Peter Bailey, for the brilliant function). The key lines are:

vi = setVariableInterval(function() {
if (currentItem == 20) {
this.stop();
}

randomSpacer = Math.floor(Math.random() * maxPixelLength) + minPixelLength;
randomPicture = Math.floor(Math.random() * pictures.length);

replacementPic = "<img class='p' src='" + pictures[randomPicture].src + "' width='100' height='75' style='margin-left: " + randomSpacer + "px;' />";
$(pics[currentItem]).replaceWith(replacementPic);

currentItem++;
}, initialInterval);

"randomSpacer" and "randomPicture" create random numbers up to the defined maximums. And the jQuery line just replaces each placeholder with a random image. "pics" lets me access via index all images that use the "p" class (they are initially set up with placeholders).

pics = $(".p");

Thursday, June 9, 2011

Avoiding the "Destination configuration already initialized" error in SAP .NET Connector 3

SAP's documentation suggests using a line similar to the following to create a connection to SAP:

RfcDestinationManager.RegisterDestinationConfiguration(new Config());

where Config() is a class that contains connection settings.

This works fine, except, you occasionally get the error, "Destination configuration already initialized", because the connection hasn't timed out. SAP's documentation that I've seen (the .chm help file and the "Overview" document) doesn't address this issue at all, and their sample code doesn't contain any examples of how to close a connection.

I've found that the following code works:

Config c = new Config();
RfcDestinationManager.RegisterDestinationConfiguration(c);
...
(processing code)
...
RfcDestinationManager.UnregisterDestinationConfiguration(c);

However, if you've just tried to connect without using "unregister", you'll have to wait until the old connection times out itself before trying the code above (the sample config code SAP provides keeps the connection open for 10 minutes).

Overall, I've found the new SAP Connector 3 to be a HUGE step up from v2, though it is quite a pain having to re-write all of my v2 applications. But I easily prefer a few months of re-writing over being tied to VS2003. Thanks, SAP, for updating this - I thought you had forgotten about us .NET developers.