## DEV Community is a community of 642,931 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

loading...

# Unconditional Challenge: FizzBuzz without `if`

Nathan Kallman on June 15, 2020

As the title says, make a classic FizzBuzz function or method without using if/else (or equivalents like ternaries, ?:, sneaky). Specifically: T... Heiker • Edited

I'm sure I could make a fancy function composition but my brain is satisfied with this.

``````const Troo = (iff, elz) => iff;
const Falz = (iff, elz) => elz;

const If  = (boolz, iff, elz) => boolz(iff, elz);

const Boolz = {
from_bool: bool => [Falz, Troo][Number(bool)],
};

const is_fizz = n => Boolz.from_bool(n % 3 === 0);
const is_buzz = n => Boolz.from_bool(n % 5 === 0);

const fizzbuzz = n => If(
is_fizz(n),
If(is_buzz(n), "FizzBuzz", "Fizz"),
If(is_buzz(n), "Buzz", n)
);

const range = (end) => Array.from({ length: end }, (val, index) => index + 1);

console.log(
range(15)
.map(fizzbuzz)
.join(", ")
);
`````` Aldwin Vlasblom

Do you consider something like this cheating, because it builds on `filter`, a built-in, to handle the conditional logic?

``````const isFizz = n => n % 3 === 0
const isBuzz = n => n % 5 === 0
const complement = f => x => !(f (x))

const fizzbuzz = n => {
const fizz = [n].filter(isFizz).map(_ => 'Fizz')
const buzz = [n].filter(isBuzz).map(_ => 'Buzz')
const num = [n].filter(complement(isFizz)).filter(complement(isBuzz)).map(String)
return `\${fizz.join('')}\${buzz.join('')}\${num.join('')}`
}
`````` Nathan Kallman

Clever! I'll accept it for the normal challenge :)

