FizzBuzz Fun

Objective: Create a program that counts from 1 to 100.
The Trick: For any number divisible by 3 replace it with “Fizz”, any number by 5 with “Buzz” and any by 3 and 5 with “FizzBuzz”.

Lets see everyones approach. Imaginary points to the winners of the following categories: Speed, Length, Strangeness.

So to start it here is mine…

set fbString to ""
repeat with i from 1 to 1000
	set fbString to fbString & fizzBuzz(i) & " "
end repeat
on fizzBuzz(i)
	if (i mod 3) = 0 then
		if (i mod 5) = 0 then
			return "FizzBuzz"
		else
			return "Fizz"
		end if
	else
		if (i mod 5) is 0 then
			return "Buzz"
		else
			return i
		end if
	end if
end fizzBuzz

Well, James, I couldn’t resist. Here’s a 5-liner (really 6):


set fbString to ""
repeat with i from 1 to 1000
	set {mod3, mod5} to {0 ^ (i mod 3), 2 * (0 ^ (i mod 5))}
	set fbString to (fbString & (items (1 + mod3 + mod5 - mod3 * mod5) thru (1 + mod3 + mod5 - mod3 * mod5 / 2) of {i, "Fizz", "Buzz"}) as string) & " "
end repeat

bmose

Offhand, I would probably do something like bmose (getting items from a list of strings).

Edit: 100 or 1000?

Edit: This works for 100:

do shell script "/usr/bin/jot 100 1 100 | /usr/bin/ruby -e '
$stdin.readlines.each {|line| 
print line.
gsub(/^15|^30|^45|^60|^75|^90/, \"FizzBuzz\").
gsub(/.*[0|5]$/, \"Buzz\").
gsub(/^3$|^6$|^9$|^[369][369]|^[258][147]|^[147][258]/, \"Fizz\").
gsub(/\\n/, \" \")
}'"

Or in 4 lines:


set fbString to ""
repeat with i from 1 to 1000
	set fbString to (fbString & (items (1 + 0 ^ (i mod 3) + 2 * (0 ^ (i mod 5)) * (1 - (0 ^ (i mod 3)))) thru (1 + 0 ^ (i mod 3) + (0 ^ (i mod 5)) * (2 - (0 ^ (i mod 3)))) of {i, "Fizz", "Buzz"}) as string) & " "
end repeat

I love you people…

ruby and of course bmose’s usuall stuff that makes me go Oook

Oh no, I just felt like timing these. :o Darn you, James. :wink: Thankfully, GetMilliSec doesn’t work on my machine.

Just saving a few characters:

set fbString to ""
repeat with i from 1 to 1000
	tell (0 ^ (i mod 3)) to set fbString to fbString & (items (1 + it + 2 * (0 ^ (i mod 5)) * (1 - it)) thru (1 + it + (0 ^ (i mod 5)) * (2 - it)) of {i, "Fizz", "Buzz"}) & " "
end repeat

set fbString to ""
repeat with i from 1 to 1000
	tell {modThree:(0 ^ (i mod 3)), modFive:(0 ^ (i mod 5))} to set fbString to fbString & items (1 + (it's modThree) + 2 * (it's modFive) * (1 - (it's modThree))) thru (1 + (it's modThree) + (it's modFive) * (2 - (it's modThree))) of {i, "Fizz", "Buzz"} & " "
end repeat

Using the Extra Suites ES milliseconds command, I timed five of the variations and increased the final string size from 1000 to 5000 to bring out differences better. The following are the execution times (PowerBook G4, average of 5 runs each to adjust for inherent fluctuations):

James’s original script:
2.79 seconds – > the speed winner!

Bruce’s tell (0 ^ (i mod 3)):
2.93 seconds

bmose’s 6-liner:
3.02 seconds

Bruce’s tell {modThree:(0 ^ (i mod 3)), modFive:(0 ^ (i mod 5))}:
3.12 seconds → my favorite for elegance

bmose’s 4-liner:
3.19 seconds → my favorite for pure weirdness

(Oops, sorry James, you have the final say in the judging contest!)

bmose