I failed this coding challenge because my solution "does not scale for new divisors and iterations"

I think it is actually a design (pattern) question, and would very much appreciate if anyone can describe a good high level solution (eg class relationships).

Problem:
Write a program that will iterate though a sequence of integers starting from 0 up to
and including a number that can be passed in and the program will:

  • output the number and “FOO” only when the integer is divisible by 3
  • output the number and “BAR” only when the integer is divisible by 5
  • but when the integer is divisible by both 3 and 5 then don’t write the above,
    output the number and “BAZ” instead
    Take into consideration that we might want to add new rules in the future including
    different numbers, operators and iteration patterns.

It's pretty vague. Can you give examples of other kinds of "operators" and "iteration patterns"?

This is a standard homework problem and we don't do homework.

commented: I would say it comes up more as a standard interview question, but since we don't do those either, it amounts to the same thing. +13
commented: Shame folk seem to aks others to do their homework. +15

This problem is most often given under the name "Fizzbuzz", being based on an old children's math game of that name, but as Rev Jim said, it is a problem that a lot of professors use as a check on how well students understand the material, as well as being a favorite of lazy interviewers who don't realize that anyone who has been programming for a few years will have seen it before (to be fair, it wasn't a bad choice fifteen years ago, but today it has been done to death).

A quick web search on the first line of the problem statement should have found literally thousands of relevant hits, even without the usual name attached, so the fact that the are asking this at all indicates a lack of effort. Note that the name 'Fizzbuzz' comes up in one the first

Presumably, changing the words from "fizz" => "FOO", "buzz" => "BAR", and "fizzbuzz" => "BAZ" was to throw off a simple search (as 'foo', 'bar', and 'baz' are standard metasyntactic variables, and searches on them would get a lot of other things instead of the Fizzbuzz problem), as well as keep you from using one of the more common approaches to the problem (one which works for the usual problem, but doesn't scale).

Now, Fizzbuzz is indeed a deceptively tricky problem; that's the whole point. It is not one that really demands much in the way of design patterns or higher-order operations, however, as the usual code for it is a single procedural function. Overthinking it is part of the trap, in fact, and can lead to some bizarre implementations, but the good solutions for it are generally simple ones.

Note that by 'iteration patterns', the person giving the problem didn't mean design patterns, but rather the patterns of numbers; 3-5-15 is the usual one, and for good reason, but it can be done with other number sequences of the form [x, y, x · y] to the same effect, and different sequences to other effects.

Also, you never mentioned what programming language this was supposed to be in (or if it was in one at all, and not in a pseudo-code or some kind of flowchart or flow diagram). That colors the problem significantly, more than you might think, as there are ways to use specific language features to simplify a general algorithm that would be too complicated to use in the time given during an interview. Still, the basic problem is simple enough to be done in most programming languages in less than 15 lines of code, tops (well, unless it is in something extremely verbose such as an assembly language, COBOL, or Eiffel).

Comparing solutions for the basic (non-generalized) problem in C, Java, Python, Scheme, Haskell, and Forth might be of interest (or maybe not, given how little effort you seem to be putting into this). Examples for the more generalized version of the problem can be found on Rosetta Code as well. Note that there are several solutions possible.

commented: Bizarre implementations? How else to avoid being called out for plagiarism but to make the most bizarre solution? +15

"It's pretty vague. Can you give examples of other kinds of "operators" and "iteration patterns"?

  • I agree, I don't know what they were after either. I was hoping to get some insight here.

"This is a standard homework problem and we don't do homework."

  • This was a code challenge rather than homework per se. I failed and have no oppurtunity to retake. However, I would just to improve and not fail for a similar reason next time. If there are other more suitable forums to discuss design I would be interested.

"would say it comes up more as a standard interview question.."

  • If there is a standard solution to this Extensibility problem please let me know.

@Schol-R-LEA

I should have mentioned the role was for Senior Java Developer, but I am interested in a solution in any object orientated language.

The Fizzbuzz problem is itself trivial, but in my experience such code challenges are really testing your knowledge of other stuff (TDD, SOLID, structure, readability, maintainability, documentation etc). I don't believe solutions in 15 lines of code would be well received.

I think the key part of the question is "Take into consideration that we might want to add new rules in the future including different numbers, operators and iteration patterns."

I was warned that most candidates fail this due to lack of extensibility (please highlight any solutions you may have found that address this).

On the other hand I may well be overthinking the problem as you suggest... The frustration is that I do not know what their model answer is.

For a problem like this I would suggest the following steps:

Break the problem down:

You need numbers to iterate over and you need 2 divisors which when multiplied will give you the third.
You need a structure to output a collection for the answer.
What if they decide to use bigger integers or floating point types? You would need a way of handling that.

Once you get these 3 problems figured out, you will be well on your way to a viable solution. The actual design pattern would depend on what you're familiar with or are willing to learn about as well as the language you choose. In my opinion, if you're not familiar with OOP, start with that. Many of the other design patterns use OOP in their design. I might add that just because a language is object oriented doesn't mean that your solution follows OOP practices.

commented: Wise words. "Break it down." So many problems can be tackled by breaking it down, even if you have to do many breaks. +15

I was warned that most candidates fail this due to lack of extensibility
Taking a guess : they would like "3" and "5" defined as variables in the beginning and then apply the variables rather than "3" and "5" later in the code, so that the numbers could easily be swapped?
Or perhaps making the code such that it could support a 3rd or unlimited number of multipliers that would all produce different outputs when combined with other multipliers; that would be a PITA and probably not what they're asking for.

@Joseph, your quote reminds me of many software development cycles. The specs are rarely clear and when not, you get what you asked for.

You got exactly what you asked for.

Let's look at the specifications:

  1. output the number and “FOO” only when the integer is divisible by 3

Clear and concise.

  1. output the number and “BAR” only when the integer is divisible by 5

Also clear and concise.

  1. but when the integer is divisible by both 3 and 5 then don’t write the above, output the number and “BAZ” instead

Still clear.

  1. Take into consideration that we might want to add new rules in the future including different numbers, operators and iteration patterns.

Here's where we get into trouble. As a software developer I would refuse this request on the basis of too little detail. If I was still forced to provide a solution I would provide (minus the input validation and /help text)

for i = 1 to num
    select case i mod 15
        case 0       : Wscript.Echo i, "BAZ"   'divisible by 3 & 15'
        case 3,6,9,12: Wscript.Echo i, "FOO"   'divisible only by 3' 
        case 5,10    : Wscript.Echo i, "BAR"   'divisible only by 5'
        case else    : Wscript.Echo i          'everything else    '
    end select
next

The code is almost self explanatory and requires only minimal commenting. It would be easy for someone to modify for other multiples. A spec that says "we may want to add new rules" is too vague to be worth anything more than derisive laughter or a short sneer. In an interview I would say that I would reject such a spec. I wouldn't work for a company that expected me to accept it and I would reply as such. I would hope that by doing so I would be demonstrating a commitment to quality code.

commented: Or "Muhaha" as you code darkly. +15

If this is in the context of a Senior Java Developer then maybe they are looking for some more genrelaised approach such as
define a functional interface Rule that takes an int and returns a String or null
define a collection of Rules
populate it with the three Rules as simple lambda expressions
add a final rule that always returns the int as a String
try all the rules in turn against each int until a rule returns a non-null string.
Now its easy to add new rules that perform any kind of test on the int. Eg

        List<IntFunction<String>> rules = new ArrayList<>();
        rules.add(i -> i % 15 == 0 ? "BAZ" : null);
        rules.add(i -> i % 5 == 0 ? "BAR" : null);
        rules.add(i -> i % 3 == 0 ? "FOO" : null);
        rules.add(i -> String.valueOf(i));

        for (int i = 1; i <= 100; i++) {
            for (IntFunction<String> rule : rules) {
                String res = rule.apply(i);
                if (res != null) {
                    System.out.println(res);
                    continue;
                }
            }
        }
commented: Meets spec. Ship it. +15

It's what I asked for but it's not what I want.

Typical user response upon receiving software.

commented: Also, most clients. +0
commented: So true +14

@JamesCherrill Looks like some pretty nice code, however shouldn't the inner loop break after a good response,only one response allowed per number, and shouldn't the response from the first 3 rules include the number and the string?

@tinstaafl: Yes, I typed continue instead of break by mistake. And missed the number printing. Sorry - I just hacked that into the edit window to illustrate what I was suggesting..

Here's a much improved version that I actually tested:

        IntStream sequence = IntStream.range(1, 100);
        // ... or any other sequence of ints

        List<IntFunction<String>> rules = new ArrayList<>();
       rules.add(i -> i % 15 == 0 ? i+"BAZ" : null);
       rules.add(i -> i % 5 == 0 ? i+"BAR" : null);
       rules.add(i -> i % 3 == 0 ? i+"FOO" : null);
       rules.add(i -> String.valueOf(i));
       // ... or any other rules based on i

        doIt(sequence, rules);

where the doIt method is just a black box:

void doIt(IntStream sequence, List<IntFunction<String>> rules) {
        sequence.forEach(i -> {
            for (IntFunction<String> rule : rules) {
                String res = rule.apply(i);
                if (res != null) {
                    System.out.println(res);
                    break;
                }
            }
        });
    }

I am almost new to lambda expressions, but thanks to you, I could write the same code in VB.Net:

Module Module1

    Dim rules As New List(Of Func(Of Int32, String)) From {
            Function(x) IIf(x Mod 15 = 0, "BAZ", ""),
            Function(x) IIf(x Mod 5 = 0, "BAR", ""),
            Function(x) IIf(x Mod 3 = 0, "FOO", "")
        }
    Sub Main()
        For i As Int32 = 1 To 100
            Console.WriteLine(i.ToString + " " + applyRules(i))
        Next
        Console.ReadLine()
    End Sub
    Function applyRules(p As Int32) As String
        Dim sRet As String = ""
        For Each rule As Func(Of Int32, String) In rules
            sRet = rule.Invoke(p)
            If sRet.Length Then
                Exit For
            End If
        Next
        Return sRet
    End Function

End Module

Hey, thats really neat.
Lambas are relatively new in Java, so I'm still learning and discovering more and more uses for them. Great fun.

How about a VB equivalent for the IntStream? The spec asks for "different iteration patterns" and IntStream allows for any arbitrary sequence of ints. IntStream.range gives you a range of consecutive integers, but (thanks to lambdas!) you can map that to even numbers, perfect squares, etc etc, or you can just supply a list of numbers that you made up.

Perhaps, array can do the work of Java's IntStream. For instance, to square a sequence of numbers:

    Sub Main()
        Dim arr() As Int32 = {2, 5, 6, 8, 3}
        Dim square = arr.Select(Function(x) x ^ 2)
        For i As Int32 = 0 To square.Count - 1
            Console.WriteLine(square(i).ToString)
        Next
        Console.ReadLine()
    End Sub

Line 3 looks like a direct equivalent for
square = sequence.map(i -> i*i);
but is there a simple equivalent to
sequence = IntStream.range(1, 100)
or
IntStream generate(IntSupplier s)
that uses a supplier to create values on the fly; useful for bizzare sequences or very long ones?

(I'm not trying to start a my-language-is-better-than-yours fight. My last real exposure to Basic was developing an application for the Mac Plus in ZBasic in 1989, so I had no idea that functions could be first class data types in VB. I'm learning stuff here.)

I'm not a Visual Basic advocate, I just use VBasic and like it because I code with it. Here is a 'workaround' to generate a sequence of integers and iterate through the sequence:

Module Module1
    Sub Main()
        Dim oRange As New Range(1, 100)
        For Each r In oRange
            Console.WriteLine(r.ToString)
        Next
        Console.ReadLine()
    End Sub
End Module
Public Class Range
    Implements IEnumerable
    Dim min, max As Int32
    Public Sub New(min As Int32, max As Int32)
        Me.min = min : Me.max = max
    End Sub
    Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
        Return New RangeEnum(min, max)
    End Function
End Class
Public Class RangeEnum
    Implements IEnumerator
    Dim min, max As Int32
    Dim curr As Int32
    Public Sub New(min As Int32, max As Int32)
        Me.min = min : Me.max = max : curr = min - 1
    End Sub
    Public ReadOnly Property Current As Object Implements IEnumerator.Current
        Get
            Return curr
        End Get
    End Property
    Public Sub Reset() Implements IEnumerator.Reset
        curr = min - 1
    End Sub
    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        curr += 1
        If curr >= min AndAlso curr <= max Then
            Return True
        End If
        Return False
    End Function
End Class

And clarity has been completely sacrificed.

commented: At least it doesn't look plagiarized. +0

Hi All,

Thanks for all the responses; while I am still not sure what they were after, I am at least heartened by the general consensus that the code challenge was ambiguously worded.

@JamesCherrill, I doff my hat to your Functional Interface suggestion -That is a cunning means of adding new rules I had not considered !

Kind regards :)

Thanks. I did have fun with the lambdas for the rules, but I'm equally excited by the IntStream to generalise the "iteration pattern". To show its versatility here's a simple fibbonaci method...

    int next = 0, prev = 1, pp = 0;  
    int fibb() {
        next = prev + pp;
        pp = prev;
        prev = next;
        return next;
    }

so now I can fizzbuzz the fibbonacci sequence without changing the doIt code by simply

sequence = IntStream.generate(this::fibb).limit(40);
doIt(sequence, rules);

I find that quite exciting!

A challenge like that? Sounds like waste of time.

commented: Wait, what? I suppose I ought to feel flattered, but I am really just confused as to why this person bothered... -3
commented: More crap from this troll who will soon enough commit infraction suicide -4

Perhaps the challenge was to see how the applicant deals with an incomplete spec. I don't consider that a waste of time at all.

commented: I agree. Most projects I've been on have deficits in the specs. +15
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.