A year ago a similar challenge did the rounds on Twitter but just restricting the modulo operator (not division). My solution was essentially based around b = i * 8 / 5 & 7 and (i + 2) * 6 / 9 & 1 == 1: https://gist.github.com/peterc/2060adac0f9cf5fb9cf3
Writing a fizzbuzz without modulo or division operators (and if-statements for that matter) isn't terribly hard when you use the fact that the fizzbuzz pattern repeats every 15 items.
The main reason I wrote this was after seeing a comment on HN about unusual FizzBuzz solutions.
The f[0-4] and t[0-2] functions emulate the state of a deterministic finite automata which determine divisibility of binary strings. The bits represent the binary strings. The left shift operator is used to "eat" bits.
For those showing ways to do it with just addition and the like, I originally titled this "FizzBuzz using only bit twiddling" but a mod appears to have changed it...
Understood. Now that I think of it, I did the same thing until someone told me about the comma. Still though, the comma-trick puts spaces in between the numbers. I don't know how to get rid of that.
To check if a number is divisible by 3, you can sum the digits of your number. If the sum of the digits is divisible by 3, then so was the original number. (e.g. 5832 -> 5+8+3+2=18) Therefore, if you recursively sum the digits of your number until you get a single-digit number and that digit is 3, 6, or 9, then the original number was divisible by 3. (e.g. 5832 -> 18 -> 9 so 5832 is divisible by 3)
To check if a number is divisible by 5, just check if the last digit is 0 or 5.
I thought about this, but there isn't a super efficient way to extract the individual digits without modulus or division or casting to a string, unless I am missing something obvious.
I did FizzBuzz at an interview, years ago, using only addition and comparison. I mentioned, at the time, that years of 6502 assembler when I was a kid conditioned me to avoid multiplication and division whenever possible. My interviewers looked at me like I was crazy. Oh, well... >smile<
Very cool. This really makes me want to get better at Haskell. I know enough of it to understand what's going on here, but not enough to be able to come up with something like this.
Funny thing is, as soon as I saw OP's solution I fired up IPython to do the same thing in Python. :)
Admittedly mine was not as elegant as I haven't thought of using izip with 3 iterables. Still, I don't think that lambda and islice is really needed... xrange(100) guarantees a finite number of iterations already.
from itertools import *
fizzer = cycle(['Fizz','',''])
buzzer = cycle(['Buzz','','','',''])
fizzbuzzer = izip(xrange(100), fizzer, buzzer)
for f in fizzbuzzer:
print f[1] + f[2] if f[1] or f[2] else f[0]
EDIT:
the output from your version does not look right. "Fizz" and "Buzz" are on the wrong index positions.
0
1
fizz
3
buzz
fizz
6
7
fizz
buzz
...
The actual effort put in the article is reduced by this title. There are so many ways you can do this without using modulo and division. The article solved this using bit manipulation that is the main point.
.say for (('' xx 2, 'Fizz') xx * Z~ ('' xx 4, 'Buzz') xx *) Z|| 1 .. 100;
Yet another way, this time in Perl 6. It generates two infinite lists, one containing two empty strings and Fizz repeated forever. Second contains four empty strings and Buzz repeated forever. They are concatenated. Next, everything is zipped with `1..100` range using `||` operator. The `||` operator returns first argument if it's true, false otherwise. Because the range is finite, the list ends.
Another way to freak interviewers out is to calculate mod5 implement a nice circular linked list with 5 nodes, one node containing "Buzz" and the other four nodes containing null and call mod5(86) means you dance around the circular linked list 86 times and whatever string you stop on you output either Buzz 1/5 the time or null string/nothing 4/5 the time. This is hilarious if you run fizzbuzz from 0 to 100 but even funnier if you try 1000000 to 1000100
Also there's a pretty obvious conversion to recursion.
Either implementation can be even funnier if you memoize results in an array cache (so if you've already figured out the hard way that 999999mod3=0 then next time around when you check 1000000 you need not cycle all the way down to 0 for 1000000 because once you hit 999999 you already know from last time around how 999999 turned out. Bonus points for making your "cache" smaller, like implementing a LRU (or simpler) algorithm for the last several lookups rather than memoizing all one million results.
There's also a devilish way of (ab)using IEEE float arithmetic rounding errors which I forget at this moment.
If your language or a library attached to it handles arbitrary bases, there's a certain pattern to the last digit WRT multiples of 5 when expressing the number in base 5... so just to be a jerk you do the math for 3-mults in base 3, 5-mults in base 5, and your 0 to 100decimal counter in base 7 for the pure hell of it. OR amuse the interviewer because the base wasn't spec'd by running up to 100base7 (which is probably going to be a new ethernet standard soon enough).
Another fun form of rebellion is to implement an emulator for any machine language machine you can remember running simple BCD math. So here's a lame little Z80 emulator and a Z80 assembly routine to solve this using simple BCD math.
Deviant forms of trig obfuscation can be funny, essentially you rely on the trig libraries overflow behavior to dance 1/5 of the way around a unit circle each time, and when you're all done, if your angle is close enough to zero, I guess its divisible by 5. This is much funnier if you implement essentially a pentagon and then rotate it using quaternions
I think programmer brain puzzles are kind of dumb, when I was younger I would have just walked out of the room, but as I age the likelihood of a total smartass answer like above increases over time.
FizzBuzz is not a brain puzzle. It's a pass/fail weedout question. It's purpose is to determine if you are worth spending more time interviewing. If you don't know enough math to understand multiples or you don't know enough programming to write a "for" loop then that's the end of the interview. If you pass, you should then get the better and more relevant questions. Writing a Z80 emulator at that stage of the interview is a waste of time, and may itself constitute a fail depending on the interviewer.
Not entirely pointless, assuming you don't completely screw up FizzBuzz 2.0 or whatever you want to call it, the next question was probably going to be along the lines of "tell me about a problem using recursion other than boring old factorial" or "can you do much of anything with an array" or "show me a data structure more interesting than Int X, like, say, a linked list?" or "Tell me about your time in the 3-d graphics rendering world" or "tell me about memoization and/or caching strategies" or "tell me how to use a library and its API in language XYZ where it could be an arbitrary numerical base library".
(edited to add a hilarious one: Using a unit testing framework only permit proper fizzbuzz, then feed with with 10e3 monkeys on typewriters trying to generate Shakespeare technology and trust the testing framework...)
I suppose for a low level CRUD app job knowing what modular math is and how to run a loop, aka fizzbuzz, is probably massive skill overkill but there are higher level jobs out there...
I'm racking my brain right now trying to think of a "funny" way to do fizzbuzz for a high freq trading interview as in another story on HN today. So to test mod3 you'd submit a buy order followed by two half sized sell orders repetitively all in a couple milliseconds and let the market maker routine clear the market, and orders left over, if any, would tell you if you submitted a multiple of 3 orders so you could print "fizz"?
I don't think FizzBuzz leads into interesting interview questions. That would be too dependent on the hope that the candidate does implement an overkill solution for fizzbuzz. Much more interesting questions can be derived from the problems the company is actually working on.
FizzBuzz is a simple "can you code at all" filter. If you write the obvious solution, you move on to the actual interview. If you write an elegant and amusing solution, you move on to the actual interview.
Surprisingly most applicants for programming positions cannot write any code that uses a for loop or an if statement at all, and fizzbuzz is a 3-minute test to prevent everyone from wasting their time.
Use a macro to generate the fully unrolled loop with only addition and iteration. Claim efficiency under conditions of branch prediction and speculative execution on IA64.
fizzBuzz x = if null str then show x else str
where str = concat [tag | (n,tag) <- tags, x `rem` n == 0]
tags = [(3,"Fizz"), (5,"Buzz")]
main = mapM_ (putStrLn . fizzBuzz) [1..100]
This is perhaps the most elaborate "fuck you" to asnine interview questions. Fizzbuzz was a great acid test but now a days people who can't solve `a = 1+2; a == ?` know fizzbuz somehow.
70 comments
[ 4.1 ms ] story [ 140 ms ] threadhttp://stackoverflow.com/questions/5284898/implement-divisio...
See:
http://stackoverflow.com/questions/15330027/regular-expressi...
http://ugccomputerscience.blogspot.com/2012/02/dfa-of-binary...
https://gist.github.com/ginkgo/7201708
https://news.ycombinator.com/item?id=1383978
The f[0-4] and t[0-2] functions emulate the state of a deterministic finite automata which determine divisibility of binary strings. The bits represent the binary strings. The left shift operator is used to "eat" bits.
See these two DFAs for an explanation:
http://stackoverflow.com/questions/15330027/regular-expressi...
http://ugccomputerscience.blogspot.com/2012/02/dfa-of-binary...
EDIT:
For those showing ways to do it with just addition and the like, I originally titled this "FizzBuzz using only bit twiddling" but a mod appears to have changed it...
[1] - https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
Any reason for not just using print? Or if you want all of them on the same line, you can put a comma at the end of print, like...
To check if a number is divisible by 5, just check if the last digit is 0 or 5.
So :
Also, 5 works "like 3" in hexadecimal:Poetry.
In python:
(bugs found by marekmroz fixed)Can you do [1,2,3] * 4 in haskell as well ?
Admittedly mine was not as elegant as I haven't thought of using izip with 3 iterables. Still, I don't think that lambda and islice is really needed... xrange(100) guarantees a finite number of iterations already.
EDIT: the output from your version does not look right. "Fizz" and "Buzz" are on the wrong index positions. 0 1 fizz 3 buzz fizz 6 7 fizz buzz ...You're also correct islice is not needed.
python -c 'print "\n".join(w or str(i+1) for i, w in enumerate(("..Fizz..Buzz.Fizz...Fizz.Buzz..Fizz...FizzBuzz."*7).split(".")[:100]))'
If you actually want to do the math, you can make your python shorter: http://stackoverflow.com/a/6890045
https://gist.github.com/tomtheisen/7203110
Functional programming for the win.
Also there's a pretty obvious conversion to recursion.
Either implementation can be even funnier if you memoize results in an array cache (so if you've already figured out the hard way that 999999mod3=0 then next time around when you check 1000000 you need not cycle all the way down to 0 for 1000000 because once you hit 999999 you already know from last time around how 999999 turned out. Bonus points for making your "cache" smaller, like implementing a LRU (or simpler) algorithm for the last several lookups rather than memoizing all one million results.
There's also a devilish way of (ab)using IEEE float arithmetic rounding errors which I forget at this moment.
If your language or a library attached to it handles arbitrary bases, there's a certain pattern to the last digit WRT multiples of 5 when expressing the number in base 5... so just to be a jerk you do the math for 3-mults in base 3, 5-mults in base 5, and your 0 to 100decimal counter in base 7 for the pure hell of it. OR amuse the interviewer because the base wasn't spec'd by running up to 100base7 (which is probably going to be a new ethernet standard soon enough).
Another fun form of rebellion is to implement an emulator for any machine language machine you can remember running simple BCD math. So here's a lame little Z80 emulator and a Z80 assembly routine to solve this using simple BCD math.
Deviant forms of trig obfuscation can be funny, essentially you rely on the trig libraries overflow behavior to dance 1/5 of the way around a unit circle each time, and when you're all done, if your angle is close enough to zero, I guess its divisible by 5. This is much funnier if you implement essentially a pentagon and then rotate it using quaternions
I think programmer brain puzzles are kind of dumb, when I was younger I would have just walked out of the room, but as I age the likelihood of a total smartass answer like above increases over time.
(edited to add a hilarious one: Using a unit testing framework only permit proper fizzbuzz, then feed with with 10e3 monkeys on typewriters trying to generate Shakespeare technology and trust the testing framework...)
I suppose for a low level CRUD app job knowing what modular math is and how to run a loop, aka fizzbuzz, is probably massive skill overkill but there are higher level jobs out there...
I'm racking my brain right now trying to think of a "funny" way to do fizzbuzz for a high freq trading interview as in another story on HN today. So to test mod3 you'd submit a buy order followed by two half sized sell orders repetitively all in a couple milliseconds and let the market maker routine clear the market, and orders left over, if any, would tell you if you submitted a multiple of 3 orders so you could print "fizz"?
FizzBuzz is a simple "can you code at all" filter. If you write the obvious solution, you move on to the actual interview. If you write an elegant and amusing solution, you move on to the actual interview.
Surprisingly most applicants for programming positions cannot write any code that uses a for loop or an if statement at all, and fizzbuzz is a 3-minute test to prevent everyone from wasting their time.
http://pastebin.com/3rUk6yS1
https://gist.github.com/euank/7206859
Also, I don't think I could write a z80 emulator on a whiteboard ;)
[1] https://github.com/KnightSoft/KnightOS