Amazon.com Widgets Fun Code of the Week #5

Fun Code of the Week #5

By Nick at October 24, 2012 21:39
Filed Under: Delphi, Fun Code

What is your FizzBuzz solution?  Any comments on mine?

If this is an interview question, what are you looking for?

Here is FizzBuzz in over 150 languages.

For the record, I spent no more than three minutes to write this. :-)

program FizzBuzz;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

var
  i: integer;
  WriteNumber: Boolean;

begin
  try
    for i := 1 to 100 do
    begin
      WriteNumber := True;
      if i mod 3 = 0  then
      begin
        Write('Fizz');
        WriteNumber := False;
      end;
      if i mod 5 = 0 then
      begin
        Write('Buzz');
        WriteNumber := False;
      end;
      if WriteNumber then
      begin
        Write(i);
      end;
      WriteLn;
    end;
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Comments (25) -

10/24/2012 10:28:31 PM #

Bruce McGee

The flag makes the logic a little fuzzy (pun intended).

Bruce McGee Canada |

10/24/2012 10:45:12 PM #

Nick Hodges

Hardy har har har.

Wink

Nick Hodges United States |

10/26/2012 10:57:04 AM #

Bruce McGee


As I think about it, I should have written the example more like this, with the FizzBuzz logic broken out into its own, more testable, function.

program FizzBuzz;

{$APPTYPE CONSOLE}

uses SysUtils;

function GetFizzBuzz(aValue: Integer): string;
begin
  if aValue mod 15 = 0 then
    Result := 'FizzBuzz'
  else if aValue mod 3 = 0 then
    Result := 'Fizz'
  else if aValue mod 5 = 0 then
    Result := 'Buzz'
  else
    Result := IntToStr(aValue);
end;

var
  i: Integer;
begin
  for i := 1 to 100 do
    Writeln(GetFizzBuzz(i));
end.

Bruce McGee Canada |

10/24/2012 11:21:20 PM #

Sean B. Durkin

Here's my crack at it...

program FizzBuzz;
uses SysUtils, StrUtils;
var
  s: string;
  i: Integer;
begin
for i := 1 to 100 do
  begin
  s := ifThen( i mod 3 = 0, 'Fizz', '');
  s := IfThen( i mod 5 = 0, s + 'Buzz', s);
  WriteLn( IfThen( s='', IntToStr( i), s))
  end
end.

Sean B. Durkin Australia |

10/25/2012 1:34:37 PM #

Bruce McGee

More concise than mine.  

I have to admit that I have never used IfThen().

Bruce McGee Canada |

10/25/2012 3:55:55 PM #

Alister Christie

Never new about IfThen() - Learn something new everyday Wink
Should probably have a good read of StrUtils.

Alister Christie New Zealand |

10/25/2012 12:24:22 AM #

Tapper

A slightly more SOLID version. About 20 mins coding.

unit uFizzBuzz;

interface

type
  TOddEven = (isNum, is3, is5);

  TOddEvenOutput = reference to procedure(WhichWay : TOddEven; const Iteration : integer);

  IOddEvenIterator = interface
    procedure Start;
  end;

  TOddEvenIterator = class(TInterfacedObject, IOddEvenIterator)
  private
    FStartValue, FMaxIterations : integer;
    FOutput : TOddEvenOutput;
  public
    constructor Create(StartValue, MaxIterations : integer; const Output : TOddEvenOutput);
    procedure Start;
  end;

implementation

{ TOddEvenIterator }

constructor TOddEvenIterator.Create(StartValue, MaxIterations: integer; const Output : TOddEvenOutput);
begin
  FStartValue := StartValue;
  FMaxIterations := MaxIterations;
  FOutput := Output;
end;

procedure TOddEvenIterator.Start;
var
  i: Integer;
begin
  for i := FStartValue to FMaxIterations do
  begin
    if (i mod 3 = 0) then
       FOutput(is3, i)
    else if (i mod 5 = 0) then
      FOutput(is5, i)
    else
      FOutput(isNum, i);
  end;
end;

end.

And the tests
unit FizzBuzzTests;

interface

uses
  TestFramework, uFizzBuzz;

type
  TFizzBuzzTest = class(TTestCase)
  published
    procedure TestBuzz;
    procedure TestNumber;
    procedure TestFizz;
  end;

implementation

uses
  SysUtils;

{ TFizzBuzzTest }

procedure TFizzBuzzTest.TestFizz;
var
  Output : string;
  FizzBuzz : IOddEvenIterator;
