F*cking with FizzBuzz
Scott Windsor
@swindsor
Wednesday, July 3, 13
about me
2001-2007 amazon.com
2007-2007 BillMonk/Obopay
2007-2012 TeachStreet
2012-? amazon local
Wednesday, July 3, 13
I interview a lot.
Wednesday, July 3, 13
FizzBuzz
Wednesday, July 3, 13
FizzBuzz
Print numbers 1-100.
Wednesday, July 3, 13
FizzBuzz
Print numbers 1-100.
For multiples of 3, print “Fizz”.
Wednesday, July 3, 13
FizzBuzz
Print numbers 1-100.
For multiples of 3, print “Fizz”.
For multiples of 5, print “Buzz”.
Wednesday, July 3, 13
FizzBuzz
Print numbers 1-100.
For multiples of 3, print “Fizz”.
For multiples of 5, print “Buzz”.
For multiples of 3 and 5, print “FizzBuzz”.
Wednesday, July 3, 13
fizzbuzz.rb
1.upto(100) do |i|
if i % 15 == 0
puts "FizzBuzz"
elsif i % 3 == 0
puts "Fizz"
elsif i % 5 == 0
puts "Buzz"
else
puts i
end
end
Wednesday, July 3, 13
Wednesday, July 3, 13
Not good for interviews
Wednesday, July 3, 13
Not good for interviews
∅ data structures
Wednesday, July 3, 13
Not good for interviews
∅ data structures
∅ algorithms
Wednesday, July 3, 13
Not good for interviews
∅ data structures
∅ algorithms
∅ problem solving
Wednesday, July 3, 13
Not good for interviews
∅ data structures
∅ algorithms
∅ problem solving
~ coding
Wednesday, July 3, 13
Not good for interviews
∅ data structures
∅ algorithms
∅ problem solving
~ coding
Wednesday, July 3, 13
How can we make this
more fun?
Wednesday, July 3, 13
Fun with DSLs
class FizzBuzz < Bazinator
default_rule ->(i){ i }
rule ->(i){"Fizz" if i % 3 == 0 }
rule ->(i){"Buzz" if i % 5 == 0 }
end
FizzBuzz.new(1..100).print
Wednesday, July 3, 13
Wednesday, July 3, 13
ActiveRecord-style
class Bazinator
attr_accessor :range
def initialize(range)
@range = range
end
def rules
@@rules
end
def default_rule
@@default_rule
end
def self.default_rule(rule)
@@default_rule = rule
end
def self.rule(rule)
@@rules ||= []
@@rules << rule
end
...
Wednesday, July 3, 13
ActiveRecord-style
...
def run_rules(i)
results = rules.map{|rule| rule.call(i) }
results.delete_if(&:nil?)
results << default_rule.call(i) if results.empty?
results
end
def each(&block)
range.each do |i|
yield run_rules(i).join('')
end
end
def print
each do |item|
puts item
end
end
end
Wednesday, July 3, 13
I can haz DSL.
class FizzBuzz < Bazinator
default_rule ->(i){ i }
rule ->(i){"Fizz" if i % 3 == 0 }
rule ->(i){"Buzz" if i % 5 == 0 }
end
FizzBuzz.new(1..100).print
Wednesday, July 3, 13
What about other
languages?
Wednesday, July 3, 13
Let’s try some C
#include <stdio.h>
#include <string.h>
const char* fizz(int i) {
if((i % 3) == 0) {
return "Fizz";
}
else {
return "";
}
}
const char* buzz(int i) {
if((i % 5) == 0) {
return "Buzz";
}
else {
return "";
}
}
Wednesday, July 3, 13
Function Pointers++
Wednesday, July 3, 13
Function Pointers++#define MAX_BUFF 10
#define NUMBER_FUNCTIONS 2
const char* (*dispatch[NUMBER_FUNCTIONS])(int i) = {fizz,buzz};
void itoa(int i, char* a) {
snprintf(a, sizeof(a), "%i", i);
}
void clear(char* s) {
strncpy(s, "", sizeof(s));
}
void run_functions(int i, char* result) {
int f;
for(f=0; f < NUMBER_FUNCTIONS; f++) {
strlcat(result,(*dispatch[f])(i),sizeof(result));
}
}
void add_number(int i, char* result) {
char number[MAX_BUFF];
if(strnlen(result,sizeof(result)) < 1) {
itoa(i,number);
strlcat(result,number,sizeof(result));
}
}
Wednesday, July 3, 13
Somewhere, Knuth is
crying.
int main(){
char result[MAX_BUFF];
int i;
for(i=1; i < 100; i++) {
clear(result);
run_functions(i, result);
add_number(i, result);
printf("%sn", result);
}
return 0;
}
Wednesday, July 3, 13
But wait, Java is missing
out.
package com.sentientmonkey.fizzbuzz;
import com.sentientmonkey.fizzbuzz.service.FizzBuzzService;
public class Runner {
public static void main(String[] args) {
FizzBuzzService fizzBuzz = new FizzBuzzService();
fizzBuzz.print(1, 100);
}
}
Wednesday, July 3, 13
Best thing is the
patterns.
Wednesday, July 3, 13
First you get the Service
Facade.
package com.sentientmonkey.fizzbuzz.service;
import com.sentientmonkey.fizzbuzz.rules.*;
public class FizzBuzzService {
RuleManager ruleManager;
public FizzBuzzService() {
ruleManager = new RuleManager();
ruleManager.addRule(new FizzRule());
ruleManager.addRule(new BuzzRule());
ruleManager.addRule(new DefaultRule());
}
public void print(int start, int end) {
for (int i = start; i <= end; i++) {
System.out.println(ruleManager.evaluateRules(i));
}
}
}
Wednesday, July 3, 13
Then you get the
Manager.
package com.sentientmonkey.fizzbuzz.rules;
import java.util.ArrayList;
public class RuleManager {
ArrayList<Rule> rules;
public RuleManager() {
rules = new ArrayList<Rule>();
}
public void addRule(Rule rule) {
rules.add(rule);
}
public String evaluateRules(int number) {
StringBuilder builder = new StringBuilder();
for (Rule rule : rules) {
rule.withBuilder(builder).append(number);
}
return builder.toString();
}
}
Wednesday, July 3, 13
Now you get a Builder.
package com.sentientmonkey.fizzbuzz.rules;
public abstract class Rule {
StringBuilder builder = null;
public Rule withBuilder(StringBuilder builder) {
this.builder = builder;
return this;
}
public abstract void append(int number);
}
Wednesday, July 3, 13
Default Rule.
package com.sentientmonkey.fizzbuzz.rules;
public class DefaultRule extends Rule {
@Override
public void append(int number) {
if (builder.length() == 0) {
builder.append(number);
}
}
}
Wednesday, July 3, 13
Fizz Rule.
package com.sentientmonkey.fizzbuzz.rules;
public class FizzRule extends Rule {
@Override
public void append(int number) {
if ((number % 3) == 0) {
builder.append("Fizz");
}
}
}
Wednesday, July 3, 13
Buzz Rule.
package com.sentientmonkey.fizzbuzz.rules;
public class BuzzRule extends Rule {
@Override
public void append(int number) {
if ((number % 5) == 0) {
builder.append("Buzz");
}
}
}
Wednesday, July 3, 13
le java.
package com.sentientmonkey.fizzbuzz;
import com.sentientmonkey.fizzbuzz.service.FizzBuzzService;
public class Runner {
public static void main(String[] args) {
FizzBuzzService fizzBuzz = new FizzBuzzService();
fizzBuzz.print(1, 100);
}
}
Wednesday, July 3, 13
Don’t forget clojure.
(defn fizz [i]
(if(= (mod i 3) 0)
"Fizz"))
(defn buzz [i]
(if(= (mod i 5) 0)
"Buzz"))
(defn join [a b]
(str a b))
(defn run-rules [numbers]
(map join (map fizz numbers) (map buzz numbers)))
(defn number [s n]
(if (= s "")
n
s))
Wednesday, July 3, 13
Something clever about
McCarthy.
(defn fizzbuzz [start end]
(let
[numbers (range start end)]
(doall
(map println
(map number
(run-rules numbers) numbers)))))
(fizzbuzz 1 100)
Wednesday, July 3, 13
or javascript
function fizz(i) {
if((i % 3) == 0){
return "Fizz";
}
}
function buzz(i) {
if((i % 5) == 0){
return "Buzz";
}
}
var rules = [fizz,buzz];
Wednesday, July 3, 13
or javascript.
function default_rule(result,i){
if(result.length > 0) {
return result;
} else {
return i;
}
}
function fizz_buzz(start,end) {
for(var i=start; i<=end; i++) {
var result = rules.map(function(rule){
return rule(i);
}).join('');
print(default_rule(result,i));
}
};
fizz_buzz(1,100);
Wednesday, July 3, 13
So what did we learn?
• Interviewees: Even fizzbuzz can be fun
• Interviewers:Ask better interview questions
• Everyone: Coding is still hard
Wednesday, July 3, 13
Thanks!
Play along at home:
http://github.com/sentientmonkey/fizzbuzz
Questions?
@swindsor
P.S. we’re hiring
Wednesday, July 3, 13

F*cking with fizz buzz

  • 1.
    F*cking with FizzBuzz ScottWindsor @swindsor Wednesday, July 3, 13
  • 2.
    about me 2001-2007 amazon.com 2007-2007BillMonk/Obopay 2007-2012 TeachStreet 2012-? amazon local Wednesday, July 3, 13
  • 3.
    I interview alot. Wednesday, July 3, 13
  • 4.
  • 5.
  • 6.
    FizzBuzz Print numbers 1-100. Formultiples of 3, print “Fizz”. Wednesday, July 3, 13
  • 7.
    FizzBuzz Print numbers 1-100. Formultiples of 3, print “Fizz”. For multiples of 5, print “Buzz”. Wednesday, July 3, 13
  • 8.
    FizzBuzz Print numbers 1-100. Formultiples of 3, print “Fizz”. For multiples of 5, print “Buzz”. For multiples of 3 and 5, print “FizzBuzz”. Wednesday, July 3, 13
  • 9.
    fizzbuzz.rb 1.upto(100) do |i| ifi % 15 == 0 puts "FizzBuzz" elsif i % 3 == 0 puts "Fizz" elsif i % 5 == 0 puts "Buzz" else puts i end end Wednesday, July 3, 13
  • 10.
  • 11.
    Not good forinterviews Wednesday, July 3, 13
  • 12.
    Not good forinterviews ∅ data structures Wednesday, July 3, 13
  • 13.
    Not good forinterviews ∅ data structures ∅ algorithms Wednesday, July 3, 13
  • 14.
    Not good forinterviews ∅ data structures ∅ algorithms ∅ problem solving Wednesday, July 3, 13
  • 15.
    Not good forinterviews ∅ data structures ∅ algorithms ∅ problem solving ~ coding Wednesday, July 3, 13
  • 16.
    Not good forinterviews ∅ data structures ∅ algorithms ∅ problem solving ~ coding Wednesday, July 3, 13
  • 17.
    How can wemake this more fun? Wednesday, July 3, 13
  • 18.
    Fun with DSLs classFizzBuzz < Bazinator default_rule ->(i){ i } rule ->(i){"Fizz" if i % 3 == 0 } rule ->(i){"Buzz" if i % 5 == 0 } end FizzBuzz.new(1..100).print Wednesday, July 3, 13
  • 19.
  • 20.
    ActiveRecord-style class Bazinator attr_accessor :range definitialize(range) @range = range end def rules @@rules end def default_rule @@default_rule end def self.default_rule(rule) @@default_rule = rule end def self.rule(rule) @@rules ||= [] @@rules << rule end ... Wednesday, July 3, 13
  • 21.
    ActiveRecord-style ... def run_rules(i) results =rules.map{|rule| rule.call(i) } results.delete_if(&:nil?) results << default_rule.call(i) if results.empty? results end def each(&block) range.each do |i| yield run_rules(i).join('') end end def print each do |item| puts item end end end Wednesday, July 3, 13
  • 22.
    I can hazDSL. class FizzBuzz < Bazinator default_rule ->(i){ i } rule ->(i){"Fizz" if i % 3 == 0 } rule ->(i){"Buzz" if i % 5 == 0 } end FizzBuzz.new(1..100).print Wednesday, July 3, 13
  • 23.
  • 24.
    Let’s try someC #include <stdio.h> #include <string.h> const char* fizz(int i) { if((i % 3) == 0) { return "Fizz"; } else { return ""; } } const char* buzz(int i) { if((i % 5) == 0) { return "Buzz"; } else { return ""; } } Wednesday, July 3, 13
  • 25.
  • 26.
    Function Pointers++#define MAX_BUFF10 #define NUMBER_FUNCTIONS 2 const char* (*dispatch[NUMBER_FUNCTIONS])(int i) = {fizz,buzz}; void itoa(int i, char* a) { snprintf(a, sizeof(a), "%i", i); } void clear(char* s) { strncpy(s, "", sizeof(s)); } void run_functions(int i, char* result) { int f; for(f=0; f < NUMBER_FUNCTIONS; f++) { strlcat(result,(*dispatch[f])(i),sizeof(result)); } } void add_number(int i, char* result) { char number[MAX_BUFF]; if(strnlen(result,sizeof(result)) < 1) { itoa(i,number); strlcat(result,number,sizeof(result)); } } Wednesday, July 3, 13
  • 27.
    Somewhere, Knuth is crying. intmain(){ char result[MAX_BUFF]; int i; for(i=1; i < 100; i++) { clear(result); run_functions(i, result); add_number(i, result); printf("%sn", result); } return 0; } Wednesday, July 3, 13
  • 28.
    But wait, Javais missing out. package com.sentientmonkey.fizzbuzz; import com.sentientmonkey.fizzbuzz.service.FizzBuzzService; public class Runner { public static void main(String[] args) { FizzBuzzService fizzBuzz = new FizzBuzzService(); fizzBuzz.print(1, 100); } } Wednesday, July 3, 13
  • 29.
    Best thing isthe patterns. Wednesday, July 3, 13
  • 30.
    First you getthe Service Facade. package com.sentientmonkey.fizzbuzz.service; import com.sentientmonkey.fizzbuzz.rules.*; public class FizzBuzzService { RuleManager ruleManager; public FizzBuzzService() { ruleManager = new RuleManager(); ruleManager.addRule(new FizzRule()); ruleManager.addRule(new BuzzRule()); ruleManager.addRule(new DefaultRule()); } public void print(int start, int end) { for (int i = start; i <= end; i++) { System.out.println(ruleManager.evaluateRules(i)); } } } Wednesday, July 3, 13
  • 31.
    Then you getthe Manager. package com.sentientmonkey.fizzbuzz.rules; import java.util.ArrayList; public class RuleManager { ArrayList<Rule> rules; public RuleManager() { rules = new ArrayList<Rule>(); } public void addRule(Rule rule) { rules.add(rule); } public String evaluateRules(int number) { StringBuilder builder = new StringBuilder(); for (Rule rule : rules) { rule.withBuilder(builder).append(number); } return builder.toString(); } } Wednesday, July 3, 13
  • 32.
    Now you geta Builder. package com.sentientmonkey.fizzbuzz.rules; public abstract class Rule { StringBuilder builder = null; public Rule withBuilder(StringBuilder builder) { this.builder = builder; return this; } public abstract void append(int number); } Wednesday, July 3, 13
  • 33.
    Default Rule. package com.sentientmonkey.fizzbuzz.rules; publicclass DefaultRule extends Rule { @Override public void append(int number) { if (builder.length() == 0) { builder.append(number); } } } Wednesday, July 3, 13
  • 34.
    Fizz Rule. package com.sentientmonkey.fizzbuzz.rules; publicclass FizzRule extends Rule { @Override public void append(int number) { if ((number % 3) == 0) { builder.append("Fizz"); } } } Wednesday, July 3, 13
  • 35.
    Buzz Rule. package com.sentientmonkey.fizzbuzz.rules; publicclass BuzzRule extends Rule { @Override public void append(int number) { if ((number % 5) == 0) { builder.append("Buzz"); } } } Wednesday, July 3, 13
  • 36.
    le java. package com.sentientmonkey.fizzbuzz; importcom.sentientmonkey.fizzbuzz.service.FizzBuzzService; public class Runner { public static void main(String[] args) { FizzBuzzService fizzBuzz = new FizzBuzzService(); fizzBuzz.print(1, 100); } } Wednesday, July 3, 13
  • 37.
    Don’t forget clojure. (defnfizz [i] (if(= (mod i 3) 0) "Fizz")) (defn buzz [i] (if(= (mod i 5) 0) "Buzz")) (defn join [a b] (str a b)) (defn run-rules [numbers] (map join (map fizz numbers) (map buzz numbers))) (defn number [s n] (if (= s "") n s)) Wednesday, July 3, 13
  • 38.
    Something clever about McCarthy. (defnfizzbuzz [start end] (let [numbers (range start end)] (doall (map println (map number (run-rules numbers) numbers))))) (fizzbuzz 1 100) Wednesday, July 3, 13
  • 39.
    or javascript function fizz(i){ if((i % 3) == 0){ return "Fizz"; } } function buzz(i) { if((i % 5) == 0){ return "Buzz"; } } var rules = [fizz,buzz]; Wednesday, July 3, 13
  • 40.
    or javascript. function default_rule(result,i){ if(result.length> 0) { return result; } else { return i; } } function fizz_buzz(start,end) { for(var i=start; i<=end; i++) { var result = rules.map(function(rule){ return rule(i); }).join(''); print(default_rule(result,i)); } }; fizz_buzz(1,100); Wednesday, July 3, 13
  • 41.
    So what didwe learn? • Interviewees: Even fizzbuzz can be fun • Interviewers:Ask better interview questions • Everyone: Coding is still hard Wednesday, July 3, 13
  • 42.
    Thanks! Play along athome: http://github.com/sentientmonkey/fizzbuzz Questions? @swindsor P.S. we’re hiring Wednesday, July 3, 13