Menu

The results of excessive hubris

May 11, 2015 - Programming

I recently discovered, via reddit, a link to another programming-oriented blog. There, the Blogger indicates that they have created 5 problems, and, if anybody cannot solve all of them within an hour, then they should not be called a programmer.

Already this reeks of a “fizzbuzz” style test, but we get a nice dose of hubris as he prescribes that he has some authority to say when other people should or should not list themselves as programmers.

However, what really took the case was inevitable- in his series of blog posts- (which he cannot demononstrate as having written all within an hour, I might add) he provides an incorrect solution. Therefore, by his own definition, he should no longer call himself a programmer. The end result is basically like somebody saying “Only idiots have problems with they’re grammar”

In the interest of something coding related, let’s see what that problem… problem was, and try to create a C# solution. I won’t be arguing that anybody unable to solve it shouldn’t call themselves a programmer, mostly because I suspect I may make mistakes myself- and claims that require such perfection of me are likely to result in some well-placed “karma”.

Write a function that given a list of non negative integers, arranges them such that they form the largest possible number. For example, given [50, 2, 1, 9], the largest formed number is 95021.

I took a rather- brute force approach:

Basically it takes all the permutations of the list if elements returned and finds the permutation that results in the largest number when concatenated. No doubt this can be made more efficient. However…

Requirements

Having specific requirements is important. In this case, the academic exercise did not come with any requirements, and all the test cases provided are incredibly short. Therefore, it is reasonable to create an implementation that works best for short lists of items. It also doesn’t suggest that speed is important- it doesn’t say to make the method as fast as possible- it merely dictates the expected output. The method I wrote does it rather brutally but is IMO easier to reason about.

Or, that is what I would say- if it worked! What happens? Well, if we give it {17,32,5,16,500}, it tells us 1755003216, but the correct answer is 5500321716. How did the brute force algorithm go so wrong?

The answer is deceptively simple and is localized in our GetFullValue() function. The intent of this function is to take an enumeration of integers, slap them together into a string, and then parse them back into an integer. You can perhaps see where things go wrong. The “real” answer- 5500321716- is larger than the maximum size of an int. TryParse fails, and the function returns 0, which means the “correct” value gets sorted as 0.

The “Fix” is to replace the int with a decimal data type for that function, and the function works again. It should be noted that this is a less-than-performant solution by quite a margin- and in fact, it’s even longer than the alternative, which compares the concatenation of the first and second value with the concatenation of the second and first value and inverts the result. Here is a full implementation which uses/compares both versions, including timing:

Overall, an interesting problem. I don’t think that being unable to solve it in an hour means a person needs to hand in their programming badge and gun, though. I like to think of such problems as “watertight” abstractions- this is in contrast to a leaky abstraction. When designing an algorithm, the implementation can be of importance. For example if an algorithm deals with Invoice numbers and we know that no invoice number can start with 1, than that can be applied to optimize any number of algorithms to save time. These sorts specifics tend to prevent the implementation and use of a “pure” academic implementation of any number of algorithms. That isn’t to suggest such exercises are futile, as it is often nice to simply attack a problem that doesn’t have annoying unknowns and require tracing through a 25-year history of ancient data schemas in order to properly reason about.

Have something to say about this post? Comment!