Hacker News new | comments | show | ask | jobs | submit login
A non-programmer’s solution to “Fizz Buzz” (nixonmcinnes.co.uk)
101 points by wintron 1604 days ago | hide | past | web | 54 comments | favorite



Boss: I need you to write me a program to print the numbers from 1 to 100

Me: Really? Is that really a business requirement? Any other requirements you need done?

Boss: Yes, it's your number 1 priority. No, just 1 to 100

Me: <a few minutes later> Done. Give it a review and I'll push it live.

Boss: <a few minutes later> No! I said 1 to 100 and everything divisible by 3 should be replaced by "FIZZ". Why didn't you do that?

Me: I'm pretty sure you didn't ask for that, but I'll do it right now. Any other requirements than FIZZ?

Boss: Thanks for taking care of this. There aren't any other requirements.

Me: <a few minutes later> Done. Give it a review and I'll push it live.

Boss: <a few minutes later> Seriously! Why didn't you put the BUZZ in there?

Me: What BUZZ are you talking about? You only asked for FIZZ.

Me: Wait a second, are you having me program FIZZBUZZ for you? What the heck!

Boss: Yes! Somebody on the internet asked how a non-programmer like myself would solve FIZZBUZZ!

Me: Sigh...


    Me: Really? Is that really a business requirement? Any other requirements you need done?
I landed a graduate assistantship in 1992 as "the computer guy's assistant" at my school's physical plant. My first assignment was to generate a fixed format file with one phone number per line. The file was to range from 1-900-0000 to 1-900-999-9999 and was needed by the campus telephone system to block all premium rate calls. They asked me to do it because they got back a 30 day completion estimate from the central IT department after filling out an internal RFP form.

I'm sure somewhere, someone has been paid to write a program that prints 1 to 100.


I know people who spent at least 40 hours/month just updating dates in monthly/weekly excel reports.

Edit: and had 6 figure salaries.


This should be the definition of a modern society.


Yes, but if you fuck it up heads are gonna roll.


I ended up doing the equivalent so many times I wrote a sequence command that had masks and could increment (count) through arbitrary series of characters (AVF => A, V, F, AA, AV, etc). Good for dataset fills.


Marketing: That's great, but can we change it so that it says now with 25% more buzz? And also get anyone who reads FIZZBUZZ to sign up for our newsletter?


Marketing: And can you add some social media buttons? That will help it go viral.


Sales: Yeah, our nerds just completed this new platform called FIZZBUZZ we want you to buy. What's that? Of course it's a fully-featured CMS/CRM/DataWarehouse/SocialMediaAggregator, the developers just have to make a few tweaks...they should be finished in a day or two at most.


Support: Your salesperson told you WHAT?! FIZZBUZZ isn't really capable of that, I'm sorry. No. No. I'm sorry, no. No, again, I apologize, I can't change that for you right now. If you'd like, I can put in a feature request for you. No, I can't give you an ETA...


Technical Cofounder: Can we release it as a simple REST API that lets you calculate fizz buzz in the cloud?


Researcher: What is the meaning of FIZZ and BUZZ? What's the definition of the operation by which FIZZ and BUZZ combine into FIZZBUZZ?


To be fair when doing front end work you sometimes need to make pretty patterns that do something like "print this table but apply this css class to every other row and one of these other classes to this row if a certain flag is set depending on what the previous class was".


And this is the problem I have with CSS selectors. What you just described is ridiculously fragile and will send shudders down the spine of any developer experienced with wrangling projects that have tangles of inappropriate coupling, but in many cases, there simply isn't a more elegant solution. Your options are:

1. Implement a sane (albeit less powerful) view hierarchy system, foregoing basically all of the CSS selector stuff, and applying styles individually. The framework will be big and unwieldy, and you'll take a performance hit, but you'll be able to maintain the client code.

2. Bite the bullet and implement it the ad hoc way, comment the crap out of it, and hope that whoever comes and changes something later will remember to read those comments.


This stuff is getting solved, for the particular example you can use n-th child in modern browsers[0].

[0]http://www.quirksmode.org/css/nthchild.html


Well, that sort of solves some of the problem, but in other ways it makes it worse. The fundamental problem is that mentally applying CSS rules is difficult, particularly when the DOM structure being styled is complex and is determined by an imperative program.

Imperatively generating and dealing with a DOM structure using simple selector queries is relatively easy to do, as is modeling what is happening in your head. Dealing with more complex CSS rules as they apply to a static (or dynamic but very simple) DOM structure is a little trickier, but not completely unwieldy. When you run into problems is when you try to do both simultaneously. Suddenly you have to not only mentally model a mutable DOM structure, but you have to model how those CSS rules will be applied in a generalized and abstract form. It's not hard to paint yourself into a corner where you'd actually start having to prove theorems about your code in order to be reasonably assured that the CSS will apply correctly.