If you want hard mode though, I think you'll have to show an implementation of `.filter` that doesn't use `if`, `?:`, `||`, `&&`, `?.`, or `??`. (I'll allow `.reduce` to be used though, as well as `.map`)

Well done, thanks for commenting! Aldwin Vlasblom • Edited

Okay, well, my next solution is probably not what you were expecting. It builds on the idea that a boolean can be used as a number. I think it meets the hardcore requirements.

``````const isFizz = n => n % 3 === 0
const isBuzz = n => n % 5 === 0
const isNeither = n => !isFizz(n) && !isBuzz(n)

// the magic:
const optional = (f, x) => Array(Number(f(x))).fill(x)

const fizzbuzz = n => {
const fizz = optional(isFizz, n).map(_ => 'Fizz')
const buzz = optional(isBuzz, n).map(_ => 'Buzz')
const num = optional(isNeither, n).map(String)
return `\${fizz.join('')}\${buzz.join('')}\${num.join('')}`
}
``````
Thread Aldwin Vlasblom

You are referring to the following clause:

Do this without "secret" conditionals like `||` and `&&` (in loosely typed languages like JavaScript)

My understanding is that this applies to the usage of such operators as conditionals when they are applied to non-boolean types. For example:

``````const fizz = n % 3 === 0 && 'Fizz' || String(n)
``````

In my code, it is used strictly on Boolean values, which I don't think was against the rules.

Thread Nathan Kallman

It uses it in a strictly boolean sense, which I'll allow. What isn't allowed is the loose/early-return way JS can use `&&`; a contrived example that would not pass hard mode:

``````const fizzbuzz = n => (n % 3 && (n % 5 && n || "Buzz")) || (n % 5 && "Fizz" || "FizzBuzz")
``````

(an easy litmus test: does changing the order of the `&&` expression change the result?) JP Antunes

Does this one count for the hard mode?

``````const fizzBuzz = n => {
const mapper = (arr, modulo, txt) => arr
.filter(e => e % modulo == 0)
.forEach(e => arr[arr.indexOf(e)] = txt);
let x = 1;
const range = [...Array(n)].map(_ => x++)

mapper(range, 15, 'FizzBuzz');
mapper(range, 5, 'Buzz');
mapper(range, 3, 'Fizz');

return range.toString();
}
`````` JP Antunes

How about with for loops?

``````const fizzBuzz = n => {
let x = 1;
const range = [...Array(n)].map(_ => x++);
for (let i = 2; i <= n; i += 3) range[i] = 'Fizz';
for (let i = 4; i <= n; i += 5) range[i] = 'Buzz';
for (let i = 14; i <= n; i += 15) range[i] = 'FizzBuzz';
return range.toString();
}
``````
Thread Nathan Kallman

Nice! I'll accept it even though I said no `for` loops because I like that you used the stepping statement to simply go through the multiples of 3,5,15. That's creative!

I was more expecting someone to abuse the `i <= n` into the `n % 3` type of check in a traditional fizz buzz. (especially abusing `while(n % 3)` into a more convoluted `if`)

Thread Nathan Kallman

Happy Juneteenth! I love everyone's approaches here, it's fun to see the way each person thinks through the problem.

I'll be posting my answers on Monday (along with the next installment of With Only CSS) so encourage your friends to give this a shot over the weekend (or take another go yourself)!

Follow me and react with a 🔖 so you remember to come back and see what I post here.

Drop a 🦄 or ❤️ if you'd be interested in some follow up posts going more in depth into each (OO/FP) solution: how they work; how they are similar; and how they are different.

Thanks everyone who took the time to post a solution to my little challenge; I'll see you all on Monday! Nathan Kallman

And here is my object-oriented approach (deeper article on it to come soon)

``````const baseBoolean = {
setThen: function(then) { return { ...this, then }; },
setOtherwise: function(otherwise) { return { ...this, otherwise }; },
};

const objectOrientedTrue = {
...baseBoolean,
evaluate: function() { return this.then; },
};

const objectOrientedFalse = {
...baseBoolean,
evaluate: function() { return this.otherwise; },
};

const objectOrientedNumber = {
value: 0,
isaMultipleCache: [objectOrientedFalse],
setValue: function(n) { return { ...this, value: n, isaMultipleCache: [objectOrientedTrue, ...Array(n).fill(objectOrientedFalse)] }; },
isaMultipleOf: function(dividend) { return this.isaMultipleCache[dividend.value % this.value]; }
};

const objectOrientedFizzBuzz = {
for: function(n) {
const number = objectOrientedNumber.setValue(n);
return this.three
.isaMultipleOf(number)
.setThen(
this.five
.isaMultipleOf(number)
.setThen("FizzBuzz")
.setOtherwise("Fizz")
.evaluate()
)
.setOtherwise(
this.five
.isaMultipleOf(number)
.setThen("Buzz")
.setOtherwise(number.value)
.evaluate()
)
.evaluate();
},
three: objectOrientedNumber.setValue(3),
five: objectOrientedNumber.setValue(5),
};
``````

Similarly to the functional approach; the main part of this solution is defining "true" and "false" as objects. But now instead of parameters, the objects have the same interface and return one or the other of the attributes set on the object. Nathan Kallman • Edited

As promised, here is my functional approach to solving this (deeper article on it to come soon)

``````const functionalTrue = (onTrue, onFalse) => onTrue;
const functionalFalse = (onTrue, onFalse) => onFalse;
const isDivisible = (dividend, divisor) => [functionalTrue, ...Array(divisor).fill(functionalFalse)][dividend % divisor];

const functionalFizzBuzz = (n) => {
const divisible_by_three = isDivisible(n, 3);
const divisible_by_five = isDivisible(n, 5);
return divisible_by_three(divisible_by_five("FizzBuzz", "Fizz"), divisible_by_five("Buzz", n));
};
``````

Similar to Heiker's solution above; the main part of this solution is defining "true" and "false" as functions taking the same two parameters but returning one or the other. Eric Nijman

This could probably get simplified (I've seen the one-liner of this one), but I still wanted to post mine

``````const fbMap = [
() => 'FizzBuzz',
String,
String,
() => 'Fizz',
String,
() => 'Buzz',
() => 'Fizz',
String,
String,
() => 'Fizz',
() => 'Buzz',
String,
() => 'Fizz',
String,
String,
];
const fizzBuzz = x => fbMap[x % fbMap.length](x);
`````` Mike Talbot • Edited
``````function map(compare, say, next = v => v) {
return function(value) {
return [() => say, next][Math.sign(compare(value))](value)
}
}
const process = map(
v => (v % 3) + (v % 5),
"fizzbuzz",
map(v => v % 5, "buzz", map(v => v % 3, "fizz"))
)

for (let i = 1; i < 31; i++) {
console.log(process(i))
}

`````` Mike Talbot • Edited

Slightly shorter without bothering to call out for variable potential conditions and using anons:

``````
let map = (compare, say, next = v => v) => v => [() => say, next][Math.sign(v % compare)](v)
const process = map(15, "FizzBuzz", map(5, "Buzz", map(3, "Fizz")))

`````` Nathan Kallman

I'm glad you liked it! I think its good to do a little self reflection on the way we do things every once in a while.

And WOW is that an impressive use of destructuring in JS. I knew about each of those things independently; I never have thought about putting them all together like that! Vidit Sarkar

Thanks for the problem. I guess this will not satisfy your conditions, but here is my solution,

``````const fizzbuzz = n => (!(n%15) && "FizzBuzz") ||
(!(n%5) && "Buzz") ||
(!(n%3) && "Fizz") ||
n
`````` Vidit Sarkar

Thanks for the reply. I think re-submission is also allowed. So, here is a C++ solution, which again, may not satisfy all your conditions.

``````string fizzbuzz(int n){
string num_string = to_string(n);

string all_options = {
{"FizzBuzz" ,"Buzz" , "Buzz"},
{"Fizz" , num_string, num_string},
{"Fizz" , num_string, num_string},
{"Fizz" , num_string, num_string},
{"Fizz" , num_string, num_string}
};

return all_options[n%5][n%3];
}
``````
Thread JP Antunes

Still not perfect, but this one comes with a special thanks to Mr. Kevlin Henney

``````const fizzBuzz = n => {
const isFizzBuzz = n => ( {false: '', true: 'Fizz'}[n % 3 == 0]
+ {false: '', true: 'Buzz'}[n % 5 == 0]
|| n.toString() );
let x = 1;
return [...Array(n)].map(_ => isFizzBuzz(x++)).toString();
}
`````` Nathan Kallman

Nice! I like how it uses `false` and `true` as keys on an object to select the resulting string.

If you can get rid of the `||` usage, then this will meet the hard mode requirements... JP Antunes • Edited

Well Mr. Henney has a great answer:

``````const fizzBuzz = n => {
const test = (d, s, x) => n % d == 0 ? _ => s + x('') : x;
const fizz = x => test(3, 'Fizz', x);
const buzz = x => test(5, 'Buzz', x);

return fizz(buzz(x => x))(n.toString());
}
``````

edit: but it still has a conditional... Bashu Naimi-Roy • Edited

I am posting for a friend who found some absolutely mind blowing ideas.

First a one-liner that extends my destructuring idea.

``````const fn = n => ({ ['2xx0x10xx01x0'[n % 15]]: result = n } = ['Fizz', 'Buzz', 'FizzBuzz'], result);
``````

secondly a solution built around a regex from hell/heaven

``````let fn = n => String(n).replace(/^(?=.*\$)(?:|(?:|*(?:|*))*(?:|*)|(?:|*(?:|*))*(?:|*))*\$/, 'FizzBuzz').replace(/^(?:|(?:|*(?:|*))*(?:|*)|(?:|*(?:|*))*(?:|*))*\$/, 'Fizz').replace(/^\d*\$/, 'Buzz');
`````` Ryan Westlund

Does this count as a secret conditional?

``````def fizzbuzz(n):
d = {(0, 0): 'FizzBuzz', (0, 1): 'Fizz', (0, 2): 'Fizz', (0, 3): 'Fizz', (0, 4): 'Fizz', (1, 0): 'Buzz', (2, 0): 'Buzz'}
return d.get((n % 3, n % 5), str(n))
`````` Nathan Kallman

I think your `.get` is a secret conditional. (It will return the value at the given `key` or the default IF the value is undefined)

If you can show how to implement `.get` without an `if` then I think this is a great answer! Ryan Westlund • Edited

How's this?

``````def fizzbuzz(n):
d = {(0, 0): lambda _: 'FizzBuzz', (0, 1): lambda _: 'Fizz',
(0, 2): lambda _: 'Fizz', (0, 3): lambda _: 'Fizz',
(0, 4): lambda _: 'Fizz', (1, 0): lambda _: 'Buzz',
(2, 0): lambda _: 'Buzz', (1, 1): lambda n: n,
(2, 2): lambda n: n, (1, 2): lambda n: n,
(2, 1): lambda n: n, (1, 3): lambda n: n,
(2, 3): lambda n: n, (1, 4): lambda n: n,
(2, 4): lambda n: n}
return str(d[(n % 3, n % 5)](n))
``````
Thread Jeremy Jacob Anderson • Edited

Has someone done this yet? It's really very fast.
There's a ternary there, I admit.

``````function fizzbuzz(i) {
let test = (d, s, x) => i % d == 0 ? _ => s + x('') : x
let fizz = x => test(3, 'Fizz', x)
let buzz = x => test(5, 'Buzz', x)
return fizz(buzz(x=>x))(i.toString())
}

Array.apply(0, Array(100)).map(function (_, i) {
i += 1
return fizzbuzz(i)
}).join("\n")
`````` Jeremy Jacob Anderson • Edited

I can't bring myself to be terribly interested in re-implementing language features like boolean or ternary. I loved seeing some of the really outlandish solutions like that un-sane RegEx that was posted. I enjoyed seeing the contortions done to avoid conditionals, too, but that's not something I'm into for it's own sake. I'm happy to fail at it.

There is a meaningful distinction between ternary and `if`.

`if` is a wilderness with few boundaries, as a form of Many-Valued Logic with an arbitrary number of values. Ternary is a specific subset of Many-Valued Logic; Three-Valued Logic. The Three-Valued Logic of ternary operators provides specific limitations that are not necessarily implied by the N-Valued Logic of the `if` statement. In most programming languages ternary is an operator, and `if` is a control structure block. Operators can be used in expressions, which is generally not true of `if` statements. Ternary is usually slightly computationally more expensive than `if` but has some advantages in terms of limiting complexity.

In real-world code I'm going to write an `if` (without `else if` or `else` if I can help it) about 95% of the time. It is both more readable and more performant in most cases. But when I need an expression that can make a decision between boolean and a maybe, I reach for ternary.

If you wanted to argue that `switch` is basically `goto` but potentially worse due to unintended fallthrough, then we'd have something to agree on.

The magic of the fizzbuzz problem is, of course, that it helps us understand in more granular detail that our design decisions, and design non-decisions, come with unavoidable trade-offs. It is a meditation on (a horrible term) `non-functional requirements`.