Smalltalk snippet of the day: Fizz Buzz
The spec. is: print the numbers from 1 to 100, except where a number is divisible by 5, print “Fizz”, and where divisible by 7, print “Buzz”. Where divisible by both, print “Fizz Buzz”.
1 to: 100 do:
[ :i | | fb |
fb := (#((5 'Fizz') (7 'Buzz'))
select: [ :each | i \\ each first = 0 ])
collect: [ :each | each second ].
Transcript
<< (fb isEmpty
ifTrue: [ i ]
ifFalse: [ fb fold: [ :a :b | a, ' ', b ] ]) ;
nl. ].
Nested ifTrue:ifFalse:, or and: / or: might do the job in fewer lines, but would be more cryptic. Note that this version splits out the ’spec’ part into an array, so you could add (11 ‘Bazz’). Nevertheless, I feel that there could be a better version…
This came up in the context of an article which said that 199 out of 200 job applicants couldn’t code it correctly. Many people expressed disbelief, claiming that it is an easy problem. The thing is, it’s not that easy. Sure, you can write a version that works, but getting it exactly right first time is hard. I didn’t: I didn’t suppress the numbers when it was Fizz (or Buzz); I only printed one of Fizz / Buzz, when both matched, and so on.
I suppose my mistake was not to write tests in advance of coding (because it was a simple problem - duh). Next time, I will try that.