Of course, hardly anybody actually lets it get that far. Instead, they start applying styles imperatively using JavaScript. And that sucks.

I don't know what the solution to this is, or if there even can be one that is a progression from where we currently are. But I don't think fancier CSS selectors are the answer.


the problem here is that CSS is _not_ a good abstraction for laying out application. Its good for styling (and i would argue, styling static content too). But css isn't very modular, and has very very high coupling with the structure of the DOM - something that isn't easily discernable at the time of modifying the css.

Like you, i can't think of a good solution - a lot of UI frameworks either just has really heavy restrictions, or it doesn't actually provide enough abstraction to actually help with the problem. Sigh...


3. Write your site in the form of a program that generates the site itself (or include javascript that generates the relevent pieces.)


That's the same as 1.


Or add classes during output generation.


Well yes, but I would consider that only a variation of option 1.


This sounds like a daily interaction with my current employer.

Sigh.


What's very interesting here is the SICP-style recursive looping, combined with the fact that the non-programmer doesn't expect to be able to pass variables but rather expects to make stateful queries. That is, the infrastructure expected (here written in JS) is:

    var query = {};
    function print(x) {
        console.log(x);
        if (typeof x === "number") {
            query = {last_num: x, time_since: 1};
        } else {
            query.time_since += 1;
        }
    }
And given all that, they have invented a fizzbuzz() which, as its last statement in each branch, calls fizzbuzz(). I like the way that it's graphically represented but I also think those semantics are quite interesting.


I wouldn't be so quick in concluding that the long back arrow stands for recursive looping. I'd guess it's just a non-coder notation for "and then do that thing again", for which the closest equivalent in actual language would be the `while` loop (most likely infinite, as the author remarked). I don't see the meta-level of considering the algorithm/procedure as a whole here, a one that is needed for thinking in terms of recursive application.

