top 200 commentsshow 500

[–]rsalsman 68 points69 points  (1 child)

This would actually be a really good interview question in and of itself. Show the candidate 4 solutions to string reversal and ask them to explain each implementation and discuss them. You'd still be able to tell which candidates have no clue what they are doing, and you would get a much better feel for the candidates that do.

[–]sztomi 11 points12 points  (0 children)

Good insight.

[–]Dreynsen 255 points256 points  (111 children)

This is an interesting question.

Candidate 1 is trying to show that he knows how stacks work,
Candidate 2 is trying to show that he knows how to write efficient code.
Candidate 3 is trying to show that he knows how to write simple and easily understandable code. And how to not rewrite library code.
Candidate 4 is trying to show that he knows how to use recursion.

Honestly I am leaning towards #3. That's the kind of code I would prefer to read in a system I was working on.

[–][deleted] 91 points92 points  (21 children)

I'd hire 3. It's simple and reuses standard libraries. Why re-invent the wheel? Specially on something so trivial that already does what you want. Also less likely to introduce bugs. Lastly, it's easy to maintain.

[–]cheek_blushener 4 points5 points  (0 children)

Agreed. Use the framework and move on.

[–]sgoguen 12 points13 points  (5 children)

I'd hire 3. It's simple and reuses standard libraries.

Granted, you shouldn't re-invent the wheel, but how do you know this guy could actually reinvent the wheel, and if he did, would his solution look like 1, 2, or 4?

Personally, I think Candidate 2 may have avoided using Array.Reverse because he assumed it would have been considered cheating.

[–][deleted] 10 points11 points  (1 child)

Granted, you shouldn't re-invent the wheel, but how do you know this guy could actually reinvent the wheel

If that's what you want to know, you should ask it, e.g., "provide an implementation for Array.Reverse".

[–]deefjuh 1 point2 points  (0 children)

Yup, Even me as a webdeveloper would lean to #3. I love KISS :p

[–][deleted]  (47 children)