begin
  FizzBuzz := TOddEvenIterator.Create(1, 3,
    procedure(WhichWay : TOddEven; const Iteration : integer)
    begin
      case WhichWay of
        is3 : Output := 'Fizz';
        is5 : Output := 'Buzz';
      else
        Output := IntToStr(Iteration);
      end;
    end);
  FizzBuzz.Start;

  CheckEqualsString('Fizz', Output);
end;

procedure TFizzBuzzTest.TestNumber;
var
  Output : string;
  FizzBuzz : IOddEvenIterator;
begin
  FizzBuzz := TOddEvenIterator.Create(1, 1,
    procedure(WhichWay : TOddEven; const Iteration : integer)
    begin
      case WhichWay of
        is3 : Output := 'Fizz';
        is5 : Output := 'Buzz';
      else
        Output := IntToStr(Iteration);
      end;
    end);
  FizzBuzz.Start;

  CheckEqualsString('1', Output);
end;

procedure TFizzBuzzTest.TestBuzz;
var
  FizzBuzz : IOddEvenIterator;
  Output : string;
begin
  FizzBuzz := TOddEvenIterator.Create(1, 10,
    procedure(WhichWay : TOddEven; const Iteration : integer)
    begin
      case WhichWay of
        is5 : Output := 'Buzz';
      end;
    end);
  FizzBuzz.Start;

  CheckEqualsString('Buzz', Output);
end;

initialization
  RegisterTest(TFizzBuzzTest.Suite);

end.

Tapper United States |

10/25/2012 11:57:24 AM #

Nick Hodges

Tapper --

That is awesome!  Totally over-engineered, but awesome.  Smile

Nick Hodges United States |

10/25/2012 2:08:57 AM #

Motaz

Dear Nick,
why do you use exception handling in your code?

Motaz |

10/25/2012 11:57:52 AM #

Nick Hodges

It's just the default template for a Console app.

Nick Hodges United States |

10/25/2012 8:16:33 AM #

Sir Rufo

Here is my approach with the State Pattern (greets from GoF)

program FizzBuzz_StatePattern;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

type
  TCustomFizzBuzzState = class;
  TFizzBuzzStateClass  = class of TCustomFizzBuzzState;

  TFizzBuzz = class
    private
      FIndex : Integer;
      FState : TCustomFizzBuzzState;
    protected
      procedure DoWriteIndex;
      procedure DoWriteString( const AString : string );
      procedure DoWriteEOL;
      procedure DoIncIndex;
      procedure DoSetState( AStateClass : TFizzBuzzStateClass );
    public
      procedure Execute( AIndex, ACount : Integer );
  end;

  TCustomFizzBuzzState = class
    private
      FContext : TFizzBuzz;
    protected
      procedure DoWriteIndex;
      procedure DoWriteString( const AString : string );
      procedure DoWriteEOL;
      procedure DoIncIndex;
      procedure DoSetState( AStateClass : TFizzBuzzStateClass );
    public
      constructor Create( AContext : TFizzBuzz );
      procedure Consume( AValue : Integer ); virtual; abstract;
  end;

  TStartState = class( TCustomFizzBuzzState )
    public
      procedure Consume( AValue : Integer ); override;
  end;

  TFizzState = class( TCustomFizzBuzzState )
    public
      procedure Consume( AValue : Integer ); override;
  end;

  TBuzzState = class( TCustomFizzBuzzState )
    public
      procedure Consume( AValue : Integer ); override;
  end;

  TFizzBuzzState = class( TCustomFizzBuzzState )
    public
      procedure Consume( AValue : Integer ); override;
  end;

  TNumberState = class( TCustomFizzBuzzState )
    public
      procedure Consume( AValue : Integer ); override;
  end;

  TEndLineState = class( TCustomFizzBuzzState )
    public
      procedure Consume( AValue : Integer ); override;
  end;

  { TFizzBuzzStateBase }

constructor TCustomFizzBuzzState.Create( AContext : TFizzBuzz );
begin
  inherited Create;
  FContext := AContext;
end;

procedure TCustomFizzBuzzState.DoIncIndex;
begin
  FContext.DoIncIndex;
end;

procedure TCustomFizzBuzzState.DoSetState( AStateClass : TFizzBuzzStateClass );
begin
  FContext.DoSetState( AStateClass );
end;

procedure TCustomFizzBuzzState.DoWriteEOL;
begin
  FContext.DoWriteEOL;
end;

procedure TCustomFizzBuzzState.DoWriteIndex;
begin
  FContext.DoWriteIndex;
end;

