18 ms·
Fizzbuzz, Interviews, And Overthinking
- deleted 14y ago[deleted]
- __david__ 14y agoForget Fizzbuzz, we get candidates that cannot reverse a string (in their language of choice). A friend of mine just told me he uses the question "What is the hex number that comes after 'F'" as his first "weed-out" technical question. It boggles the mind.
- KirinDave 14y agoBecause I tend to get really nervous in interviews and consequently don't interview all that well most of the time, I try to be sensitive to people like me. I prefer to start very simple and sort of gradually increase the pressure until I can find a backing off point.
- sliverstorm 14y agoI'm not sure asking what comes after 0x000F is high-pressure.
- adgar2 14y agoIf you cannot reverse a string under pressure, you are likely unqualified for the job you are applying for. At least in my job, there is often more pressure than "write a string reverse function in any language you like in 10 minutes."
- nopassrecover 14y agoIt's a different kind of pressure though.
- adgar2 14y agoExplain. If you can't produce a god damned string reversal function in 10 minutes, why would I believe you can produce a bug fix to your own, complex code in a few hours? That's what interviewers are considering: the interview is a proxy to see if you can come close to the requirements of the job.
- nopassrecover 14y agoCan you get in the zone with people watching and judging you intently? If you can't get into the zone with only a couple of people watching you, how will you get into the zone when the whole company is depending on your bug fix? The pressure of judgement is not the same as the work pressure of a stressful scenario. It's why public speaking and job interviews are among the most feared activities people go through, but people consider meetings boring and mundane.
- merijnv 14y agoEasy, the company that is depending on me is not physically there, watching and judging me. Sure they probably are watching and judging me, but as long they're not physically present that makes all the difference to my mind...
- KirinDave 14y agoI can program a string reversal with my eyes closed, tied up in chains, upside-down, while holding my breath. Or whatever. The point is more that for a person with a given skill level, interviews can be stressful and make them perform below that skill level. I try to structure my interviews such that people get more comfortable and I don't ram their head into a metaphorical wall. I get all the same information, but without all those hard feelings.
- EnderMB 14y agoWhat a load of bollocks. If your job is to write methods to reverse strings then you are unqualified, otherwise I wouldn't give a shit whether a candidate can reverse a string. Why would I want to know if someone can reverse a string if the job is to maintain a web app? A few questions for you. How old are you? Have you hired developers before? Truthfully, have you ever had to reverse a string under pressure at your current job.
- borplk 14y agoAre you kidding? reversing a string in your language of choice is far too trivial. If you can't do it you really aren't ready to be working in the industry.
- cygwin98 14y agoOut of curiosity, when the interviewer asks you to reverse a string in your language, say Ruby, are you supposed to use existing algorithms/methods built-in in that language, or to flip each character using a for-loop? In Ruby, it's really a single method called reverse will do the trick, i.e., "hello".reverse gives "olleh". I'm trying to make sense of the reason why such a question is asked.
- candybar 14y agoNo, the expectation is that you'll use a loop or recursion. If you use an existing method/function, the interviewer will kindly ask you to implement that yourself. The general reason why such a question is asked is because interviewers don't have an infinite amount of time and there's no point in considering any candidate who can't do this. It's a way to weed out ridiculously bad candidates so that you can focus more on good candidates.
- EnderMB 14y agoIt's not about whether they can do it or not. It's about why knowing a skill that will take even a non-developer ten seconds to Google makes someone incapable of functioning as a developer. More often than not the people that spout that kind of nonsense are twenty-something junior developers that read a bit of HN and have decided that they know better than everyone else about what makes a good programmer. Why would you test if someone can reverse a string if you're hiring someone to maintain and build on some shitty web app?
- rybosome 14y agoBless you. I get extremely nervous in interviews as well. One that came right out of the gate with difficult questions (not saying string reversal is) would crush me.
- candybar 14y agoI haven't observed any correlation between being nervous and underperforming in answering technical questions. How do people get through math exams in college? If anything, I'd expect answers to non-technical questions to be far more influenced by the artificiality and unfamiliarity of the interview situation, being judged by a stranger, high-stakes, and everything.
- KirinDave 14y agoI actually got a lower GPA in college than I could have because of test anxiety issues in college, and I've since learned that it is hardly a rare condition.
- jlgreco 14y agoI wonder what kind of answers he gets for that. I think I would probably answer that verbally as "sixteen, spelled one-zero".
- just2n 14y agoI would think that 'G' would also be correct, in a base higher than 16, just like how 11 is just 0xB, 013, and 0b1011, depending on your perspective.
- jiggy2011 14y agoThey cannot reverse a string even using the API call? If so are these people who have held down a programming job before?
- jlgreco 14y agoI assume the question is something along the lines of "Implement a strrev in the language of your choice", not "Use the strrev equivalent in the language of your choice".
- Xion 14y agoEven with this addendum, there is a grey zone: reversed_string = string[::-1] Is it just using the equivalent, or a new implementation?
- jlgreco 14y agoIf I was the interviewer in that case I would probably accept that, with note that the person seemed clever. Then I would ask another harder question that I would hope would trip them up if they didn't understand iteration.
- nopassrecover 14y agoTo be fair though, reversing a string is not the kind of thing a lot of people deal with - there's usually a library function. Now they should be able to puzzle it out, but if it takes them a moment I'd be generous because I at least put it into the box of "that sounds easy, but oh wait a minute it's slightly different from my usual dev pattern". To put it another way - when I code it's rarely different from writing to me; code is simply an expression of thought. But when you ask me to do something that seems a bit artificial (reverse a string) it's like asking me to write a haiku - I can do it, but give me a moment while I count out my syllables.
- rauljara 14y agoI understood from near the very beginning that this wasn't really about Fizzbuzz. All the way through the post, I was waiting for the author to get a real world example instead of Fizzbuzz. Yet, I got to the end of the post and realized it was already pretty long. I think in talking about programming, we are often hindered by the fact that it is much more complicated than our brains can handle. Our only choices are to write novel length treatments of real programs or short story length posts about a toy program, or just the tiniest piece of a real program. Which is all to say, as sick of hearing about Fizzbuzz as I am, I'm glad there are silly little examples like it that we all know. Even though it was ostensibly about interviewing, that was a much clearer introduction to monoids than most. I think it was largely because it was in reference to Fizzbuzz: something very concrete with which we're all familiar. Too many introductions to Haskell's abstractions are too abstract. Good on the author for finding away around that.
- KirinDave 14y agoThanks! What sort of surprised me as I shopped my copy around and showed people the python-add-one-factor example is that even programmers I consider experts didn't realize how quickly the conditional cascade blows up. It's easy to miss. And I looked around for people to mention this in blog posts, but almost no one does. So I feel like there's a bit of life left in the old fizzbuzz yet.
- dspeyer 14y agoI think the non-blown cascade is exactly what makes fizzbuzz aggravating. With three noises, the linear solution clearly dominates. With two, the exponential is actually shorter -- but feels unclean.
- jerf 14y agoI've been programming some game servers, and I have the same problem with guaranteed two-player games; I feel dirty hard-coding the logic to assume two players, yet making it general enough for N players makes it absurdly more complex for no gain, which is a net loss. (And yes, before anyone pops in, these are guaranteed two-player games. Of all the rules of the games in question which have changed over time, that is the one rock-solid constant which will not change in this application.)
- absherwin 14y agoI agree that Fizzbuzz can be a more interesting example of how to write code without repetition. While the author suggests that languages such as Haskell provide a unique advantage, the deciding question seems to be the availability of pre-built abstractions. Consider the following solution in Python: for i in xrange(1,101): print (('' if i%3 else 'Fizz')+('' if i%5 else 'Buzz')) or i or the even more general: mapping={3:'Fizz',5:'Buzz'} for i in xrange(1,101): print ''.join(['' if i%x else mapping[x] for x in mapping]) or i We can even do this in C though to write something as extensible as the second would require writing more helper functions than I can justify for this brief comment: #include<string.h> #include<stdio.h> int main(){ int i; char s[4]; char n[3]; for (i=1;i<101;i++){ sprintf(n,"%d",i) s=strcat((i%3)?"":"Fuzz",(i%5)?"":"Buzz") printf("%s",(strlen(s))?s:n) } return 0; }
- wisty 14y agoJust as you can write FORTRAN or COBOL in any language, you can write functional code in any language.
- innguest 14y agoNo you can't, as you need the language to provide a few basic building blocks, such as lambdas, and the ability to pass functions as arguments.
- KirinDave 14y agoYou can generally approximate higher order functions in almost every OOP language. See C++ before it got lambdas, they have a pattern. See also java's anonymous inner classes, which are often used with the Runnable interface for that rule.
- KirinDave 14y agoIt is still crazy to me that in Python ('' or 10) == 10 # True That's like making the universe crazier one electron at a time. But yes, it's just about having the right abstractions. What's nice about the Haskell solution is that the right abstractions make the code much nicer (to my eye).
- droithomme 14y agoWe're five years into this, and here's yet another weekly column from a person who has just heard about it and is champing at the bit to prove both he can write FizzBuzz and all the other implementations are not as good as his. It will be a miracle if this thread doesn't turn into a chain of "even better" solutions, like all the other threads that came before it. In this week's installment, the variation where it is claimed that common production languages are inadequate for a problem of this complexity, and the tool stack should be shifted to languages supporting monads... er monoids? Sigh.
- KirinDave 14y agoI can't help but feel like you didn't read the article. The entire thing is basically an excuse to tell you about monoids. It's like a super long joke where the punch line comes way too late. But instead of a punch line it's monoids and instead of being funny it's not. P.S., hello edits!
- deleted 14y ago[deleted]
- rprasad 14y agoI would prefer to force candidates to implement FizzBuzz in a language invented solely for purposes of that interview (and which will never be used again). This places all candidates on the same level. It's probably a good thing I don't interview people for programming positions...
- jerf 14y agoYou have so little time in an interview to learn so much you can't afford to lose the time to both learn whether they can do FizzBuzz (or whatever other problem) and whether they can manipulate some language of interest, when you could be learning both The purpose of an interview isn't to be abstractly "fair", it's to find the best candidates for the job. You choose what "best" is (which is to say, please don't put words in my mouth about "only interviewing for the exact skillset" or whatever... you choose what is best, whatever that is). My preferred approach is to give the problem, then let the candidate write in whatever language they choose. If they flail in their putatively favorite language with which they've putatively been working for 4 years... well... I've certainly learned some very important things in those few moments.
- Swizec 14y agoI recently challenged people to codegolf fizzbuzz (http://swizec.com/blog/fizzbuzz-without-ifs-in-90-char-i-will-buy-you-a-beer-if-you-can-do-better/swizec/5276 http://swizec.com/blog/fizzbuzz-without-ifs-in-90-char-i-wil...) The Haskell solution was really cool: [max(show x)(concat[n|(f,n)<-[(3,"Fizz"),(5,"Buzz")],mod x f==0])|x<-[1..100]] This is much simpler and it looks easier to extend as well.
- Gazler 14y agoMy goto ruby solution looks something like: (1..100).map{|i|(f=[["Fizz"][i%3],["Buzz"][i%5]].join).empty? ? i:f}
- GeZe 14y ago60 character solution in LiveScript[0], without using 'if's, also easily extensible! [1 to 100]map(->[s for s,n of{Fizz:3,Buzz:5}|it%n<1]*''||it) [0]http://gkz.github.com/LiveScript/ http://gkz.github.com/LiveScript/
- andreasvc 14y agoUnfortunately not below 90 characters, but without loops or ifs: l=range(101) l[3::3]=100/3*['Fizz'] l[5::5]=100/5*['Buzz'] l[15::15]=100/15*['FizzBuzz'] print l[1:] This one is 86 characters by using constants: l=range(101) l[::3]=34*['Fizz'] l[::5]=21*['Buzz'] l[::15]=7*['FizzBuzz'] print l[1:]
- buu700 14y agoI wrote a JS one-liner solution the other day, though JS isn't quite as concise as Haskell: function fizzbuzz (n) { return new Array(n + 1).join().split(',').map(function (j, i) { return (i % 3 ? '' : ' fizz') + (i % 5 ? '' : ' buzz') || ' ' + i; }).slice(1).join().slice(1); } 185 characters Edit: If I move from a general solution to only 1-100 and remove spaces and semicolons: new Array(101).join().split(',').map(function(j, i){return (i%3?'':' fizz')+(i%5?'':' buzz')||' '+i}).slice(1).join().slice(1) Down to 126, but a lot of that is related to precision with the whitespace and handling a JS quirk with map on undefined values; without the extra joins/split/slices, it goes down to 83 characters (but also doesn't work).
- aristus 14y agocases = ( (3, 'Fizz'), (5, 'Buzz'), (7, 'Bazz'), (11, 'Boo'), (13, 'Blip'), ) for i in range(1, 101): out = [] for c in cases: if i % c[0] == 0: out.append(c[1]) if out: print ''.join(out) else: print i Edit: not to detract from the post's point, I think it's valid. Monoids are cool and all but simple counting arguments can take you a long, long, long, way when case analysis fails you.
- just2n 14y agoI agree. Same thing in JS. Also, this is precisely what I thought to do when he started asking about 7 and 11. (function fizzbuzz(n, cases) { var i = 0; while (i++ < n) { console.log(cases.reduce(function (prev, c) { return i % c[0] ? prev : (prev || '') + c[1]; }, null) || i); } }(100, [[3, 'Fizz'], [5, 'Buzz'], [7, 'Bazz'], [11, 'Boo'], [13, 'Blip']])); Excuse the terseness, I didn't want to make this post too lengthy, but it's still quite readable, IMO. Array.reduce was designed to solve problems like this.
- Xion 14y agoPrecisely. The Ruby solution author quotes as ideal and impressive seems way overblown to me. And I don't buy that ,,it would probably be dismissed as “overly complex” by younger programmers'' because it is exactly what I would consider perfect approach... few years ago. Since then I learned the value of simplicity, and abstractions with adequate flexibility. That Ruby code exhibits neither.
- KirinDave 14y agoFirstly, the ruby code was produced (admittedly from my memory) from someone on the tail end of a 5 hour interview process, of which I was not the first technical interviewer. It is exceptional in that context. Secondly, I feel like you (and aristus in his/her code snippet above) missed the secondary point of my post. Please consider that monoids and Maybe are capturing a higher level pattern in a way that we can compose. To write a classical for loop and toss in conditionals and whatnot is to descend to exactly the same depths as the Ruby code you say is not "simple". Basically, you say one is "simple" and the other is not is you picking up on what you're comfortable with in Python. Both are complex in the same way; the Python just makes a marginally better choice in how to represent the rules (as data). If you'd like to see how I'd take that piece of code and golf it to include that feature, I'm happy to oblige. I originally was going to post that, but cut it because the post was already overlong and the point is to explore the unusual patterns fp is capturing. Here is my bullshit golfing derivative, though: {-# LANGUAGE MonadComprehensions #-} module Main where import Control.Applicative import Data.Monoid import Data.Maybe import System.Environment factors = [(3, "fizz"), (5, "buzz"), (7, "bazz")] rules = [\i -> [res | i `rem` fac == 0] | (fac,res) <- factors] fizzbuzz d i = fromMaybe (d i) $ mconcat (rules <*> pure i) main = do upTo <- fmap (maybe 100 read . listToMaybe) getArgs mapM_ putStrLn [ fizzbuzz show i | i <- [1..upTo] ]
- ostso 14y agoFor more on monoids, see Brent Yorgey's paper _Monoids: Theme and Variations (Functional Pearl)_ at <http://www.cis.upenn.edu/~byorgey/pub/monoid-pearl.pdf> http://www.cis.upenn.edu/~byorgey/pub/monoid-pearl.pdf> (there's also a video of his talk at the Haskell Symposium at <http://www.youtube.com/watch?v=X-8NCkD2vOw> http://www.youtube.com/watch?v=X-8NCkD2vOw>).
- adiM 14y agoI was waiting for a Java solution with an AbstractFactory somewhere.
- LnxPrgr3 14y agoNo AbstractFactory here, but there is XML! And 411 lines of Java: http://pastebin.com/TyNrvRmB http://pastebin.com/TyNrvRmB
- romonopoly 14y ago"When you really boil it down to its implementation, FizzBuzz is something of an irritating program. I’m not sure how much the author of the problem really thought about FizzBuzz, but it turns out it’s difficult to express well with the tools available to most imperative programming languages..." Nonsense.. you call a simple loop with a couple conditions difficult?
- jisaacks 14y agoThe Ruby example that you recommending hiring because of, is overkill. Here is a better Ruby example: (1..100).each do |i| o = "" o.concat("Fizz") if i % 3 == 0 o.concat("Buzz") if i % 5 == 0 o.concat("Bazz") if i % 7 == 0 o.concat(i.to_s) if o.empty? puts o end
- deleted 14y ago[deleted]
- nandemo 14y agoThis seems overcomplicated. Why wrap String (which is already a monoid) inside Maybe? You can just use concat; if the result is the empty string then print the number. If you want it to work for any monoid, then use mconcat, and test for equality to mempty. And why introduce monad comprehensions if you're just introducing monoids?
- KirinDave 14y ago> Why wrap String (which is already a monoid) inside Maybe? Because it's a bit easier to write the tail end of the logic in generic terms. You can go talk to c_wraith on Freenode#haskell if you want. > You can just use concat; if the result is the empty string then print the number. If you want it to work for any monoid, then use mconcat, and test for equality to mempty. You can find other discussions about why flexibility is important. > And why introduce monad comprehensions if you're just introducing monoids? Because it's a really nice syntax? Compared to explicitly using guard, anyways.
- SeoxyS 14y agosubs = {3 => "Fizz", 5 => "Buzz", 7 => "Bazz"} (1..100).map{|n| subs.keys.inject(nil) {|a,k| n % k == 0 ? (a||"")+subs[k] : a} || n.to_s} Kind of boggles the mind sometimes to realize the crappy code people will write without thinking things through.
- pd_i 14y agoGreat article. The title is a bit misleading though. I thought this was sort of a counter-argument to the 'programmers cannot program', but introduces monoids right at the end. Anyway, FizzBuzz and the like are the kinds of questions you would probably ask to a new graduate because frankly, there is nothing else to ask from them. They have no related experience for the most part. For experienced ones, the way our company (http://aelogica.com http://aelogica.com) identifies good candidates is via a day of pair-programming. Technical knowledge is just part of the package, and any kind of problem solving will not address that.
- judofyr 14y agoI've always liked the \r-trick: a=b=c=d=(e=1..100).each do |num| print num, ?\r, ("Fizz" unless (a = !a) .. (a = !a)), ("Buzz" unless (b = !b) ... !((c = !c) .. (c = !c))), ("Bazz" unless ((d = !d) .. (d = !d)) ... (e = !e)), ?\n end
- ludovicurbain 14y agoFirst of all a modulo is ultra expensive, one does not simply modulo 15 when they already modulo 3 and 5. The proper structure is if(3){if(5)}elif(5){}else{},unless anyone has a better proposition. While of course it is possible to define abstractions that handle fizzbuzzing anything for any number, it's clear that the monoid way is a bad overweight bloated approach. Second the example written is code bloat à la java, writing tons of stuff for no reason. Third Ruby is a beta prototype language that doesn't have any production ready implementation. Lastly functional and procedural programming enable you to work at the highest level of abstraction you can think of, whereas OO tends to lock you at a specific abstraction level, which is pretty low and not adapted to most cases. I have to admit it's impressive how such a simple test can show so many failures in people's deep understanding of programming.
- KirinDave 14y agoThis is another example of someone who I think looked at my code examples but didn't read the post. Fair enough, I guess. > While of course it is possible to define abstractions that handle fizzbuzzing anything for any number, it's clear that the monoid way is a bad overweight bloated approach. Why? It is not computationally expensive, and it avoids excess modulo operations. All the dispatching work gets figured out at compile time and you end up with pretty much the same sorts of string concatenation costs you get in every other implementation. Do you mean to suggest that it is conceptually expensive? > Lastly functional and procedural programming enable you to work at the highest level of abstraction you can think of, whereas OO tends to lock you at a specific abstraction level, which is pretty low and not adapted to most cases. I actually agree with this, although I sort of question procedural's place on the totem. I suppose stuff like Forth suggests you're right.
- ludovicurbain 14y agoBloated, as in, takes way too much space for what it is. Additionally, it does _not_ avoid excess mod operations, _and_ the implementation is _broken_ because it won't print fizzbuzz for the 15. Lastly, using lambda's and whatnot's just because you can is yet another form of inefficiency and completely obfuscates what the machine will do. I mean to suggest that 1) it should be a much shorter read 2) it's inefficient, and wrong 3) one does not simply lambda everything.
- scotty79 14y agoMonowha? for(var i=1;i<=100;i++) console.info(((!(i % 3) ? "Fizz" : "") + (!(i % 5) ? "Buzz" : "") + (!(i % 7) ? "Bazz" : "")) || i);
- yjo 14y agoIn CoffeeScript: divisors = {Fizz:3, Buzz:5, Bazz:7} for i in [1..100] alert (name for name,divisor of divisors when i % divisor == 0).join("") || i