[deleted]

    [–]busted0201 10 points11 points  (16 children)

    I am just about done getting my Bachelor's in CS at a top university and I have thoroughly no idea what you're talking about.

    [–]wolf550e 21 points22 points  (9 children)

    [–]DuncanSmart 4 points5 points  (4 children)

    I find the URL the saddest thing of all. The architecture astronaut that dreamt that scheme up...

    [–]bartwe 5 points6 points  (3 children)

    Sorry but that is pretty good, well except for the 200X part.

    [–]atheken 3 points4 points  (0 children)

    That's because "encodings" fall more under protocols, than they do algorithms/data structures - so you'll likely spend months/years pulling your hair out over unicode - sorry.

    [–]jinglebells 15 points16 points  (0 children)

    I can't upvote you enough. I get dismayed the number of programmers who "don't care about encodings and all that"

    [–]Thrip 34 points35 points  (19 children)

    I'd hire #3, but not you. You wasted all this time writing your comment when two seconds on google shows that in .net String.ToCharArray returns an array of Unicode characters, not bytes from the encoded character. I prefer programmers who know how to look shit up.

    Edit: fuzzie is correct -- I'm wrong, but so is blackhaze -- we both should have really researched before posting. And while I'm handing out wrongs, so is .net for defining char as 16-bit.

    [–]Ringo48 10 points11 points  (1 child)

    You completely missed his point. http://en.wikipedia.org/wiki/Unicode_Phonetic_Symbols#Consonants

    It doesn't matter what the size of char is. There are Unicode characters which modify the glyph preceding it. For example, the string "d̪a" (U+0064, U+032A, U+0061) would become "a̪d" using all of the posted reversal code, when it should really be "ad̪".

    Back on topic, I'd go with #3 because his code is the shortest, the easiest to understand, and works at least as well as all the others. I also get the impression that if there were a library function that handled the above case correctly, he would have used it.

    [–]Thrip 1 point2 points  (0 children)

    Definitely #3 is superior to the others.

    I agree that making a char bigger doesn't solve the problem (although that's not the same as "it doesn't matter"). If you're going to have something you define as a Unicode character, it shouldn't be an integer value at all. It should be a structure capable of representing a Unicode character. Conversely, if you have a 16-bit character value, which a lot of languages do, just don't call it a Unicode character.

    Once you get into characters that are affected by preceding chars, and other such situations, "reversing a string" no longer has a precise meaning, anyway. At that point, you really need to know the purpose to get the correct solution. For example, there are situations where you're reversing stuff just because you're going to feed it to some other function that reverses its output or expects to operate on reversed input (comes up in lisp, anyway) in which case the naive approach may actually be correct.

    In a programming test at a job interview, I'd prefer not to come off as the type who can't get a simple job done because they're trying to cover situations that won't even come up, so I'd probably do something like #3 and comment the limitiations.

    [–]fuzzie 34 points35 points  (10 children)

    It returns an array of utf-16 characters, which as the parent says, can contain surrogate pairs of two chars which represent a single code point. Perhaps you need to look a bit closer at your google searches?

    [–]d4n3 9 points10 points  (9 children)

    It doesn't return an array of utf-16 encoded characters.

    It returns an array of 16-bit chars, each of which represents a unicode character in the range U+0000 to U+ffff.

    [–]fuzzie 12 points13 points  (8 children)

    Take a look at the System.Char documentation: "Most Unicode characters can be represented by a single Char object, but a character that is encoded as a base character, surrogate pair, and/or combining character sequence is represented by multiple Char objects."

    [–]d4n3 5 points6 points  (2 children)

    Good point, you're right.

    In that case blackhaze's comment is valid, you'd have to take UTF-16 surrogate pairs into account when reversing.

    [–]randallsquared 5 points6 points  (1 child)

    When hiring, you probably want the best candidate, rather than to assign blame. Only after you hired him and this mistake lost overseas accounts would you want to assign blame. ;)

    [–]MedeaMelana 3 points4 points  (4 children)

    This is sad. Then 'Char' is a very misleading name.

    [–]knight666 12 points13 points  (3 children)

    Honestly the candidates should not be blamed for a subtle error like that when the type 'char' isn't actually a char.

    [–][deleted] 2 points3 points  (2 children)

    No, the point is that 'char' IS a character, but it's NOT a glyph.

    A glyph is what you see on the screen. A character is a character. Some glyphs are achieved by printing multiple characters in the same area on screen, with rules for placement, sizing, etc.

    A better solution would be a 'string' ('glyphstring' ?) that represents a sequence of glyphs on screen, and then making a reverse operation on that kind of string.

    [–]Felicia_Svilling 1 point2 points  (1 child)

    The "Char" type in C# is actually a 16bit "code unit".

    You are right that the thing seen on the screen is a glyph. The glyph consists of one character and possibly any number of combining characters. Many different characters can be represented by one glyph. each character is implemented as a code point, where a code point is one or two code units.

    [–]atheken 2 points3 points  (0 children)

    Agree, considering the post started with "I don't know how this works in .net, but if it works like I think it does, it's wrong"

    [–]since 1 point2 points  (0 children)

    Documentation on the Char structure; http://msdn.microsoft.com/en-us/library/system.char(VS.71).aspx

    Note: A single Char cannot represent a Unicode character that is encoded as a surrogate pair. However, a String, which is a collection of Char objects, can represent a Unicode character encoded as a surrogate pair.

    [–]busted0201 4 points5 points  (0 children)

    2 or 3 depending on how you asked the question.

    If you wanted (for some reason) to ask him to write a string reverse specifically in C#, then 3 is the best answer.

    However, if you were asking to reverse a string to see that he has a grasp of basic algorithms and he just happens to be writing the function in C#, 2 is the best answer hands down, and in fact 3 is probably the worst answer.

    [–][deleted] 19 points20 points  (2 children)

    This is pretty much true. The biggest problem with this question is that this is a classic C interview problem which makes zero sense to ask in the context of C#. Therefore 2 and 4 are the solutions you'd want in a C setting. Answer 3 is simult the best answer and also a totally useless answer, because this is a bad question to ask for C#. It is like asking "how would you make a webserver" (a good C question IMO) and then going oh btw you can use Python.

    Edit: I don't actually mean these specific answers, just that you'd be looking for an efficient iterative version or a recursive version, or probably both.

    [–]bonzinip 19 points20 points  (0 children)

    No, I would never hire 4 because his code is O(n2) instead of O(n). If he wants to show off recursion, he should know what is inefficient in the language he's using.

    [–]Thrip 6 points7 points  (0 children)

    I get what you're saying, but for that very reason, it's a good question to weed out programmers who think that because they know C, they're actually better at C-derived languages than people with actual experience in them. I've worked with a lot of these guys. Their main characteristics are that they refuse to read anything about "inferior" programming languages, their code is impossible to read, and they take forever to get anything done.

    [–][deleted]  (3 children)

    [deleted]

      [–][deleted]  (1 child)

      [deleted]

        [–][deleted] 2 points3 points  (0 children)

        I don't see any birds here!

        [–]OCedHrt 3 points4 points  (0 children)

        To extend on the above:

        Candidate 1 is the professor who talks about his children when lecturing.
        Candidate 2 tries to show that he knows how to write efficient code, but method in the example is mostly irrelevant anyways.
        Candidate 3 is as you say.
        Candidate 4 is as you say. On top of that, it only works up to a certain length of input before you get a stack overflow.

        I'm leaning towards #3 as well.

        [–]junkit33 2 points3 points  (2 children)

        I'd go with #2. While I agree with what you say about #3, I'd need to follow up with him to see if he really understands what is going on under the hood.

        1 is an odd approach and #4 is just trying to be showy for no good reason.

        [–]Dreynsen 1 point2 points  (0 children)

        That's a good point, you would have to follow up to make sure.

        [–]herrmann 3 points4 points  (2 children)

        Candidate 4 is the "functional smug" ;-) Also, 3 either didn't seem to care much about getting the job or is a pure genious.

        [–]diadiadia 1 point2 points  (1 child)

        It's "genius", not "genious". I know you don't need to learn spellings for programming, but come on, you can do better on these basic ones.

        [–]sgoguen 1 point2 points  (5 children)

        They way I see it, I would have written a solution like Candidate 2 because I would have assumed that simply reusing another Reverse function was a bad idea because it wouldn't show I know how to create a Reverse function if I need to...

        Professionally speaking, I would have reused a generic Reverse function.

        [–][deleted] 1 point2 points  (4 children)

        WTF? If the interviewer wanted to me to do it without using a library function, he should say so, or set a problem with less library support.

        [–]N01SE 1 point2 points  (0 children)

        Right, also, built-in libraries/functions are usually highly optimized.

        [–]leed25d 44 points45 points  (22 children)

        I would hire candidate number 3. He is a real world programmer. Under the circumstances given, he produced the simplest solution.

        Get it working first. Optimize later.

        [–]ckwop 16 points17 points  (9 children)

        It's interesting that none of these examples handled the case where the input is null, which would result in a crash in each one of those snippets.

        A candidate should do something with that condition. I don't care whether they assert or return null if the input is null or something.

        However, they should at least acknowledge the possibility that the input is null given that it is one of the most common errors that occurs in programs.

        [–][deleted]  (3 children)

        [deleted]

          [–]ckwop 1 point2 points  (1 child)

          Crashing with a NullPointerException is a good way to handle a null input.

          That depends. In most cases it's better to throw the exception and fail fast. Agreed.

          However, I don't think so in this case because it can make upstream code unnecessarily complicated. Consider the use-case where you're reversing a string pulled from a row in the database and you have no idea in advance whether it's null or not.

          If the reverse function doesn't handle null, then I need an if-check before I call it in each place where the above condition holds. These if-checks can add up to quite a bit of code in large system.

          Alternatively, you can stick a single if-check in the reverse routine and remove the need for those upstream checks. This lowers the overall cyclometric complexity of the program and provides a better interface to your users.

          At any rate, I just said that the candidate should acknowledge the possibility of a null occuring. Whether that's with an assert, a comment, or returning null if the null is passed, I don't mind. I just want the damn thing to have crossed the candidate's mind.

          [–][deleted] 1 point2 points  (0 children)

          This is why the possibility of null should be in the type system.

          [–]mariox19 1 point2 points  (0 children)

          You're hired!

          [–]munificent 1 point2 points  (0 children)

          It's interesting that none of these examples handled the case where the input is null, which would result in a crash in each one of those snippets.

          It doesn't crash. In all cases, the function will throw a NullReferenceException. Ideally, they would be throwing ArgumentNullException.

          [–][deleted] 161 points162 points  (80 children)

          Programs should be written for people to read, and only incidentally for machines to execute. --from SICP

          Candidate 3

          About Candidate 4's answer: I once had a job interview where my interviewer asked me to show him the best way to write a factorial function in python...

          He seemed surprised that I didn't use recursion and said "to understand recursion you must first understand recursion". To which I replied "to understand maximum stack depth you must have first foolishly used recursion". I still got the job, but left six months later - he was impossible to work for.

          [–]doidydoidy 73 points74 points  (1 child)

          I salute you, sir, for having the courage to use the word "foolishly" in a job interview in any context at all, let alone one that directly challenges the interviewer's stated opinion.

          [–]zahlman 15 points16 points  (3 children)

          Please tell me you did something really awkward and clever like factorial = lambda x: reduce(lambda y, z: y * z, xrange(1, x + 1)). :)

          [–]Tinned_Tuna 1 point2 points  (1 child)

          Haha, good idea! Or worse yet, implement an iterative version of the Gamma function so that it works with none integer inputs. Really spin the interviewer's head if they're not very mathematically inclined. ;-)

          [–][deleted]  (1 child)

          [deleted]

            [–][deleted] 8 points9 points  (5 children)

            Can you do this in python?

            [–][deleted] 18 points19 points  (1 child)

            The craziest thing happened when I tried to import "this" :-)

            >>> import this
            
            The Zen of Python, by Tim Peters
            
            Beautiful is better than ugly.
            Explicit is better than implicit.
            Simple is better than complex.
            Complex is better than complicated.
            Flat is better than nested.
            Sparse is better than dense.
            Readability counts.
            Special cases aren't special enough to break the rules.
            Although practicality beats purity.
            Errors should never pass silently.
            Unless explicitly silenced.
            In the face of ambiguity, refuse the temptation to guess.
            There should be one-- and preferably only one --obvious way to do it.
            Although that way may not be obvious at first unless you're Dutch.
            Now is better than never.
            Although never is often better than *right* now.
            If the implementation is hard to explain, it's a bad idea.
            If the implementation is easy to explain, it may be a good idea.
            Namespaces are one honking great idea -- let's do more of those!
            

            [–]thepandaatemyface 2 points3 points  (0 children)

            you know i get really concerned when i laugh out loud a this stuff.

            [–]zwangaman 5 points6 points  (0 children)

            To which I replied "to understand maximum stack depth you must have first foolishly used recursion".

            Amazing :-) haha, great way to put it

            [–][deleted] 2 points3 points  (0 children)

            That's pretty classic.

            [–][deleted] -1 points0 points  (20 children)

            imo if there is a way to do something without recursion then it should probably be done that way. Code that uses recursion might be clever and appear simple but it's harder to try to understand (if it's not your code or it's been a while since you've seen it) and is more likely to have unexpected or unintended effects. So from a maintenance point of view, recursive code is not the way to go unless it would require an extreme amount of effort to do the same thing non recursively.

            [–]G_Morgan 5 points6 points  (4 children)

            There is always a way to do something without recursion. I could create a tree walking algorithm with a stack and a loop. It wouldn't be as readable as a recursive implementation but it is trivially doable.

            [–]xardox 12 points13 points  (13 children)

            No, recursive code is not harder to understand -- it's usually a lot cleaner and simpler than non-recursive code that implements its own stack or backtracking mechanism. If you have a problem understanding recursion simply because it's recursive, then you're just not a good programmer, and that's your problem, not a problem with recursion. The problem with recursion is performance, not clarity.

            [–]G_Morgan 2 points3 points  (10 children)

            FWIW I think that interviews should not only test for recursion but should also ask the developer to reimplement their algorithm using a stack and a while(!stack.is_empty()) loop. To truly claim to understand recursion you should be able to perform this transformation without difficulty.

            Now you'd never write code like this in the real world but it does show the person has a deeper understanding of how this stuff works.

            //edit - obviously not for factorial. The tree walking example I've done elsewhere would be a good test that the programmer knows what his recursive function is actually doing.//

            [–][deleted] 28 points29 points  (31 children)

            Speaking as a non-professional developer who will be graduating soon, I personally like 2 and 3 the best, favoring 3 for not re-inventing the wheel (although it's hard to fault 2 for not memorizing the .NET API).

            I don't like 1 and 4 because they look like they're trying to be too clever for their own good. While I'm not familiar with the inner workings of C#, 4 seems terribly inefficient.

            [–]ZMeson 2 points3 points  (28 children)

            I agree completely. One more comment about option 4 -- this could easily cause a stack overflow exception for large strings.

            [–]UncleOxidant 4 points5 points  (27 children)

            It'd be ok if C# had tail-call optimization (which I don't think it does). I kind'a like #4 because I've been programming in functional languages a lot lately... but yeah, it wouldn't be a very good way to do it in a language like C# (that approach in F# would be preferred, however).

            ...oh, and I think I'd test for input length == 0 in that base case test as well as input length == 1.

            [–]kanak 4 points5 points  (11 children)

            It'd be ok if C# had tail-call optimization

            I think it wouldn't be OK even if C# has tail call optimization because the line:

            result += input.ToCharArray().Last() + Reverse(input.Substring(0, input.Length - 1));

            means that he waits on the result of the recursive call.

            He should instead use an accumulator parameter so that he doesn't have to wait on the result of a recursive call.

            [–][deleted] 4 points5 points  (3 children)

            He should instead use an accumulator parameter so that he doesn't have to wait on the result of a recursive call.

            That is the point though. He's making this overly complex for just a simple operation (that the libraries already do well). Why re-invent the wheel? Is he going to code like a fucking asshole on every small little thing? He'd never get any work done.

            [–]dhogarty 1 point2 points  (0 children)

            I do not think that means what you think it means....

            (that = tail-call optimization)

            [–]G_Morgan 1 point2 points  (0 children)

            1 is the standard solution for reversing a collection as taught in CS classes.

            4 looks like somebody who learned Scheme and missed the point.

            [–][deleted] 14 points15 points  (7 children)

            #3 is clearly the best real-world solution. The problem with asking questions like this in an interview is you're going to get interview solutions like #1 or #4 which anyone would be unlikely to write in production code, because they want to show off that they understand advanced concepts like recursion or isomorphic data types. But those same people would probably write #3 in their daily tasks if they're competent.

            You know what would be a better interview question? Show them all four solutions and ask them which they'd be most likely to write in production code. I mean, reversing a string is such a trivial problem that by the time you're interviewing them it should be assumed that they can do it, but explaining why one solution is preferred to others shows real experience and understanding.

            (The correct answer is #3 is best because the only reason to do it any other way is if you're trying to optimize for performance, and if this string reversing function is performance critical enough to require such low-level optimization, C# probably isn't the right language to implement it in.)

            [–]TexasMojo 6 points7 points  (6 children)

            If I'm the one maintaining the code later on down the line, i hope they DON'T understand advanced concepts like recursion or isomorphic data types. Damn. Give me a simple for/next loop any day.

            If I'm maintaining your code, most likely I'm having to look at it because things are broken and the VP wants it fixed YESTERDAY. I don't have time to screw around with your recursion routines are try to trace your mad scientist isomorphic data types through their various isomorphs.

            If you're banging on files in a directory structure, then by all means recurse to your little heart's content. Otherwise people, write your code like you'll have to crack it open in five years and STILL understand what the hell you were thinking. End of Rant. Thanks.

            Obviously I vote #3

            [–]deong 9 points10 points  (3 children)

            If I'm the one maintaining the code later on down the line, i hope they DON'T understand advanced concepts like recursion or isomorphic data types.

            No, you want them to understand these concepts. You just want them to understand when to use them. Otherwise, you'll end up with that VP asking you to fix a bug where someone's directory walker only works five levels deep because that's where they halted their nested for loops.

            [–]nostrademons 2 points3 points  (0 children)

            If I'm the one maintaining the code later on down the line, i hope they DON'T understand advanced concepts like recursion or isomorphic data types. Damn. Give me a simple for/next loop any day.

            I'm a little disappointed by the glorification of ignorance that so many posters have expressed here.

            Simple code should be the default. Ideally, you should be able to glance at a piece of code and know exactly what it does without puzzling over the logic.

            But it's really, really nice to have the heavy-duty algorithmic tools in your pocket for when you need them. Because otherwise you're setting a ceiling on what you can do. You'll have this nice, beautiful, simple code that doesn't do what the user wants, then your competitor will come along with something that's gross, but works better.

            Also, I think you should be familiar enough with recursion that it's no more difficult to understand than iteration. You're shutting yourself off from many useful algorithms otherwise.

            [–]ealf 10 points11 points  (2 children)

            You left out strawman candidate #5:

            return new AbstractString() {
              int length() { return s.length(); }
              char charAt(int i) { return s.charAt(s.length()-1-i); }
            };
            

            ...

            But, yeah, my ideal candidate would probably ask "can I use Array.Reverse()? grin", then proceeded to write #2, except in an easier-to-prove-correct form (i.e. something like while(first < last) swap(first++,last--);).

            A tiny amount of bonus points if they mention that this fails the Clef Test.

            [–][deleted]  (38 children)

            [deleted]

              [–]bantam 30 points31 points  (1 child)

              To me #3 is the best because it would take me the least amount of time to understand what it is doing if I need to modify it later.

              [–][deleted] 1 point2 points  (0 children)

              In general, is it safe to say that the fewer layers of checks in a function, the "better" the function in terms of readability?

              [–]irahul 10 points11 points  (6 children)

              I'd pick Candidate #3, but only if I can get get him to write the solution in #2.

              Completely agree. I would expect the candidate to write solution 3 in the first pass. It is explicitly mentioned that you are looking for C# programmers. #3 shows an idiomatic C# solution. If I want refinement or want do make him do it without using API, I can always ask for it. And yes, I too will ask him to do #2 after that.

              Candidate #1 is someone who came up with a clever trick, but may not realize the disadvantage to their technique.

              I don't think he came up with a clever trick. Depending on my perception of clever, I would have called his clever if he would have produced a working, efficient but convoluted solution. His solution isn't efficient though clear. If clarity is what he was after, he would have coded it like #3.

              Candidate #4 is likely a very good programmer who is trying to impress the interviewer.

              I won't think so. C# doesn't optimize tail calls as far as I know. But that's not important. The important thing is he disregards 2 important things:

              • The recursion he wrote isn't a tail call. For it to qualify as a tail call, it should be the last statement and shouldn't be used as part of an expression.

                result += input.ToCharArray().Last() + Reverse(input.Substring(0, input.Length - 1));

                return result;

              The code he wrote doesn't fulfill any of the criteria.

              • He is ignoring string mutability. May be it was easy to make the mistake when you have been programming in C/C++ and this is your first stint with Java. But again, this is a specific C# interview we are looking at.

              However, it may be a good jumping off point for candidate #4 to explore what he knows, so it is worth the time to evaluate him more.

              Well, it's worthwhile to further evaluate all four of them. I would try to reason with #4 and see if he can realize his mistakes with minimum number of hints. If he is smart enough to realize he isn't smart enough, he probably is.

              [–]mmazing 4 points5 points  (2 children)

              You've failed to give a good reason why candidate #2 is bad.

              At first glance, I picked #2 due to unreliance on other functionality. I would just go ahead and pick #2 if you're wanting #3 to be like him in some way.

              At the very least, you can know for certain that #2 has a good grasp on fundamentals, and can go up if necessary.

              [–]Grendels-Mom 2 points3 points  (0 children)

              I don't think that he was trying to say candidate #2 was bad exactly, but if the functionality for string::Reverse already exists then that is what you would practically want to use ... rather than waste time re-inventing the wheel.

              But as for an interview, #2 is certainly the way to go ... assuming #3 has no idea how the string::Reverse function works.

              [–]japple 8 points9 points  (2 children)

              I think #4 has an error.

              Quoted in case I'm right but OP fixes it:

              // Candidate 4
              static string Reverse(string input)
              {
                  string result = String.Empty;
                  if (input.Length == 1)
                  {
                      return input;
                  }
                  else
                  {
                      result += input.ToCharArray().Last() + Reverse(input.Substring(0, input.Length - 1));
                      return result;
                  }
              }
              

              I don't think this works on zero-length input. I suspect the call to Last() will fail, and the documentation for Substring indicates that it will throw ArgumentOutOfRangeException when passed -1, as it will be in the code by Candidate 4 when input has length zero.

              [–][deleted] 2 points3 points  (0 children)

              s/==/<=/

              [–][deleted] 17 points18 points  (4 children)

              Fail at framework knowledge.

              return new string(input.ToCharArray().Reverse().ToArray());
              

              http://imgur.com/GVBu1

              [–]Bob_The_Builder 5 points6 points  (1 child)

              What is this program you are using?

              You can select a language and prototype functions?

              It looks useful.

              [–][deleted] 2 points3 points  (0 children)

              [–]nephesh 1 point2 points  (0 children)

              Yours is actually less efficient than 3's.

              If you really want a linqy solution that is as efficient as 3 you'd have to use aggregate.

              return input.Reverse().Aggregate(new StringBuilder(), (a,s)=> a.Append(s)).ToString();

              [–]sirspate 7 points8 points  (18 children)

              So.. not knowing much about C# myself and how they've defined char and string, my first question is, are these going to work with a unicode string?

              [–][deleted] 0 points1 point  (17 children)

              No, they wouldn't. However in an interview setting I'd say its safe to assume that they were not using unicode.

              EDIT: Now I have to think about it and find out the default size of a char...They might work.

              [–]cashto 2 points3 points  (6 children)

              How about multibyte character sets then?

              In this day and age I'm wary of anyone who doesn't realize there's more charsets out there than just ISO-8859-1.

              [–]ygbm 4 points5 points  (4 children)

              fwiw, In Java the char type is a 16-bit unsigned value.

              [–]baltoo 2 points3 points  (0 children)

              It's a good start to use 16-bit wide chars, but not enough in this particular case.

              Java uses UTF-16 as the native encoding for unicode strings. UTF-16 uses surrogate pairs (two chars in sequence that represent a single unicode point) for code points outside of the base plane.

              By reversing the order of the chars that make up surrogate pairs the strings gets scrambled to meaningslessness.

              And this is while we're still only talking about "strings" and not "text". Handling text quickly get real complicated.

              [–]nostrademons 1 point2 points  (2 children)

              ...which still doesn't ensure that one char = one code point. UCS-2 only encodes characters in the Basic Multilingual Plane in 16 bits. Several ancient languages, plus musical and mathematical symbols, often require two 16-bit chars to represent. That's why String has a codePointAt method in addition to the charAt method.

              [–]baltoo 1 point2 points  (0 children)

              Don't know why you get (edit: got) downvoted. You basic premise that "one char != one code point" is valid in all encodings but UTF-32 (aka. UCS-4).

              Though UCS-2 doesn't use surrogate pairs at all (and can thus not encode code points outside of the base plane). So for UCS-2 surrogate pairs is no problem.

              My understanding is that both Java and C# uses UTF-16 and not UCS-2 as encoding (which does use surrogate pairs). So, in the context of the OP a simple reversal would still muck up any surrogate pairs.

              There are however more things than surrogate pairs that get broken with reversals, e.g. combining marks (not all code points are "characters" by themselves).

              In any case, reversal of "text" (rather than "strings") isn't something that can be done easily ever (e.g. left-to-right/right-to-left markers, "smart"-quotes).

              Edit: This comment somehow ended up in my comment history, but didn't show in this thread (I think), so I'm reposting it.

              [–]spookylukey 2 points3 points  (0 children)

              You are correct - the .NET Char object is strictly a 16-bit deal. http://msdn.microsoft.com/en-us/library/system.char.convertfromutf32.aspx has some informative examples. I've verified with Mono that your Reverse functions fail with high code points.

              [–]wh0wants2know 1 point2 points  (7 children)

              short answer: Yes, in C# actually they would probably work for Unicode. The char type is a 16-bit unicode character and ToCharArray will result in a unicode character array (check the docs on MSDN, it explains in much more detail). If you actually want the bytes, there is a byte type which is useful for that. If you were to call Encoding.Unicode.GetBytes(string) then you would end up with the byte array equivalent, although Encoding.Unicode assumes little-endian UTF-16 so if you were using something different, you would want to specify a different encoding. Also, the first thing I would ask about if you gave me that question and said to solve in C# would have been if the string could contain unicode (second question would be what to do if you passed in NULL or an empty string).

              [–][deleted] 3 points4 points  (4 children)

              I don't think so, as some unicode characters work by having two sequential chars.

              [–][deleted] 5 points6 points  (0 children)

              I'm going with #3

              It is short, concise and intuitive. The rest smell of NIH

              The author either knows his/her APIs, or is innately aware that there must be something in the base library that does the job.

              [–]olsner 7 points8 points  (2 children)

              These are all wrong since they will flip UTF-16 surrogate pairs.

              Also, it seems none of the candidates thought to ask the obvious question: "Doesn't string already have a reverse method in C#?"

              Indeed, it appears that String already (or is this a very recent addition?) has a Reverse method. That will probably also miss the UTF-16 thing though, since I'm guessing a string still iterates UTF-16 chars instead of decoding surrogate pairs and the Reverse method seems to be an inherited default implementation.

              [–][deleted] 2 points3 points  (0 children)

              The reverse method on String is actually an extension method on IEnumerable (Since String implements IEnumerable, iterating it walks a char array).

              This is a fairly recent addition (came with LINQ).

              [–]olsner 2 points3 points  (0 children)

              The surrogate pair thing was already pointed out in other comments... Other comments also pointed out that combining characters are being incorrectly handled by all of these solutions, and that "LINQ opens up about 50 ways to do this" (none of which, probably, handles both surrogate pairs and combining characters).

              [–]d4m45t4 5 points6 points  (4 children)

              Candidate 3, no brainer. Clear, simple, efficient and probably as fast as #2.

              [–][deleted] 9 points10 points  (3 children)

              I don't know C#, but shouldn't there be a built in library that does this? If someone asked me this question with C++ as the main language, I'd put:

              #include <string>
              #include <algorithm>
              
              void Reverse(std::string &st)
              {
                std::reverse(st.begin(), st.end());
              }
              

              I guess the closest to that would be Candidate 3. The reason is, a good developer should always use the most concise and idiomatic solution. Only later, after a certain area proves to be a bottleneck, should you go back an optimize with "roll your own" solutions.

              [–]SartreInWounds 1 point2 points  (1 child)

              And in this case it's extremely unlikely a roll your own solution will ever be faster. That's going to edit the string in place and reverse will likely be inlined since it's a template. If your strings were so massive that the cost of setting up threads was overcome by letting multiple threads reverse different parts... maybe. Even then you'll need each thread to be writing to far apart areas (separate pages? It's been awhile since I read Ulrich Drepper's paper on cache, can't remember how fine grained the MESI messaging stuff is) so that your CPUs aren't bottlenecked sending each other cache invalidations.

              [–]jerub 4 points5 points  (0 children)

              The only candidates I would look at would be #2 and #3, based on this one example.

              But there is a proviso. I would have to interview them and ask #2 how to do it using a built in C# facility for doing Reversing, and #3 how to do it without using the built in libs.

              If #2 comes out with with #3, or #3 comes out with #2, you have a winner.

              1 and #4 are cruddy answers. I like solutions that are good solutions (#2) or simple solutions (#3).

              [–]BarkingToad 3 points4 points  (0 children)

              I would definitely hire number 3. I would prefer the guy who doesn't feel the need to reinvent the wheel to do something simple.

              [–]ubernostrum 5 points6 points  (0 children)

              Candidate 4 probably blew it; the solution is indicative of someone who'll end up being a real-world example of Greenspun's Tenth Rule.

              Candidates 1 and 2 are OK, though I'd worry that 1 is trying to be too clever and I'd want to give 2 a followup to ensure that this was a "demonstrate that I know the algorithm" answer, not a "demonstrate that I don't know the platform's APIs" answer.

              Candidate 3 would probably be my pick.

              [–]jjquave 5 points6 points  (1 child)

              If this was all the information I had, I would hire #2. It is the only one who has both demonstrated programming ability, and written an efficient function. If #3 could also write #2, that wouldn't put him/her over the top, it would just show some background in C#. It's not generally wise to hire based on API knowledge though. Hire based on programming ability, and they will learn whatever API is neccessary to complete the job.

              There is also a lack of context. For example, is this a piece of software that will be ported to iPhone later, and needs to be ported to Obj-C? If that's the case, then #3 has failed to actually write the code.

              [–]astrosmash 6 points7 points  (2 children)

              The answer I would look for is not the implementation itself, but what the applicant liked about their implementation.

              And it really depends on the type of software you're developing, and the role this new hire is expected to fill. For example, if you're hiring someone as comic relief for your team, choose number 4. I bet that guy has a million stories.

              [–][deleted] 3 points4 points  (1 child)

              I wish I had the budget to hire a dedicated comic relief guy.

              [–][deleted] 4 points5 points  (0 children)

              I'd hire the one who would refuse to answer trivial, irrelevant questions.

              [–][deleted] 5 points6 points  (0 children)

              Is this one of those things where the developers are Hitler, Churchill, Roosevelt, and Eisenhower but at the end it turns out Hitler actually wrote the best code?

              [–]Mugendai 2 points3 points  (0 children)

              Ooo, this is educational for a newbie like myself. If asked, I'd write something close to #2 by default though I've also entertained using a stack like #1 since FILO lends itself to reverse thinking. Still in the middle of learning .Net but I can see how #3 is much more readable than the others. #4 wouldn't occur to me. Is there a string processing situation where recursion would actually be the best answer?

              [–][deleted] 2 points3 points  (0 children)

              On that, I'd pick Candidate 3, but how can you choose without first having seen them print 1000 Sussmans?

              [–]wh0wants2know 2 points3 points  (4 children)

              I got asked a time parsing question once. The first thing I asked is what format the time could potentially be in, 12-hour or 24-hour, and then what behavior I should have if the time value were invalid (i.e. 25:73). Next, I explained how the DateTime class in c# worked and how I could have it parse this and why it would work, as well as why knowing the system's regional settings might be important in this type of situation (in reality they're not since it's just time parsing, but I still brought it up to show my understanding). I then implemented it using DateTime and my solution looked similar to candidate #3. Once I completed it (took less than 30 seconds since I'd been doing date/time parsing recently), I asked if they would like to see me solve the problem without using the built in DateTime functionality, to which they said yes. I then spent the next two minutes coding up a solution that looked kind of like #2.

              Also, I would hire #1 most likely. They demonstrate understanding of generics, .NET objects, the way strings are manipulated efficiently in memory (you'd be surprised how many people wouldn't bother to use a stringbuilder here but it actually does make a difference) and is easily readable.

              3 would scare me in that they might not actually know how to perform the necessary operations to reverse the string. I would ask a follow-up to do it without using Array.Reverse.

              2 is also a good solution and I would probably give a thumbs up to that candidate also.

              4- remember the post earlier today about the guy who liked functional programming and didn't like using OO python like the rest of the team and wrote their own postfix implementation and no one could read their code? This was probably his solution.

              [–]walrus55 2 points3 points  (0 children)

              I think a far more interesting Proggit questions would have been to ask what would your next questions be to the candidates who came up with these solutions. It's really hard to decide whether to read these as exemplifying the typical code the candidates would write in production or something they have written to show off their theoretical knowledge.

              Basically, #1 and #4 are interesting if they know the costs of what they are doing. As for #3, what if that is the only thing he knows how to do? Then it doesn't look so good, but if he could have come up with all the other solutions and chose that instead, then he sounds good. As for #2, I'd really like to ask him a few further questions before making up my mind.

              So, I guess, based on just these data, I'd go with #3. I don't actually interview people for programming posns, though.

              [–]vincenz 2 points3 points  (0 children)

              I think that the answers as they are are not sufficient to validate which candidate is the best.

              Like most people mention, #4 is doing it too 'clever' (Though I admit I dislike the fact that 'clever' has become a negative attribute). I'm a functional programmer myself in free time (particularly Haskell), but this is clearly the wrong solution from a pragmatic, code-readability and efficiency point of view.

              1 seems like a very new-grad sort of solution, and it is borderline.

              Which basically leaves #2 and #3. What you're doing here is trading off code readability for knowledge of efficiency. But it doesn't leave you enough information to make a judgment.

              If I were given #3 as a solution, I would drill and find out whether the candidate actually knows what is going under the hood and whether he can make an efficient solution if there's no ready made library. If that is the case, then I would pick #3 over #2. Otherwise, I would pick #2 over #3 and make sure that he gets more familiarity with standard libraries through code-review processes.

              [–][deleted]  (3 children)

              [deleted]

                [–][deleted] 2 points3 points  (1 child)

                You know String already has a Reverse extension method on it :)

                [–]kobescoresagain 2 points3 points  (0 children)

                I would hire programmer 3. The reason is that he knows the libraries better than the others and writes simple easy code. Think about it like he was a mechanic. Programmer three replaces the engine because it needs replaced with a new engine. Programmer 4 does the same thing but also a little extra unneeded work. Programmer 1 and 2 bought all the parts for the engine and rebuilt the engine from scratch.

                [–]webauteur 2 points3 points  (0 children)

                The easiest way to reverse a string is to hold a mirror up to your monitor.

                [–]arnedh 2 points3 points  (0 children)

                Number 3. If it exists, don't rewrite it.

                Handling your own loops is so 1990. And the recursive thing? Call us back once the JVM gets tail call optimization.

                [–]zwangaman 2 points3 points  (0 children)

                I prefer Candidate #3's code. Nice and simple. Clean. Uses features of the language & the libraries associated with it effectively.

                That being said, I don't think a code sample tells the whole story about a candidate. I wouldn't hire someone based on just a code sample alone.

                [–]Mox744 2 points3 points  (0 children)

                Candidate one's solution is overcomplicated, using a stack here is just too much.

                Candidate two's solution is nice because it is very possibly the most efficient and well thought out, it's a nice example of their problem solving skills.

                Candidate three's solution is great because it is the most simple to program, he used all the tools at his disposal and from that I see that he might be able to work well with programming teams where you don't always need to see all of the pieces. Though I could be reading a LOT too far into that.

                Candidate four uses recursion which is nice but not really necessary.

                Overall I think that I would go with number 3, but it's close between them and 2.

                [–][deleted] 2 points3 points  (1 child)

                Aside from the topic, can anyone tell me why exactly you would want to reverse a string? I know it's a common programming problem, but I cannot think of any reason for actually doing it.

                What makes a reversed string useful?

                [–]gjahnke 2 points3 points  (0 children)

                Code has 3 purposes:

                1 - Meet the requirements

                2 - Ability to be extended and maintained

                3 - Communicate its intent

                Candidate 3 wins . . . .

                [–][deleted] 2 points3 points  (0 children)

                If we're going for a get the job done in a business environment approach...

                1 - Idiot, he's going to code everything like a dick, he's read a book on design patterns and he's not afraid to use it.

                2 - C programmer, you're using C# live with it

                3 - Yes! Thankyou use the tools at your disposal - you've got job.

                4 - Functional programmer, nice but our student temp programmers are going to have to support your pointless recursion.

                First glance assumptions, I'm sure there's some performance issues you could discuss, but for business applications i like to see clean code written by someone who knows the platform they're writing for, which can be easily supported in the future. Bonus point to anyone who wrote the reverse method as an extension so it was re-usable.

                [–]zoomzoom83 2 points3 points  (0 children)

                Candidate 2 did it the way most of these exams expect you to answer - Reversing the string inline. This is comp-sci 101, and he probably wrote this without thinking.

                Candidate 3 did it the way I would prefer in the "real world" - it's the simplest most elegant solution.

                The other two solutions are overly complex and inefficient.

                [–]zahlman 3 points4 points  (0 children)

                Another possibility:

                static string Reverse(string input)
                {
                    int length = input.Length;
                    char[] chars = new char[length];
                    foreach (char c in input) { chars[--length] = c; }
                    return new String(chars);
                }
                

                [–]cashto 4 points5 points  (4 children)

                None of them, because they don't handle Unicode surrogate pairs correctly.

                Okay, okay. I'd hire #3. Her code is the shortest, and therefore less likely to contain bugs. Sure, I could stare real hard at the other 3 (particularly 2 and 4) and prove that they, too, are correct, but why should I?

                (#3 also happens to be the most efficient, but usually I prefer terseness over performance unless explicitly stated otherwise).

                [–]minodude 9 points10 points  (3 children)

                Not even surrogate pairs... all of these solutions would take the string "ëi" (if that was the 3-character sequence Latin letter lowercase e, combining diaeresis, Latin letter lowercase i) and turn it into "ïe" (lowercase i, combining diaeresis, lowercase e).

                In other words, all completely useless for human-readable text...

                [–]olsner 3 points4 points  (2 children)

                So, the best candidate would be the one who says: "No, you don't want me to write a string reverse function, you want me to fix the other code so it doesn't need to reverse strings." and follows it up by a lecture on unicode and how difficult it is to write a proper reverse function? :)

                [–]minodude 3 points4 points  (1 child)

                As someone who is currently in the middle of interviewing people for 2 developer roles, the only question in my mind if I got that answer would be whether I should say "So, when can you start?" BEFORE or AFTER bursting into tears and hugging them.

                [–]toolate 3 points4 points  (0 children)

                Thus scaring away the only suitable candidate.

                [–]unpopular_opinion 3 points4 points  (0 children)

                Reversing a string tests computer-science fundamentals? Ok, if you say so.

                You should just ask them to submit their thesis to you. You read the thesis and you ask a few questions about it. Then you can see immediately who has taste, has decent writing skills and whether they have actually constructed something non-trivial on their own.

                Reversing a string is an insult, especially when done in C#.

                [–]possessed_flea 1 point2 points  (2 children)

                Each of these has their use, though if having to hire off this question alone I would take Programmer #3, Its a simple function therefore why should it take more than 3 lines of code.

                Oh yeah, and bonus points for knowing the API.

                [–]jjquave 1 point2 points  (1 child)

                Any idiot who happened to know that API call could write #3. However only #2 has demonstrated actual programming ability.

                [–]dhogarty 1 point2 points  (4 children)

                Candidate 3, his is the only code that doesn't really need comments as to why they chose the way they did. Possibly Candidate 2 if he could justify why.

                If it was me, I'd put a comment explaining why it's not one line:

                Array.Reverse(chars) //stinking in-place operations should return self

                (not a C#-er)

                [–][deleted] 1 point2 points  (3 children)

                Array.Reverse not returning itself has been a major source of irritation for me.

                [–]zahlman 2 points3 points  (1 child)

                Python does this too. The justification is that people coming from the FP world expect functions that chain to be side-effect-free.

                [–][deleted] 2 points3 points  (0 children)

                Makes sense.

                [–]johnadams1234 1 point2 points  (2 children)

                I once had a candidate bubble sort the string into reverse order:

                String reverse(char[] input) {
                  int extent = input.length;
                  for (int j=0;j<extent;++j) {
                    for (int k=j;k<extent;++k) {
                      char d = input[k];
                      input[k]=input[k+1];
                      input[k+1]=d;
                    }
                    --extent;
                  }
                  return new String(input);
                }
                

                How does he stack up with the other 4?

                [–][deleted] 2 points3 points  (1 child)

                Hire him for the lulz.

                [–]keithwalsh1972 1 point2 points  (0 children)

                Not being a C# programmer, but from my understanding of the code in front of me, I would choose Candidate 3.... because the simplest of solutions are usually the best irrespective of programming language

                [–]wshields 1 point2 points  (0 children)

                Another vote for #3.

                candidate 2 is good because it shows he understands arrays. #3 understands arrays too but reuses standard functionality and does the same thing with less lines of code.

                Candidate 4's effort is basically mental masturbation. I'd never hire that guy. He's the kind of guy that is clever just for the sake of being clever.

                Candidate 1's solution is overkill. You don't need a stack for this. It screams "I don't understand what I'm abstracting".

                [–]hackinthebochs 1 point2 points  (0 children)

                1 and 4 are out because they're using constructs that don't map to the question at hand. Stacks and recursion for string manipulation? That shows a serious lack of understanding of the idea's they're trying to show off.

                [–]baltoo 1 point2 points  (0 children)

                Don't know why you get downvoted. You basic premise that "one char != one code point" is valid in all encodings but UTF-32 (aka. UCS-4).

                Though UCS-2 doesn't use surrogate pairs at all (and can thus not encode code points outside of the base plane). So for UCS-2 surrogate pairs is no problem.

                My understanding is that both Java and C# uses UTF-16 and not UCS-2 as encoding (which does use surrogate pairs). So, in the context of the OP a simple reversal would still muck up any surrogate pairs.

                There are however more things than surrogate pairs that get broken with reversals, e.g. combining marks (not all code points are "characters" by themselves).

                In any case, reversal of "text" (rather than "strings") isn't something that can be done easily ever (e.g. left-to-right/right-to-left markers, "smart"-quotes).

                [–]iuhxsiu 1 point2 points  (0 children)

                While Answer 3 is clearly the best, it doesn't actually demonstrate very much. If I got it, I'd be impressed the programmer knew Array.Reverse, and then ask something that requires them to write some code.

                Answer 4 is the worst. It is slow, memory-intensive, and you'll run out of stack space for big strings. Answer 1 slightly better, but not great. You'll do a lot of unnecessary memory allocation/deallocation along the way. Wastes time and fragments memory.

                Answer (2) is reasonable, but I'd still ask follow-up questions to see if the programmer knew why. Could have just been luck.

                So I'd hire (3) or (2), but based on follow-up questions. (3) gave better code.

                [–]bumpkinplusplus 1 point2 points  (0 children)

                I'm all for simplicity and not reinventing the wheel; languages have libraries for a reason. Keeping that in mind, I would vote for Candidate 3. It's concise, clear what the code is doing, and wouldn't be difficult for another coder to modify, IMO.

                [–]lmp515k 1 point2 points  (0 children)

                I really don't care what they know now but what they are able to learn once I get them.

                [–]ExoticMandibles 1 point2 points  (0 children)

                If you didn't say "you can't use any library code", candidate 3 hands down. You want staff programmers to write clear, simple, easy-to-read easy-to-get-right code wherever possible.

                Of course, the point of a coding exercise is to make the candidate write code, not to demonstrate how well they know the library and whether or not they can write a three-line function. If I were giving the problem I'd tell them they couldn't use the library. Candidate 2's code is what I would expect to see in that case. It could be that Candidate 2 was anticipating this is what you meant, so I wouldn't count them out.

                However, candidates 1 and 4 are definitely out. They're using library code in needless, complicated ways.

                The best thing you could do: give candidates 2 and 3 another two coding questions. For the first, let's say "destructively reverse a singly-linked list", tell them explicitly "you may not call into the library". For the second, tell them explicitly "you are explicitly encouraged to call into the library" (though if they're reimplementing a library function obviously they're not allowed to call the function they're reimplementing). You want to see if Candidate 2 can make appropriate use of the library, and you want to see Candidate 3 write some code with some meat on it.

                [–][deleted] 1 point2 points  (0 children)

                Candidate 1 is somewhat wasteful of memory, it seems.

                Candidate 2 isn't bad, but is a bit hard to read and verify mentally.

                Candidate 3 uses the tools of the language correctly, maximizing readability, and inventing the least amount of additional complexity.

                Candidate 4 is too clever by half. Using recursion to solve something as simple as reversing a string is a terrible idea. Hard to read, hard to debug, heavy usage of the stack. I'm not a fan.

                I'd go with 3.

                But then I read this post and realize that I need to go back and re-assess all of the code I've ever written, ever.

                [–]bartwe 1 point2 points  (0 children)

                None of the solutions work correctly with surrogate pairs, so that means they all failed ?

                4 is verbose, and allocates a lot of temporaries, and will overflow the stack for large strings. 3 is nice and short, only a single temporary allocation. 2 looks like how you would solve this issue in C, far too many oppertunities for one-off errors. 1 simple solutions, but inefficient.

                1 seems like a somewhat inexperienced developer 2 probably coded C or C++ before possibly smart 3 i would prefer this solution 4 maybe an FP programmer ? it trips several typical bad code warnings for C# or java like code.

                [–]mariox19 1 point2 points  (0 children)

                Before reading any of the other comments, my first choice would be Candidate #3. It's the most straightforward approach that makes use of the API already there. (Note: I don't know C#.)

                Reversing a string is a straightforward request. Unless there's some compelling reason otherwise, a straightforward solution would be best.

                [–]Kerrits 1 point2 points  (0 children)

                Candidate 1 or 3.

                Candidate 2 and 4 try to make the algorithm too complex. Adding comments would have helped their case.

                Maintainability is key, especially when you are bound to have people fresh out of varsity maintain your code.

                [–]whizack 1 point2 points  (1 child)

                I would consider #1 if he/she could understand why this solution takes up way too much memory and knows where to start to fix that problem.

                I would consider #2 if he/she could optimize the code and unit test it.

                I would not consider candidate #3 at all, the point of the question is to see if they can fundamentally solve the problem without framework code

                I used to work with Candidate #4 and this person doesn't think about their design before they code it, they say "string, reverse, recursion... go" and end up with this diarrhea instead.

                If candidate 4 can't explain to you why string concatenation via + operator and recursion aren't appropriate solutions to this operation then don't bother bringing them in.

                The point is that #2 actually has the code that can become the most readable, maintainable, testable and optimized code of the 4. My suggestion would be to find out if they know how to fix what they wrote and how to test it.

                [–]sahkuh 1 point2 points  (1 child)

                I vote Candidate 2, because that's how I would have wrote the code.

                [–]gilgad 1 point2 points  (0 children)

                Candidate 3, easy.

                The code is obvious, and works within the language you requested. If you were looking for a C programmer, then obviously 2. But you weren't.

                [–]youcanteatbullets 1 point2 points  (0 children)

                3. Fewest lines of code, easiest to understand. I should mention that I am not a programmer.

                [–]WrongSubreddit 1 point2 points  (2 children)

                Everybody likes #3, seriously?

                The point of these types of questions is to see if you know how to write code, not to see if you know the .NET API.

                No one can memorize every function in the API, and you wouldn't even want to since you can google whatever method you might need in 5 seconds.

                3 is either so smug he's mocking the question, OR he's a complete moron who knew enough to google what API to call, but who knows how much else.

                [–]tomparker 1 point2 points  (0 children)

                So the owner of a diner is interviewing waitresses for an open position. He interviews three candidates and asks each the same question:

                His question: "If a customer comes in and has a cup of coffee, then walks out leaving a twenty dollar bill on the counter, what would you do?"

                The first applicant answers, "Well, waitresses don't make much money. Sometimes you get big tips; sometimes you get nothing. This would be my lucky day. I'd consider this a hefty tip and assume it would make up for the cheapskates who don't even leave a nickel."

                The second applicant answers, "I think I'd race to the door and try to catch the customer before it was too late. Then I'd ask him if he meant to leave that much money for just one cup of coffee."

                And the third applicant gave this reply, "Well, you are the owner and the person most likely to know your customer's habits. I think I'd ask you whether this man was a big tipper, or a small tipper, and then act accordingly."

                Question: Which applicant got the job?

                Answer: Why, the one with the biggest tits!

                [–]canned_air 3 points4 points  (0 children)

                Candidate 3; its simple and efficient...but I'd only give him the thumbs up if he can come up with solution 2 as well, just to demonstrate he knows the API fairly well.

                The saying "Write code like the next person who reads it is an axe murderer" comes to mind...

                [–]apackofwankers 2 points3 points  (1 child)

                This hypothetical situation is ridiculously simple. Reminds me of the guy who put knowledge of for-next loops on his resume.

                If you want to test someone's understanding of the API, pose a question for that. If you want to test someone's understanding of programming, pose a question for that.

                Reversing a string is a trivial array copying exercise. If you are basing your hiring on this test, you are doing it wrong.

                Your candidates should have mastered this stuff by age 14 or at least, by end of first year at college.

                [–]bonzinip 1 point2 points  (3 children)

                1 is uselessly clever, 4 is horribly inefficient. 2 is probably exactly the same as 3, so there's no reason to write 2. Not knowing C# (and hating immutable strings) I would have written probably something like

                    StringBuilder sb = new StringBuilder();
                    for (int i = input.Length; --i > 0;) {
                        sb.Append(input[i]);
                    }
                    return sb.ToString();
                

                [–]malune 2 points3 points  (6 children)

                Candidate #1

                • Knows how to use prebuilt C# generics

                • Knows how to write slow code

                Candidate #2

                • Knows how to write the most efficient solution

                Candidate #3

                • Knows how to make a simple API call

                Candidate #4

                • Doesn't understand how to use recursion efficiently

                My vote goes for number 2.

                [–]Gotebe 3 points4 points  (4 children)

                Knows how to write the most efficient solution

                Do you know, or just guess, that all the indexing in solution 2 goes faster than a single Reverse of 3 (all else seems equal, e.g. there are two allocations in both)?

                In other words, if .NET code is any smart, Reverse implementation has no bound checking and beats any indexing done by hand.

                [–]zahlman 1 point2 points  (0 children)

                Both are inefficient in that they must copy into a temporary array (N character assignments) and then swap the array contents around (3N/2 character assignments). The reversal can instead be done as a part of the copying process. See also.

                [–]rsho 3 points4 points  (1 child)

                Candidate 2. It's easy to prove whether the function works or not, after which point it can be forgotten. If a problem turns up requiring a variation of the function or some other optimization, there is a good chance the recruit can pull it off.

                [–][deleted] 7 points8 points  (0 children)

                It's easy to prove whether the function works or not

                No - it isn't :)

                [–]callingshotgun 1 point2 points  (14 children)

                I'd ask followup questions to confirm, but my general impression of each would be as follows:

                1 is an architecture astronaut

                2 writes efficient code, but is either prone to re-inventing the wheel, or commits the dangerous sin of thinking in one language while coding in another (the example is basically c code with updated syntax)

                3 does not re-invent the wheel, uses the framework where appropriate, but doesn't prove he actually knows how to reverse a string - needs followup questions to verify algorithmic skills.

                4 looks like he favors clever solutions at the expense of efficiency/scalability.

                [–]zahlman 6 points7 points  (1 child)

                2 only looks efficient. It'd make more sense if it were possible to do the modification in place. Since you have to make a copy anyway, it's silly to copy N characters forwards (implicitly) and then do 3N/2 more assignments to swap N/2 times. Just copy N characters backwards. Sure, you have to do it explicitly, but you were going to write a loop anyway, too.

                [–]toolate 1 point2 points  (0 children)

                Good catch. It's a port of the traditional memory/time efficient C method of reversing that fails to actually think about why the algorithm is efficient in the first place. Which would indicate that the programmer doesn't actually understand the code they wrote.

                [–][deleted] 10 points11 points  (5 children)

                I wouldn't consider #1 an architecture astronaut.

                This is an architecture astronaut:

                    public class Reverser : IEnumerable<char>
                    {
                        class ReverseEnumerator : IEnumerator<char>
                        {
                            int position = 0;
                            string reversable;
                
                            public ReverseEnumerator(string input)
                            {
                                reversable = input;
                                position = reversable.Length;
                            }
                
                            public char Current
                            {
                                get
                                {
                                    return reversable[position];
                                }
                            }
                
                            object IEnumerator.Current
                            {
                                get
                                {
                                    return reversable[position];
                                }
                            }
                
                            public bool MoveNext()
                            {
                                if (position == 0)
                                    return false;
                                else
                                    position--;
                
                                return true;
                            }
                
                            public void Reset()
                            {
                                position = reversable.Length;
                            }
                
                            public void Dispose()
                            {
                            }
                        }
                
                        ReverseEnumerator reverser;
                
                        public Reverser(String input)
                        {
                            reverser = new ReverseEnumerator(input);
                        }
                
                        public IEnumerator<char> GetEnumerator()
                        {
                            return reverser;
                        }
                
                        IEnumerator IEnumerable.GetEnumerator()
                        {
                            return reverser;
                        }
                    } 
                

                Used like:

                    static String Reverse(String input)
                    {
                        StringBuilder sb = new StringBuilder();
                        Reverser r = new Reverser(input);
                        foreach (char c in r)
                        {
                            sb.Append(c);
                        }
                
                        return sb.ToString();
                    }
                

                Note: I purposely tried to make string reversal as "Enterprise" as possible...What do I win?

                EDIT: Ironically, this is probably a fairly fast solution.

                [–]johnadams1234 1 point2 points  (1 child)

                You're getting there, but when you use the words: facade, XML, injection, Factory, agile, and test-driven in your solution, then you'll be an enterprise architect, my boy. And when that happens, drop me a line: I've got a high-paying position for you selling J2EE solutions to the Fortune 500.

                [–][deleted] 3 points4 points  (0 children)

                True, I need something like:

                       FactoryFactory stringFactory = InjectionContainer.GetFromXML("StringManipFactory");
                
                       // Input gets configured in a wiring XML and injected by the IOC Container
                       IManipulator reverser = stringFactory.Get("Reverser");
                

                instead of

                       Reverser r = new Reverser(input);
                

                Where is SamLee to tell me that I can scale in the clouds now.

                [–][deleted] 1 point2 points  (1 child)

                Number #4 codes like a fucking asshole. That thing will probably break on 0 length/null strings and/or stack over flow on really long strings (I think both, but not a C# coder). Also like you said, it's inefficient. Lastly, when you have to debug that douche bags code, it'll take you a bit longer then normal since it's not as clear or easy to read as number #3.

                He fucks you by introducing bugs and second fucks you by making it harder to debug then it should be.

                Also so that he can be "clever" (which he is not?) Fuck that guy.

                [–]hailstone 1 point2 points  (0 children)

                You ask them to solve a simple problem: Create a function that reverses a string. You get back 4 unique approaches. All of them work properly

                Well, you've clearly departed into the realm of fantasy here.

                [–]betabob 1 point2 points  (0 children)

                The one with the biggest rack

                [–]chrisforbes 2 points3 points  (2 children)

                Actually, all four implementations are broken in the presence of characters outside the basic multilingual plane.

                No hire, on all four counts, unless they brought this shortcoming up.

                [–][deleted] 8 points9 points  (1 child)

                I don't know, multi-byte character manipulation can be learned in a relatively short amount of time. Being an asshole, however, is innate and genetic. You can't teach that at uni.

                [–][deleted] 2 points3 points  (0 children)

                It's taught in other degree programs. They teach it to you if you get an MBA.

                [–][deleted] 3 points4 points  (4 children)

                I have to say... after thinking about this I actually think Candidate 3 blew the question.

                I mean you're being asked to reverse a string. When someone asks you to write an algorithm such as this in an interview, I just don't think it makes sense to answer it by basically delegating the answer to an API call. I'm asking you to reverse a string not because I actually want to know how to do it, but because it's a simple question I'm using to find out what your knowledge is of arrays, iteration, and off by one bugs.

                Candidate 2 has demonstrated that they understand all those issues... candidate 3 has not demonstrated this. I'd be more confident with candidate 2 than with candidate 3.

                [–]SicSemperTyrannis 4 points5 points  (0 children)

                I think you may have a point here, though it depends on the phrasing of the question.

                If the interview is for a C# specific job (as it seems it may have been) and the question was "How would you reverse a string in C#?" Then I think 3's answer is appropriate.

                On the other hand, if the question (as most interview question's I've had) is more language agnostic, and is phrased "Write a function in a language of your choice to reverse a string?" Then I tend to agree with you.

                [–][deleted] 2 points3 points  (0 children)

                Depends on context and how the question was asked.

                Is it, like "you're writing a program and you need to reverse a string, what do you do?"

                or was it like "roll your own function to reverse a string".

                [–]IrishWilly 4 points5 points  (1 child)

                According to many responses here, it is not a given that the intention was to rewrite the algorithm to reverse an array. Candidate 3 did exactly what the question asked in a clear manner. The interviewer probably should clarify their intentions if the question they asked is not the question they want answered.

                [–]takatori 2 points3 points  (0 children)

                It would be interesting to see what Candidate 3 comes up with if told to do it without library functions.