procedure TCustomFizzBuzzState.DoWriteString( const AString : string );
begin
  FContext.DoWriteString( AString );
end;

{ TFizzBuzz }

procedure TFizzBuzz.DoIncIndex;
begin
  Inc( FIndex );
end;

procedure TFizzBuzz.DoSetState( AStateClass : TFizzBuzzStateClass );
begin
  if Assigned( FState )
  then
    FState.Free;

  FState := AStateClass.Create( Self );
end;

procedure TFizzBuzz.DoWriteEOL;
begin
  Writeln;
end;

procedure TFizzBuzz.DoWriteIndex;
begin
  write( FIndex );
end;

procedure TFizzBuzz.DoWriteString( const AString : string );
begin
  write( AString );
end;

procedure TFizzBuzz.Execute( AIndex, ACount : Integer );
begin
  DoSetState( TFizzState );
  FIndex := AIndex;
  while FIndex < AIndex + ACount do
    begin
      FState.Consume( FIndex );
    end;
end;

{ TStartState }

procedure TStartState.Consume( AValue : Integer );
begin
  DoSetState( TFizzState );
end;

{ TFizzState }

procedure TFizzState.Consume( AValue : Integer );
begin
  if AValue mod 3 = 0
  then
    begin
      DoWriteString( 'Fizz' );
      DoSetState( TFizzBuzzState );
    end
  else
    DoSetState( TBuzzState );
end;

{ TEndLineState }

procedure TEndLineState.Consume( AValue : Integer );
begin
  DoWriteEOL;
  DoIncIndex;
  DoSetState( TStartState );
end;

{ TBuzzState }

procedure TBuzzState.Consume( AValue : Integer );
begin
  if AValue mod 5 = 0
  then
    begin
      DoWriteString( 'Buzz' );
      DoSetState( TEndLineState );
    end
  else
    DoSetState( TNumberState );
end;

{ TNumberState }

procedure TNumberState.Consume( AValue : Integer );
begin
  DoWriteIndex;
  DoSetState( TEndLineState );
end;

{ TFizzBuzzState }

procedure TFizzBuzzState.Consume( AValue : Integer );
begin
  if AValue mod 5 = 0
  then
    begin
      DoWriteString( 'Buzz' );
    end;
  DoSetState( TEndLineState );
end;

var
  FizzBuzz : TFizzBuzz;

begin
  try

    FizzBuzz := TFizzBuzz.Create;
    try

      FizzBuzz.Execute( 1, 100 );

    finally
      FizzBuzz.Free;
    end;

    Readln;

  except
    on E : Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;

end.

Sir Rufo Germany |

10/25/2012 11:58:10 AM #

Nick Hodges

Awesome!

Nick Hodges United States |

10/25/2012 11:15:01 AM #

Filippo Forlani

Sure, not my approach... just one of my friend told me..... Smile

Program FizzBuzz;

var
  i: integer;

begin
  for i:=1 to 100 do
  case i of
  1: writeln("1");
  2: writeln("2");
  3: writeln("Fizz");
  4: writeln("4");
  5: writeln("Buzz");
  6: writeln("Fizz");
  7: writeln("7");
  8: writeln("8");
  9: writeln("Fizz");
  10: writeln("10");
  11: writeln("11");
  12: writeln("Fizz");
  13: writeln("13");
  14: writeln("14");
  15: writeln("FizzBuzz");
  16: writeln("16");
  17: writeln("17");
  18: writeln("Fizz");
  19: writeln("19");
  20: writeln("Buzz");
  21: writeln("Fizz");
  22: writeln("22");
  23: writeln("23");
  24: writeln("Fizz");
  25: writeln("Buzz");
  26: writeln("26");
  27: writeln("Fizz");
  28: writeln("28");
  29: writeln("29");
  30: writeln("FizzBuzz");
  31: writeln("31");
  32: writeln("32");
  33: writeln("Fizz");
  34: writeln("34");
  35: writeln("Buzz");
  36: writeln("Fizz");
  37: writeln("37");
  38: writeln("38");
  39: writeln("Fizz");
  40: writeln("Buzz");
  41: writeln("41");
  42: writeln("Fizz");
  43: writeln("43");
  44: writeln("44");
  45: writeln("FizzBuzz");
  46: writeln("46");
  47: writeln("47");
  48: writeln("Fizz");
  49: writeln("49");
  50: writeln("Buzz");
  51: writeln("Fizz");
  52: writeln("52");
  53: writeln("53");
  54: writeln("Fizz");
  55: writeln("Buzz");
  56: writeln("56");
  57: writeln("Fizz");
  58: writeln("58");
  59: writeln("59");
  60: writeln("FizzBuzz");
  61: writeln("61");
  62: writeln("62");
  63: writeln("Fizz");
  64: writeln("64");
  65: writeln("Buzz");
  66: writeln("Fizz");
  67: writeln("67");
  68: writeln("68");
  69: writeln("Fizz");
  70: writeln("Buzz");
  71: writeln("71");
  72: writeln("Fizz");
  73: writeln("73");
  74: writeln("74");
  75: writeln("FizzBuzz");
  76: writeln("76");
  77: writeln("77");
  78: writeln("Fizz");
  79: writeln("79");
  80: writeln("Buzz");
  81: writeln("Fizz");
  82: writeln("82");
  83: writeln("83");
  84: writeln("Fizz");
  85: writeln("Buzz");
  86: writeln("86");
  87: writeln("Fizz");
  88: writeln("88");
  89: writeln("89");
  90: writeln("FizzBuzz");
  91: writeln("91");
  92: writeln("92");
  93: writeln("Fizz");
  94: writeln("94");
  95: writeln("Buzz");
  96: writeln("Fizz");
  97: writeln("97");
  98: writeln("98");
  99: writeln("Fizz");
  100: writeln("Buzz");
  end;