Furthermore, the fact that non-programmer expects to be able to poll the state of everything around (like the numbers which were already printed) would indicate that in their mind, there is no separation between the program/algorithm and the environment it is executed in. (Ironically, this is completely accurate viewpoint if we're thinking at the level of actual machines, be it real ones or abstract models like Turing machines.)


I think the arrows are being though of as GOTO`s.


Inspired by this, I translated the whole solution into JS. I renamed your "query" object to "output_state," which seems like a more accurate name.

    var output_state = {};
    function print(x) {
        console.log(x);
        if (typeof x === "number") {
            output_state = {last_num: x, time_since: 1};
        } else {
            output_state.time_since += 1;
        }
    }

    function fizzbuzz() {
        switch(output_state.last_num) {
            case undefined:
                print(1);
                break;
            default:
                var a = output_state.last_num;
                var b = output_state.time_since;
                var number = a + b;

                if (number % 5 !== 0) {
                    if (number % 3 === 0) {
                        print("Fizz");
                    } else {
                        print(number);
                    }
                } else {
                    if (number % 3 === 0) {
                        print("FizzBuzz");
                    } else {
                        print("Buzz");
                    }
                }
        }

        fizzbuzz();
        // Or, correctly: if (number < 100) { fizzbuzz(); }
    }


I too was struck by the fact that it's essentially an FSM. It's cool that a non-programmer will naturally gravitate towards that structure, while we're forced to spend weeks learning it in upper-level courses...


This is a perfect illustration of why programming is easy if you have aptitude for it, at least on a small scale, but almost impossible if you're not. Clive is already a programmer; he just doesn't know any programming languages yet, and anyone can learn those.


Yep, he's already thinking things through like a programmer, practice is all he needs really. I'd get him started on learning python/ruby/javascript or whatever and see if he enjoys it.


Site is down, here's a PDF of the solution: https://nm-files.s3.amazonaws.com/clive-fizz-buzz.pdf


And if you prefer to not leave your browser, here's a Google Viewer-rendered version of that PDF: https://docs.google.com/viewer?url=https://nm-files.s3.amazo...


Hi All.

I'm Clive, Wintron's non-programmer colleague and the guy who tried FizzBuzz on the piece of paper.

I feel fascinated by the fact people are examining the approach I took, and a little flattered by the nice remarks people have made about the fact I should maybe move on to learn a programming language. Maybe I will.

If I'm honest, I don't understand all the observations people have made, but there's one I do understand, and wanted to shed some light on: the point about iteration.

The exercise reminded me of some kind of in-the-round drinking game, where everyone is determining the responses one by one, as an iteration of the last number. Consequently, this shaped the way I approached the problem.

In retrospect, I completely see that I would have been better off simply counting from 1 to 100, then translating each of the 100 numbers into how it should be displayed (Fizz, Buzz, FizzBuzz or as a number). But recreating the drinking game in my head, it made perfect sense to me that each number is determined by being an iteration of the last one. That feels to me like I count in real life.

Thanks again for taking an interest, and yes, maybe I will ask Wintron/Steve to teach me some programming!

Clive


I've been thinking a lot lately about what sorts of systems "the rest of us" (where by "us" I mean "them") are able to program effectively.

One thing I've noticed is that people that don't really know programming in a hacker sense seem to have no problem creating a spreadsheet that calculates even fairly complex things (not that FizzBuzz is complicated, but see here: https://docs.google.com/spreadsheet/ccc?key=0AnUa0E6R--UedGd...).

I think one of the biggest factors is that users don't have to keep track of the order of operations. If you change the value in cell A1, and cell B6 depends on it, and D5 depends on it, and so on until you get to Z22, there's no step-by-step thinking about what order the calculations will be done in. Basically a change in the input is instantaneously (and automatically, transparently) reflected in the output.

Another big factor is that all state is made explicit by default.

In some ways it seems similar to functional reactive programming. The code for e.g. FizzBuzz looks crazy complicated (http://www.lejordet.com/2012/01/fizzbuzz-with-reactive-exten...), but if you hooked it together in a GUI (sort of how Quartz Composer works on the Mac) it would probably be pretty easy to wrap your head around, and probably possible for someone with no formal programming knowledge to figure out, if not recreate.



Which doesn't include the image of the solution since the server hosting the image is down.


You can click on it


I like how instead of giving a procedure to produce the whole answer he created an induction-style algorithm that, given part of an answer, produces the next output.

Looks like "The mathematician's solution to Fizz Buzz"


Is this really an "induction-style" algorithm? (I haven't actually heard that term before.) I usually associate induction with taking some large input and shrinking it at each step until you hit some base case. This is really the opposite of induction--it starts with a base case (1) and grows the output, which makes this sound a bit more like co-induction.

Another way to think about it would be that he defined a little finite-state automaton to compute the answer. You just run the automaton for as many steps as you want, noting down what it outputs each time. I think this is actually very much like what a programmer would write if tasked with solving FizzBuzz in an online streaming fashion (rather than for some bounded n).

Maybe it's just my bias towards functional programming showing, but I actually think this approach is fairly intuitive. In fact, I would have probably come up with something structurally similar (differing only in details).


You're right, it looks like co-induction the term for what I was thinking.

Is it a common FP technique to do local-state-less looping like that? I would expect a tail-recursion solution to pass the next or previous value rather than re-deriving it from reading the output.


Agree with the mathematician point. It looks a lot like something (I think) I would come up with if I didn't know any programming.


In other words, this person seems to be expressing a tail-recursive solution? Interesting. I would agree that tail-recursion is probably more intuitive than stateful iteration to a mathematician as well.


I don't wish to complain but does that look like an infinite loop to you?

Programs are just algorithms, a flow diagram is just a different programming language


It's an infinite loop, and the b variable isn't necessary, but it's interesting to see how a supposed non-programmer is able to structure a (near) solution.


It is actually a complete solution to the problem as stated. The only requirement are that the numbers 1 through 100 are printed, with fizz, buzz, and fizzbuzz replacing them where appropriate. It is not a requirement that that is all that the program does.


Programs are more than just algorithms, they are also documentation of that algorithm. Sometimes they also describe checked invariants of the execution of that algorithm (types).

There's probably a lot more to say about programs that doesn't fit within the "just algorithm" view.


This inspired me to do FizzBuzz in CSS: http://codepen.io/SachaG/pen/jCpba


I must say that's a really unique approach to the problem, very well done!


It's always interesting to have a peek at how how non-programmers think. What I dislike about these sorts of posts though, is the comments, where everyone feels like it'd be useful for them to submit yet another trivial Javascript, C or Python FizzBuzz implementation. Congratulations! You can do a basic programming task in a popular language!



Good for Clive for being a sport and coming up with a valid answer, of course, but this is what interested me about his response:

He tackled the problem on a "meta" level, but didn't grasp the math. He could have saved a lot of time by seeing if the number was divisible by 15.


No if statements and a single, convoluted line: http://jsfiddle.net/P8Dr2/2/


Good work, but why make it so complicated? http://jsfiddle.net/4NnVw/3/


Shouldn't the ternary operator be excluded as well if you're doing 'no ifs'?


That sounds like a mathematicians mind.

Peano Axioms and all that.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: