top | item 18794214

FizzBuzz in ten languages

115 points| pplonski86 | 7 years ago |iolivia.me | reply

91 comments

order
[+] dbrgn|7 years ago|reply
Crossposting my comment from the blog:

The Rust example looks a bit strange, since you're matching on a variable, but don't actually use it.

Instead, you could write the match like this:

    let div_by_three = x % 3 == 0;
    let div_by_five = x % 5 == 0;
    
    match (div_by_three, div_by_five) {
        (true, true) => println!("FizzBuzz"),
        (true, false) => println!("Fizz"),
        (false, true) => println!("Buzz"),
        _ => println!("{}", x),
    }
...or even like this:

    match (x % 3, x % 5) {
        (0, 0) => println!("FizzBuzz"),
        (0, _) => println!("Fizz"),
        (_, 0) => println!("Buzz"),
        _ => println!("{}", x),
    }
Furthermore, inclusive ranges can be written like this:

    for x in 1..=100 {
[+] thanatos_dem|7 years ago|reply
Unless I’m missing something, your second example seems to be the one in the article.

Did the author change it?

Edit: just saw the comments on the article. Yes, she did.

[+] malloryerik|7 years ago|reply
That looks so much like Elixir.

    for x <- 1..100 do
      case [rem(x, 3), rem(x, 5)] do
        [0, 0] -> IO.puts("FizzBuzz")
        [0, _] -> IO.puts("Fizz")
        [_, 0] -> IO.puts("Buzz")
        _ -> x
      end
    end
[+] geraldbauer|7 years ago|reply
Fast. Faster. Fastest. The FizzBuzz Gold Standard. Lookup pre-calculated ("hard coded") constants. Don't over-engineer :-):

    def fizzbuzz
       [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14,
  "FizzBuzz", 16, 17, "Fizz", 19, "Buzz", "Fizz", 22, 23, "Fizz", "Buzz", 26,
  "Fizz", 28, 29, "FizzBuzz", 31, 32, "Fizz", 34, "Buzz", "Fizz", 37, 38,
  "Fizz", "Buzz", 41, "Fizz", 43, 44, "FizzBuzz", 46, 47, "Fizz", 49, "Buzz",
  "Fizz", 52, 53, "Fizz", "Buzz", 56, "Fizz", 58, 59, "FizzBuzz", 61, 62,
  "Fizz", 64, "Buzz", "Fizz", 67, 68, "Fizz", "Buzz", 71, "Fizz", 73, 74,
  "FizzBuzz", 76, 77, "Fizz", 79, "Buzz", "Fizz", 82, 83, "Fizz", "Buzz", 86,
  "Fizz", 88, 89, "FizzBuzz", 91, 92, "Fizz", 94, "Buzz", "Fizz", 97, 98,
  "Fizz", "Buzz"]
    end
Source: https://yukimotopress.github.io/fizzbuzz#gold-standard
[+] Someone|7 years ago|reply
Fastest? We need benchmarks to show that. I can see this being slower than traditional approaches on systems with slow memory, tiny CPU caches, and compilers that don’t do constant string folding.

You can also replace the array by a single string. That may or may not be faster, depending on CPU and language implementation. I think it likely is (rationale: the code writing the array to stdout either does multiple write calls, or builds up the string in memory and then does what the code writing the string does. The code writing the array need not load the string, but it needs to store the array, and that won’t be much smaller, even when it shares strings)

[+] bjoli|7 years ago|reply
In racket I would probably use a wheel for a more general solution:

    (define wheel '(#f #f "fizz" #f "buzz" "fizz" #f #f "fizz" "buzz" #f "fizz" #f #f "fizzbuzz"))

    (for ((fb? (in-cycle wheel)) (i (in-range 1 101)))
      (displayln (or fb? i)))

It would be more elegant in a lazy language, but it is probably quite fast since it doesn't need any division (?? My assumption here might be wrong). I typed this out on my phone, so it might not work, and racket isn't my daily driver.

Edit: My initial assumption was correct, but the in-cycle sequence creator has a very large overhead. The final solution for racket (Ugly, because mlist doesn't have any nice things included): https://pastebin.com/aB2BLY1U

The mutable list solution (as one would write it in scheme) is more than twice as fast as the remainder one, and I expect it to be for other languages as well.

[+] a3n|7 years ago|reply
Plus a program to produce the pre-calculated data, to avoid typos. :-)
[+] andrewstellman|7 years ago|reply
I've been looking for an example that shows how pattern matching can make code much both compact and readable. I think this does nicely. Here's an example in Scala:

  (1 to 100).map(i => (i % 3, i % 5) match {
    case (0, 0) => "FizzBuzz"
    case (0, _) => "Fizz"
    case (_, 0) => "Buzz"
    case _ => s"$i"
  }).foreach(println)
Compare that to the rest of the examples on the page. The only one that comes close in either readability or compactness (in my opinion) is the Rust example, mainly because it's syntactically almost identical, just a bit more verbose. I'm really excited that C# 8 will support similar syntax with _ discards.
[+] war1025|7 years ago|reply
Maybe I'm missing something, but how is that any more readable than:

  for val in xrange(1, 100):
    if val % 15 == 0:
      print "FizzBuzz"
    elif val % 5 == 0:
      print "Buzz"
    elif val % 3 == 0:
      print "Fizz"
    else:
      print val
[+] chucky|7 years ago|reply
The Haskell example is quite similar to the Scala/Rust example as well. I guess you could rewrite the Haskell version to match your Scala version pretty closely as well if you prefer doing the tuple construction and then matching on the tuple, like in your Scala version, instead of doing it directly inside the pattern match.

Something like this, with the caveat that I haven't done any proper coding in Haskell in years and I don't have an interpreter installed to verify correctness.

  fb :: (Integer, Integer) -> String
  fb (mod3, mod5)
    | (0, 0)    = "FizzBuzz"
    | (0, _)    = "Fizz"
    | (_, 0)    = "Buzz"
    | otherwise = show n
  
  main = putStrLn $ unlines $ map fb $ map (\x -> (x % 3, x % 5)) [1..100]
[+] leereeves|7 years ago|reply
As seen on reddit recently, Rockstar:

  Midnight takes your heart and your soul
  While your heart is as high as your soul
  Put your heart without your soul into your heart
  
  Give back your heart
  
  Desire is a lovestruck ladykiller
  My world is nothing 
  Fire is ice
  Hate is water
  Until my world is Desire,
  Build my world up
  If Midnight taking my world, Fire is nothing and Midnight taking my world, Hate is nothing
  Shout "FizzBuzz!"
  Take it to the top
  
  If Midnight taking my world, Fire is nothing
  Shout "Fizz!"
  Take it to the top
  
  If Midnight taking my world, Hate is nothing
  Say "Buzz!"
  Take it to the top
  
  Whisper my world
(Yes, that's actually source code.)

https://github.com/dylanbeattie/rockstar

[+] levi_n|7 years ago|reply
A bit shorter python version:

    for x in range(1, 101):
        out = ""
        if x % 3 == 0:
            out += "Fizz"
        if x % 5 == 0:
            out += "Buzz"

        print(out or x)
[+] bash-j|7 years ago|reply
Python one liner:

print('\n'.join([{(True, False): 'Fizz', (False, True): 'Buzz', (True, True): 'FizzBuzz'}.get((i % 3 == 0, i % 5 == 0), str(i)) for i in range(1, 101)]))

[+] a3n|7 years ago|reply

  print('\n'.join([
      'fizzbuzz' if x%15 == 0 else
      'fizz' if x%3 == 0 else
      'buzz' if x%5 == 0 else
      str(x)
          for x in range(1, 101)]))
Or

  for x in ['fizzbuzz' if x%15 == 0 else
      'fizz' if x%3 == 0 else
      'buzz' if x%5 == 0 else
      x for x in range(1, 101)]:
    print x
[+] KineticLensman|7 years ago|reply
If you like this may I also recommend [0] which has fizzbuzz in:

Java, VBA, php, cobol, forth, C++, brainfuck, python, Groovu, BASIC, JavaScript, CoffeeScript, sh, PowerShell, Clojure, Ruby, C#, Haskell, ABAP, Lua, Matlab, Common Lisp, Oracle PL/SQL, Scala, F#, Bash, C, LOLCODE, golang, Enterprise Java, MySQL, Visual FoxPro, Perl, shakespeare

Of course, if you want it in Malboge [1], you can refer to a prior HN discussion [2] of FizzBuzz in multiple languages.

[0] http://wiki.c2.com/?FizzBuzzTest

[1] https://en.wikipedia.org/wiki/Malbolge

[2] https://news.ycombinator.com/item?id=4921651

[+] happimess|7 years ago|reply
The "Haskell implementation using monoids" on this page is the only solution I've seen where adding a new behavior (e.g. "FizzBuzzWoof") only requires a modification in one spot.

  (d 3 "Fizz" <> d 5 "Buzz")
becomes

  (d 3 "Fizz" <> d 5 "Buzz" <> d 13 "Woof")
eta: And just below it is a similar solution in Python. Cool!
[+] YeGoblynQueenne|7 years ago|reply
How about machine-learning the Prolog version, using Inductive Logic Programming and Metagol [1]?

Here's one way to do it:

  % e.g. place in metagol/examples/
  :-['../metagol'].
  
  % Second-order inductive bias.
  metarule([P,Q],([P,A,A]:-[[Q,A]])).
  metarule([P,Q,B,C],([P,A,B]:-[[Q,A,C]])).
  
  % Learning primitives.
  prim(positive_integer/1).
  prim(exact_division/2).
  
  % Primitives' definitions.
  positive_integer(N):-
  	between(1,inf,N).
  
  exact_division(X,Y):-
  	positive_integer(X)
  	,divisor(Y)
  	,0 is X mod Y.
  
  divisor(3).
  divisor(5).
  divisor(15).
  
  
  % Training setup.
  learn_fizzbuzz:-
  	% Positive examples
  	Pos = [fizzbuzz(1,1)
  	      ,fizzbuzz(2,2)
  	      ,fizzbuzz(3,fizz)
  	      ,fizzbuzz(5,buzz)
  	      ,fizzbuzz(15,fizzbuzz)
  	      ]
  	% Negative examples
  	,Neg = [fizzbuzz(1,fizz)
  	       ,fizzbuzz(1,buzz)
  	       ,fizzbuzz(3,fizzbuzz)
  	       ,fizzbuzz(5,fizzbuzz)
  	       ]
  	% Train with metagol
  	,learn(Pos,Neg).
We can put that in a file, consult it and call learn_fizzbuzz at the Prolog repl:

  ?- learn_fizzbuzz.
  % learning fizzbuzz/2
  % clauses: 1
  % clauses: 2
  % clauses: 3
  % clauses: 4
  fizzbuzz(A,fizzbuzz):-exact_division(A,15).
  fizzbuzz(A,buzz):-exact_division(A,5).
  fizzbuzz(A,fizz):-exact_division(A,3).
  fizzbuzz(A,A):-positive_integer(A).
  true .

  
This will give us the fizzbuzz/2 function, mapping each integer N to {fizz,buzz,fizzbuzz,N}. Then we can simply loop over it:

  print_fizzbuzz(N):-
  	forall(between(1,N,I)
  	      ,(fizzbuzz(I,FBN)
  	       ,writeln(FBN)
  	       )
  	      ).
Note we learned a general version of fizzbuzz from only 5 positive and 4 negative examples. Just don't tell Joel Grus [2].

_______

[1] https://github.com/metagol/metagol

[2] http://joelgrus.com/2016/05/23/fizz-buzz-in-tensorflow/

[+] chrisulloa|7 years ago|reply
Clojure version

  (defn fizzbuzz [x]
    (cond-> nil
      (zero? (mod x 3)) (str "Fizz")
      (zero? (mod x 5)) (str "Buzz")
      :always (or (str x))))

  (doseq [x (range 1 101)] (prn (fizzbuzz x)))
[+] YeGoblynQueenne|7 years ago|reply
The Prolog version is fine, but the nested conditionals make it harder to read and may cause confusion about scope (for example, it's not necessary to enclose "divBy3(X),divBy5(X)" in parentheses, as on line 6 in the article).

Here's an alternative version, that avoids nested conditionals and also doesn't use the cut ("!") to control backtracking:

  fizzbuzz(X,'Fizz'):-
  	0 is mod(X,3).
  fizzbuzz(X,'Buzz'):-
  	0 is mod(X,5).
  fizzbuzz(X,X):-
  	\+ fizzbuzz(X,'Fizz')
  	,\+ fizzbuzz(X,'Buzz').
  
  print_fizzbuzz(N,M):-
  	N > M.
  print_fizzbuzz(N,M):-
  	N =< M
  	,forall(fizzbuzz(N,FBN)
  	      ,write(FBN)
  	      )
  	,nl
  	,succ(N,N_)
  	,print_fizzbuzz(N_,M).
  
This one uses Prolog's nondeterminsm to generate either Fizz, Buzz, both, or neither as apropriate and collects them all with forall/2 (yes, Prolog does have for-loops; of a sort), then adds a newline to the output.

Call it like this:

  ?- print_fizzbuzz(1,100).
And have a Happy New Year.
[+] vertline3|7 years ago|reply
Why or how did fizzbuzz earn its place in lore? I looked at Wikipedia and it didn't seem to go into detail.

Also we have the teapot, hello world, Foo Bar

What are some others?

[+] stcredzero|7 years ago|reply
Why or how did fizzbuzz earn its place in lore?

The functional why was as a filter for eliminating impostors. At the time it was new, no one could look up the answers for it, because it was such an arbitrary problem. Now, it's just a curiosity.

[+] RobertKerans|7 years ago|reply
A few others that are similar:

- fibonacci sequence to n (ooh, look, isn't recursion pretty) - parallel map (simple demonstration of parallelism in languages that allow it)

[slightly more involved, webapp hello worlds] - basic blog (various MVC web frameworks, normally along lines of if I run commands x, y and z I get models, views and controllers and it all works) - basic todo application (various frontend frameworks) - basic chat application (as a realtime demonstration, generally for websockets)

[+] tyingq|7 years ago|reply
Printing the lyrics to "99 bottles of beer".
[+] Tarean|7 years ago|reply
Took this as an excuse to write it in pure lambda calculus https://gist.github.com/Tarmean/65da65b8da37bd66d48e96d2aa73...

I always enjoy how lambda calculus suddenly becomes a readable language after the prelude:

     let (\n.
         let (\m. isZero (mod n m)) \divisibleBy.
         if (and (divisibleBy 3) (divisibleBy 5))
         then FizzBuzz
         else
           (if (divisibleBy 3)
            then Fizz
            else
              (if (divisibleBy 5)
               then Buzz
               else (intToStr n))))
      \fizzBuzzStep.
      (loop \recurse. \n.
          if (equals n 100)
          then nil
          else (cons (fizzBuzzStep n) (recurse (n+1)))
        ) 1)
    (\letArg letBody. letBody letArg)
let, if, then, else, loop, and even the numbers are all functions.
[+] crispyambulance|7 years ago|reply
The whole point of fizzbuzz is to filter for people that can just solve a tiny problem in a reasonably short time-- that's it. Most interviewers will even give some slack if the person has to look up the modulo operator or even do with out it.

If someone can't do it at all there's some kind of serious issue with the way they're approaching the problem, or perhaps they're just not capable of doing it.

But another common way for people to fail or at least get red-flagged is to over-think it and come up with a turgid solution-- like using lambda calculus!

Simple problem. Simple solution. Nothing fancy. Going against that is asking for failure.

[+] leifmetcalf|7 years ago|reply
I'm a bit confused, how did you implement let, if, else etc.? I don't really know much about the lambda calculus except for what I learned from a short youtube video.
[+] Spivak|7 years ago|reply
Your bash example could be a little cleaner. Since 0 is truthy in bash and [ `expr something` ] is, for most purposes, (( )).

    for i in {1..100}; do
        if (( $i % 3 && $i % 5 )); then
            echo FizzBuzz
        elif (( $i % 3 )); then
            echo Fizz
        elif (( $i % 5 )); then
            echo Buzz
        else
            echo $i
        fi
    done

Bash also has a decently powerful matching statement so you can do something similar to the rust example.

    for i in {1..100}; do
        case "$(( $i % 3 ))$(( $i % 5 ))" in
            00)
                echo FizzBuzz
                ;;
            0*)
               echo Fizz
               ;;
            *0)
               echo Buzz
               ;;
            *)
               echo $i
               ;;
        esac
    done
[+] TedDallas|7 years ago|reply
--A T-SQL version

  Select Case When SomeNumber % 3 = 0 and SomeNumber % 5 = 0 Then 'FizzBuzz'
              When SomeNumber % 3 = 0 Then 'Fizz'
              When SomeNumber % 5 = 0 Then 'Buzz'
              Else Convert(VarChar(10), SomeNumber)
              End As Answer
  From (
      Select Top 100 
          SomeNumber = Row_Number() Over (Order By [object_id]) 
      From sys.all_objects
  ) as Answers
[+] a3n|7 years ago|reply
I love a good fizzbuzz HN thread, on a snowy day off with coffee, almost as much as a good vim HN thread.
[+] _old_dude_|7 years ago|reply
Java version using higher order functions :)

  public interface Matcher {
    Optional<String> match(int value);

    static Matcher divideBy(int div, String text) {
      return value -> Optional.of(value).filter(v -> v % div == 0).map(__ -> text);
    }

    default Matcher zip(Matcher matcher, BinaryOperator<String> op) {
      return value -> Stream.of(match(value), matcher.match(value)).flatMap(Optional::stream).reduce(op);
    }

    public static void main(String[] args) {
      var matcher = divideBy(3, "Fizz").zip(divideBy(5, "Buzz"), String::concat);
      IntStream.rangeClosed(0, 100)
          .mapToObj(value -> matcher.match(value).orElse("" + value))
          .skip(1).forEach(System.out::println);
    }
  }
[+] okl|7 years ago|reply
An Ada version using predicates:

  with Ada.Text_IO;

  procedure FizzBuzz_Predicate is
     subtype Div_3 is Integer
        with Dynamic_Predicate => Div_3 mod 3 = 0;
     subtype Div_5 is Integer
        with Dynamic_Predicate => Div_5 mod 5 = 0;
  begin
     for i in Integer range 1 .. 99 loop
        if i in Div_3 and i in Div_5 then
           Ada.Text_IO.Put_Line ("FizzBuzz");
        elsif i in Div_3 then
           Ada.Text_IO.Put_Line ("Fizz");
        elsif i in Div_5 then
           Ada.Text_IO.Put_Line ("Buzz");
        else
           Ada.Text_IO.Put_Line (Integer'Image (i));
        end if;
     end loop;
  end FizzBuzz_Predicate;