end!

Filippo Forlani Italy |

10/25/2012 11:58:36 AM #

Nick Hodges

That is sweet.

Nick Hodges United States |

10/25/2012 12:36:21 PM #

Mason Wheeler

Gah! It's the FOR/CASE paradigm!  thedailywtf.com/.../The_FOR-CASE_paradigm.aspx

(Hey Nick, how do you post a link in comments on here? Neither HTML <A> tags nor BBCode [link] tags seem to work...)

Mason Wheeler United States |

10/25/2012 2:05:02 PM #

Nick Hodges

Mason --

Just post the link, and it will be automatically converted (see above....)

Nick Hodges United States |

10/25/2012 11:37:07 AM #

Richard Davis

Interesting how none of these examples fully implements FizzBuzz. Everyone seems to be missing when the number is a multiple of 3 and 5, print "FizzBuzz".

Richard Davis United States |

10/25/2012 11:58:43 AM #

Remy Lebeau

Both Nick's and Sean's examples do implement the 'FizzBuzz' condition.

Remy Lebeau United States |

10/25/2012 11:58:53 AM #

Nick Hodges

Mine does!

Nick Hodges United States |

10/25/2012 12:01:34 PM #

Remy Lebeau

Not entirely sure, but I think Sir Rufo's example does, too.

Remy Lebeau United States |

10/25/2012 2:32:20 PM #

SirRufo

Yes of course it does

SirRufo Germany |

11/4/2012 11:38:37 PM #

Richard Davis

Sorry, for some reason I was reading an "else" between the if statements for Nick's implementation. I'm not sure what my excuse is for the other two.

Richard Davis United States |

10/25/2012 12:38:34 PM #

Filippo Forlani

we should try to find the source code (in pascal) with lesser characters to do that...
and the most elegant!

and win a beer each!

Filippo Forlani Italy |

10/25/2012 1:40:49 PM #

Jeffrey

I did not see one of the 150 done in t/SQL so:

alter procedure [dbo].[FizzBuzz]
as
declare @II    as integer
begin
  set nocount on
  create table #TempTable (FB varchar(8))
  set @II = 0
  while (@II < 100)
  begin
    set @II = @II + 1
    insert into #TempTable values (
      case
        when ((@II - (@II / 15 * 15)) = 0) then 'FizzBuzz'
        when ((@II - (@II / 5 * 5)) = 0)  then 'Buzz'
        when ((@II - (@II / 3 * 3)) = 0)  then 'Fizz'
        else convert(char(3),@II)
      end)
  end
  select * from #TempTable
end

-- exec fizzbuzz

Jeffrey United States |

10/25/2012 7:14:13 PM #

Wouter

Somebody should create a fizzbuzz webservice so that we don't have to worry about implementation details of the algorithm anymore.

Wouter Netherlands |

Comments are closed

My Book

A Pithy Quote for You

"Courage is not simply one of the virtues, but the form of every virtue at its testing point."    –  C. S. Lewis

Amazon Gift Cards

General Disclaimer

The views I express here are entirely my own and not necessarily those of any other rational person or organization.  However, I strongly recommend that you agree with pretty much everything I say because, well, I'm right.  Most of the time. Except when I'm not, in which case, you shouldn't agree with me.

Month List