39
votes
Programming Challenge: creative FizzBuzz
Pretty standard:
Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.
The twist: come up with the most creative or unusual way to solve this in your language of choice.
I only know how to code at a really basic level, but a weekly coding challenge would be quite cool to have on ~comp.
Neural network fizz buzz is also worth mentioning.
Here's one I prepared earlier (python 2.7 only):
I'm an idiot. What's going on here? I see numbers with multiples of 3 and multiples of 5 in there. What am I missing?
Nah, you're not an idiot, it's just really obfuscated code. It looks like it reads its own source code and does some fuckery with the embedded comment, though I honestly don't know what exactly that is. Something to do with converting to integer values, then to byte arrays, and then finally to strings, but the details escape me.
Code golf and code obfuscation really aren't my cup of tea and certainly not my area of expertise, so unfortunately this is about as much insight as I can give you.
Ok, I cant code but my god can I excel. So I did.
Image of my final outcome.
I used this formula in each cell (where A24, in this case, is the cell number):
=IF(AND(MOD(A24,4)=0,(MOD(A24,3)=0)),"FizzBuzz",IF(MOD(A24,3)=0,"Fizz",IF(MOD(A24,4)=0,"Buzz",A24)))
MOD(A24,4)=0
Essentially asks do you get 0 when you divide cell A24 by 4? If you do it must mean it is a multiple of 4. I use this basic way of finding out if it is a muiltiple as the basic for the rest of it. I use an 'and' statement to check first of all if it is a muiltple of both if it's not it tries the other two individually.Essentially It is one big if statement. In laymen's terms, it's asking
Is this cell divisible by 4 and 3? If so return "FizzBuzz", if not is it divisible by 3? If so return "Fizz", if not is it divisible by 4? If it is return "Buzz" if not just what value is the cell.
To be fair, I'd count that as coding.
Silicon Valley here I come.
Man, you opened with a bad topic (jokes) but I'm not failing to giggle at every comment you write :D
Excel is Turing complete so it's definitely coding.
If you're interested in learning to code, it's a small (purely syntactical) jump from what you already know.
The big change is basically learning to keep in mind the structure you're building and learn how to output the final result the way you want.
The big change is basically learning to keep in mind the structure you're building and learn how to output the final result the way you want.
I just gave this problem a shot in Excel and came to same solution as you. I did consider using another IF(MOD(ref,15)=0) instead of the AND(), since 15 is the lowest common multiple.
On the one hand, a shorter formula always looks more elegant. On the other hand, that's using knowledge calculated outside the program, which feels like bad practice to me. What does everyone else think?
I've been wanting to see how hackable quines are and came up with this just now.
The quine was found on some big listo'quines and looked the most adjustable.
I can run it with the .bat file:
and it'll churn out the source for the next iteration along with the output at the top in a comment.
I really like quines for some reason and I might start fiddling with them even more. I like the idea of having a quine clock that constantly recompiles and re-runs for each output. But i haven't had much luck with that so far.
I hate to be nitpicky, and I may be wrong here but with this logic:
This should not be needed.
For example, e=14 will hit the first 2 if statements printing fizzbuzz then also hit the third with the final line being fizzbuzzfizzbuzz. I'm purposefully ignoring the rest of your solution, as it is pretty neat! :)
By all means feel free to nitpick, it's the only way I keep learning. Thanks for pointing that out.
I think I spent most of the hour trying to figure out how to perform surgery on the quine and forgot about what it'd be outputting and whatnot haha
That's exactly what I figured happened. All of us know many solutions to this problem, so the basics are easy to overlook.
Thanks for this solution though, I hadn't looked into quines yet!
I'm an amateur programmer, so I'm mostly proud that it worked on the first try. Then I googled the print_function stuff to clean up the output a little
outputs
If you want to tighten that up a bit more:
Just in case you want to work on making something a bit more magical and a bit less readable. Also note: the above only works in Python2 not Python3 (which is not what I would recommend learning).
Here's a Py3 version:
Here's a more ridiculous Py3
I tend to like readable, but magical can be more efficient and requires a greater understanding, so...
In the py2 example, it looks like you're using * as a conditional where it will print eg. 'Fizz' if x%3, but what is the /2 and how does it translate to modulo 0? And why is it /4 in the modulo 5?
In the first py3 example, you're populating a list with a map of a defined lamda, then printing the list. I again see * as a conditional, but the order is swapped ("print 'Fizz' if i%3==0" rather than "if i%3==0 print 'Fizz'). Is this a py2/py3 difference, or because you're doing it in a lamda?
I only ask here because I have no idea what I'd be googling. And the "ridiculous" py3 appears beyond me for the moment ("Mmhmm. I understood some of those words")
In the first py2 example, the division is floor division and the * is string multiplication.
Floor or Integer division: in python 2, if you use integers to divide, you'll always get an integer, and it's the mathematical floor of that divison, ie
75/76 == 0
. In python 3, division coerces a float and you need to use the double // to get floor division.String multiplication writes the string that number of times.
'Fizz' * 3
gives you'FizzFizzFizz'
.Let's consider just the 'Fizz':
Some real values.
Set
x=0
:Set
x = 1
:Set
x=2
:The same processing works for buzz (it just takes longer to write down), but notice that FizzBuzz will happen automatically because you concatenate the string results together. So '' + '' is still not truthy, but '' + 'Buzz', 'Fizz' + '', and 'Fizz' + 'Buzz' are all truthy.
The same "trick" is being done in the first Py3 example.
The second Py3 example is just silly obfuscation; I didn't write it, but I did find it once upon a time in an obfuscation golfing thread. If anyone is unfamiliar with either term:
Edit: this comment got out of hand.
First off, TIL "string multiplication"
So if I'm reading this correctly, it works because you're looping through 0-99 and adding 1 at the end so that it's 1-100. This allows the uniqueness of the x%3=2 result to serve as a pseudo-conditional (doubt that's a word, but it makes sense to me, dammit!) via truthiness since adding 1 to any such number gives you a multiple of 3.
[Edit: what makes " not truthy?]
That's almost it.
The "trick" is that
x
in this case is not the number that gets displayed. A lot of people see this question as "make a list of numbers from 1 to 100; for each number, check if it's divisible by three, and if it is print Fizz. Otherwise, print that number". But that's not what this one-liner is doing; it's actually testing if the number above whatever the current x is is divisible by 3. This is a minor change, but it makes things much easier todeal withmake into a single line of seemingly "magical" code.A blank string is considered
False
; a non-blank string is consideredTrue
. There are a number of times this can be useful; the concept of "truthiness" in python is pretty great. This stackoverflow answer about Truthiness and Falsiness is pretty succinct.I included some later iterations of the one-liner in Python2, just in case that helps. I think they illustrate the slight difference in what we expect to see.
Consider
x = 43
,x = 44
andx = 45
. If we're looking at the rules of FizzBuzz without looking at this one-liner, we'd say that the result we expect is "when x = 43 or x = 44, the program should print x. When x = 45, the program should print FizzBuzz". But that's not what this program actually does.For
x = 43
our brain thinks "43 is not divisible by 3 or 5, so print 43", but this program prints 44:For
x = 44
our brain thinks "44 is not divisible by 3 or 5, so print 44", but this program prints "FizzBuzz":For
x = 45
our brain thinks "45 is divisible by 3 and 5, so print FizzBuzz", but this program prints 46:Ah, I was reading " as a character (and therefore a non-blank string) but you had typed '', which is a blank string. Pebkac.
It really is a nifty trick. I think I could have worded my interpretation better as "when
x%3=2
, x+1 is divisible by 3". Adding +1 at the end when you're printing lets you take advantage of the unique state created when floor dividing(x-1)%n // (n-1)
(in that the statement will only evaluate true forx%n=0
. That "trick" doesn't work unless you're iterating over x-1.Ah, sorry - the '' was just an empty string. I should have made sure to
''
backtick them.And you definitely get it, based on your last paragraph (which is great for someone who identifies as an amateur!).
A quick note, your solution is just slightly off.
range(start, end)
will give you a range of integers starting fromstart
inclusive and ending atend
exclusive, mathematically represented as[start, end)
.In this case, your solution covers the range from
1
to99
, whereas the expected solution should cover the range from1
to100
. To fix this, you could dorange(100)
and perform your operations onnum
using an offset, i.e. onnum + 1
, or you could change your range to berange(1, 101)
.The form of your solution is on point, though. Good use of if statement chaining instead of specific if/else cases. A lot of people don't really think of that, so it's a nice touch!
D'oh, that's what I get for not doublechecking!
How about using obnoxious amounts of currying?
Oof ouch owie my IIFE
This is a good one!
Here's a bonus for you using copious amounts of mapping:
This reminds me of this hilarious post on stackexchange.
Among the many things I try to teach interns, "try to avoid doing 'clever' things because it will cause you headaches in the future" is one of them. I like to use solid examples, of course, like the ol' XOR trick for swapping values between two variables without an intermediate third variable.
Would you consider the XOR trick an example of cleverness?
Yes, absolutely. It definitely works, but it relies on the more subtle details of how bit manipulation works. If you're unfamiliar with how it works, then you need to do some research and potentially take the time to prove to yourself that the logic is sound. It takes a lot of mental overhead to verify and maintain just a few lines of code.
Unless you have a direct need for it, it's far better to use the explicit temporary variable. Even if you do have a genuine need, you should at least document such tricks in detail.
Granted, the XOR trick is documented well enough and is short enough that it's not too bad, but writing maintainable code requires discipline and allowing yourself to use small tricks here and there will almost inevitably result in those little tricks littering your entire code base and turning it into a mess of technical debt.
Edit: Also, when a trick like this only really works on int types, doesn't make a significant dent in performance, and is often optimized better by a compiler, it's just a silly trick to use in general.
Awesome response, thanks for the detail - that makes sense. I tend to conflate idiomatic programming with cleverness sometimes. In Ruby (my primary language) there are tons of shortcuts that the community pushes as good practice, and many of these fall into the 'clever' bucket in my mind.
edit: for example, it's considered good practice to build arrays using
%w[some thing]
instead of the standard['what', 'ever']
structure. A minor example, but it highlights what I'm getting after.I can definitely see how it would be easy to confuse the two, yeah. If we want to define what being "clever" is more concretely (in the negative sense that we've been using), then I would define it as having two important characteristics:
A few common signs that you're (probably) trying to be clever:
Those signs aren't definitive, of course. Sometimes you have to work with less-maintainable solutions in order to make necessary performance gains. Knowing the difference between trying to be "clever" and just working around the limitations of the technology you're working with is a matter of experience.
As an aside, experienced Ruby programmers would probably hate me because I would be averse to using a construct like the one you mentioned for string array building. I recognize the use case and I fully understand the motivation, but it seems like something that would be too error-prone and difficult to understand for junior devs in particular. Throw in punctuation and it'll take some serious mental overhead to understand. (Also, I would actually argue that such an idiomatic construct is itself an example of its designer being "clever".)
I just started learning Rust a few days ago, and haven't had much time to dedicate due to work. To my understanding, the
match s.parse()
has to return a number value, correct? I don't understand why it doesn't compile if I do this instead:The match statement doesn't actually need to return anything, I don't think; you should be able to just do something like:
The reason it isn't compiling for you like that is because rustc doesn't know which version of
parse()
to use. It's a generic function that could return any type, so the compiler needs to either figure out from the context (you returning an integer) or by explicitly stating which version you want like so:match s.parse::<u32>() {
Having said that,
match
is an expression and it does return a value, so a common idiom is to make that work for you in situations like this (where you want to assign a variable based on some match).Now, I'm not convinced
String
parsing is strictly necessary here, and an informative exercise might be to try doing everything with&str
slices instead of (owned, allocating)String
s.Fantastic explanation, thank you. I didn’t realize parse() was a generic function, so the error messages I was getting make a lot more sense now.
Here's one I just made in JS. Output is to the console.
Now that is quite the one liner! Clever :)
Thanks! It could definitely be shortened, but I don't think the goal here was the shortest code haha
You can take it down a few characters by not initializing f, b or z:
for(var i=0,f,b,z;++i<101;f=i%3>1,b=i%5>3,z=f&&b){console.log(z?"FizzBuzz":f?"Fizz":b?"Buzz":i);}
Nice! I think I was testing this in a strict environment, so that would have never crossed my mind.
On modern browser you can write that in es6+ and use less characters (shorthands and functional programming approach).
On mobile right now or I'll write it down, sorry :(
What ES6 optimizations could be used in this situation? At least, for this version?
Hey! Nothing, my bad!
I was checking from mobile and basically could only see partials of the whole string and thought to have seen a "function(){}" somewhere in that line and of course you could have used the shorthand "val=>returned" in that case but I see now that it's quite perfect as it is :)
Thanks! I wasn't too sure there was anything to be changed, but my familiarity with the ES6 spec is still a bit rough in places, I thought I had missed something :)
How about using something super old? Don't google this and guess what it's written in.
Good lord is this COBOL in 2018?
At first I thought I was looking at an ancient Egyptian tablet, but on second glance I think you're right, it looks like it predates that.
I want to try out this program but my Antikythera mechanism is broken and I haven't gotten around to fixing it.
This has to be the most educational joke I've seen in a long time.
beautiful
I no longer have a COBOL interpreter, so I had to check online to make sure this actually worked.
You can run COBOL in a modern Windows/Linux environment... Someone at my work apparently had the idea that this counted as modernizing our infrastructure.
They then had the idea that modern anything was too much to hope for, so we're doing COBOL on Server 2008 R2, with a version of the COBOL interpreter that will be out of support by the time the project is ready to go into production.
The good news is that I had nothing to do with any of that. The bad news is that as soon as it goes into production, the initial blame is going to fall on me if something breaks and people don't get their paychecks. You better believe I've documented the hell out of my objections.
There's also this web framework for COBOL:
https://github.com/azac/cobol-on-wheelchair
(just because it feels like we're talking about ridiculous COBOL things)
Here's a C solution that abuses POSIX printf:
Can you explain this? I'm a C noob, so I'm getting hung up on what exactly you filled your array with and the hex(?) in the for loop.
Don't feel bad, this isn't exactly idiomatic C! I was intentionally trying to obfuscate how it works.
We need to support the following four behaviors: print a number, print "Fizz", print "Buzz", and print "FizzBuzz". The idea is to use a printf format string as a very limited kind of programming language for selecting what to print. The reason this works is due a somewhat obscure feature of POSIX printf. You can use the syntax
n$
in a format string to select the n-th argument. For example, you can use"%2$s"
to print the second argument as a string.The array
s
represents the format string. It starts with a newline (so everything isn't bunched up onto one line), and then specifies a string using"%n$s"
. The character"n"
iss[2]
—it's assigned a different character each time through the loop. More on that later. Next we have a"\0"
, which is a NULL byte. This terminates the C string, so the rest of the string isn't used by default. This NULL byte iss[5]
. Then we have"%1$d"
, which simply outputs the first argument as a number.Once you understand
s
, you can start to see what's going on. Our goal is to modifys
on each row like this:s = "\n%2$s\01%1$d"
s = "\n%2$s\01%1$d"
s = "\n%3$s\0%1$d"
s = "\n%2$s\01%1$d"
s = "\n%4$s\0%1$d"
On lines that we output a number, we set
s[2]
to '2' (or 50 in ASCII)—this makes the format specifier"%2$s"
, which prints the second argument, an empty string. On lines that we output "Fizz", we sets[2]
to '3' to get"%3$s"
—printing the third argument, "Fizz" (and so on withs[2]='4'
for "Buzz" ands[2]='5'
for "FizzBuzz").We use the NULL byte to hide the number on lines where we print "Fizz", "Buzz", or "FizzBuzz". The printf function stops reading the string when it encounters the NULL. On other lines, we set the byte to 1, which represents the "SOH" control character. The printf function will output this character, but the terminal should just ignore it (so you won't actually see it on screen).
Now, on to the hex number. 0x1241843 in base 4 is 01021001201003—decoding the base 4 digit tells us which string to output. The expression
0x1241843>>i%15*2&3
performs this base-4 decoding, giving us 0, 1, 2, or 3, depending on whether the number should be printed directly, or if we should output "Fizz", "Buzz", or "FizzBuzz".Since 50 is the ASCII code for '2', we can add that to the base 4 digit to get the proper value for
s[2]
. If the result is less than 51, the digit must have been 0, so we use that comparison result to write a 1 or a 0 intos[5]
.Edit: typos.
32-bit MIPS Assembly:
You just gave me flashbacks to my computer architecture class during my CS studies.
For some reason I have a habit of dragging out MIPS for these types of things.
Fizzbuzz in css using 3 nth-child selectors and pseudo-elements:
https://jsfiddle.net/wjbosrxv/
I like your approach, but using margin and pixel offsets to adjust the text doesn't look well or properly aligned. I would use
list-display: none
for allli
and CSS counters to generate the numbers to add to the:before
pseudo element, that way they will always be aligned with the text. Here's my improved version.Just for the hell of it, let's get rid of the hard-coded
li
tags and use a small piece of JS to add them in. While we're at it, we can bring that total up to 100 to better meet the requirements. Here's my update.Good idea, now it reaches 100 with little effort and the logic still remains in the CSS.
I never thought to use CSS for this. Neat solution! :)
Sorry for zombifying this thread but I was super proud of being able to do one of the challenges!
In Python.
ES6 Javascript. Can be executed in Chrome's dev tools console.
It does some stupid fuckery to read the parameter names of the
GO
function and extract the stringFizzBuzz
from in there. And I just obfuscate some array indices by using u=3 and zz=5 and various maths operations to get 0, 1, 2, 4, 23, and 100.I'm not a great programmer, but here I go with javascript:
Yes, that's much better. Thanks.
If I'm allowed to nitpick, I'd say that
c
andd
aren't great variable names. I'd also recommend usingfor n in range(amount)
instead ofwhile(c < amount)
.Given that the dictionary is a generalization made to easily change how the function works, passing it in as an argument would make sense.
Bad habits are the bane of every programmer's existence. Trust me when I say that it's far better to crush those bad habits now and build on good habits so that you save yourself massive headaches down the line.
For example, while it's generally fine to use bad naming for prototyping--or, at least, there's nothing necessarily wrong with it--if you do it in a professional setting then you may find that while you're in the middle of prototyping, your development priorities get changed on you. Then, when you get back to working on that piece of prototyped code from potentially more than a month ago, you'll have to figure out what that code does all over again because of the bad naming that was used.
Sorry, not the most creative way of doing it. In Perl 5:
I keep codegolfing in other examples, but I kind of like this for Perl:
Necroposting, since I'm late to the party:
JS can now be abused to the point of looking like if Perl and ML had a baby. Backticks and
${}
now act like clumsy brackets, the functional features (andlet
) are lovely, and some pointless esoterica can completely mislead people.Don't worry about necroposting. I don't remember which thread it was, but it was noted by @Deimos himself that we have the activity sort for a reason, and that's to encourage posting on older threads if we feel like it. Those who don't want to see a post as old as this one can set their activity sort to only show posts up to X age. So feel free to try out any of the other programming challenges if you feel like it!
As for your submission here, I'm not sure if I should be impressed or horrified! All I can say for sure is, if we're ever working on a team together, please show consideration for my sanity by never issuing a merge request with something like this in it.
That's cool with the activity sort.
I came up with the idea for the solution after reading a fizzbuzz thread on /g/ a while back, in which the code got more and more obfuscated with more obscure languages and features. I hadn't seen anyone in the thread manage a Regex solution, so I made one myself, and because that's too obvious on its own, I also completely mangled the syntax via custom template literals instead of normal function calls. Choosing something like Ook! would be too obviously incomprehensible, but writing incomprehensible code in one of the most widely comprehended languages? Now that is truly art!
I had just done this for my bootcamp. Here's mine in JavaScript (repl.it = https://repl.it/@nickfp1985/array-index-fizzbuzz )
for (i = 1; i < 100; i++) {
if (i % 3 === 0 && i % 5 === 0) {
console.log('fizzbizz');
} else if (i % 5 === 0) {
console.log('fizz');
} else if (i % 3 === 0) {
console.log('bizz');
} else {
console.log(i);
}
}
FYI, you can do this quicker if you don't use "else if" statements. Just 3 "if" statements will suffice:
if (i%3 === 0) FIZZ
if (i%5 === 0) BUZZ
if (i%3 !== 0 && i%5 !== 0) NUMBER
Any number divisible by both will hit for the first 2, in order and print FIZZBUZZ.
Good point. They could just output everything to a string with a += '\n' at the end of the "if" statements and then log the final.
Either way, it's possible with fewer conditions.
You'd change the
if-else
for conditional operator and put that inside oneconsole.log
Broken out to make it easier to read:
Also notice I don't use
=== 0
because 0 is type coerced to false.Just so you're aware, that operator--the use of
condition ? val_if_true : val_if_false
--is called a ternary operator :)Yes. But that's because it's the only operator that takes 3 operands. It is called the conditional operator on MDN.
Fuck, when did people start referring to it as the conditional operator? I've always heard it strictly called the ternary operator to avoid ambiguity with if statements.
In any case, I stand corrected!
if statement isn't an operator :p
And the word "literally" doesn't mean "figuratively", but somehow people have managed to confuse those to the point of the dictionary definition changing. Some people just don't think about the words they're using, and "conditional" is typically the word they pay attention to while ignoring the word "operator". Or, they'll hear "conditional operator" and think of logical operators.
The term "conditional operator" may have a strict definition, but it's just ambiguous enough that a lot of people are going to misunderstand what it means. The term "ternary operator", on the other hand, isn't really ambiguous, and while inexperienced devs (or just devs who have known it as the conditional operator from day one, even) may not know it by name at first, they won't easily mistake it for anything else when they hear it in conversation.
This is why I find the use of "conditional operator" so surprising. I mean, I get it from the perspective of the term being easier to use and remember, but ambiguity is a pain to deal with in programming.
Then again, language has always been a funky subject for me.
Pro tip: use three backtick characters `, the same key as the tilde character ~, to enclose your code and get it in that nice monospace style that you see elsewhere in the comments, e.g.:
Additionally, you can do inline preformatted text by enclosing the text with single backticks, e.g. to get text to look like
this
.Edit: Oh yeah, this also tends to work on some other platforms like Discord and Slack. On Discord, you can even add the name of your target programming language on the same line as the opening backticks to get syntax highlighting for that language!
SQL, tested with SQLite 3.24.0: