Sunday, March 21, 2010

FizzBuzz? SRSLY?

I was playing with Visual Studio 2010 and could not resist. Does that mean I'm not a good software developer? Anyway, without further ado, I present to you my ridiculously overengineered, gold-plated version of FizzBuzz in C++. Complete with lazy evaluation via a custom random access iterator. I'm not a C++ guru, so I probably got a lot of stuff wrong. If you take the time to write a comment about my mistakes, it won't have been a complete waste of time. Well, not for me at least.


#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
#include <stdexcept>

class fizzbuzz {
public:
 class const_iterator;
 typedef std::pair<int, int> range;

 fizzbuzz(const range& range = range(0, 100),
    int fizz_num = 3,
    int buzz_num = 5,
    const std::string& fizz_word = "Fizz",
    const std::string& buzz_word = "Buzz")
  : _range(range),
    _fizz_num(fizz_num),
    _buzz_num(buzz_num),
    _fizz_word(fizz_word),
    _buzz_word(buzz_word) {}

 range get_range() const { return _range; }

 int get_fizz_num() const { return _fizz_num; }

 int get_buzz_num() const { return _buzz_num; }

 std::string get_fizz_word() const { return _fizz_word; }

 std::string get_buzz_word() const { return _buzz_word; }

 int get_fizz_num() { return _fizz_num; }

 int get_buzz_num() { return _buzz_num; }

 std::string get_fizz_word() { return _fizz_word; }

 std::string get_buzz_word() { return _buzz_word; }

 void set_fizz_num(int num) { _fizz_num = num; }

 void set_buzz_num(int num) { _buzz_num = num; }

 void set_fizz_word(const std::string& word) { _fizz_word = word; }
 
 void set_buzz_word(const std::string& word) { _buzz_word = word; }

 const_iterator begin() const { return const_iterator(this); }

 const_iterator end() const { return const_iterator(this, true); }

 class const_iterator {
 public:
  typedef std::string value_type;
  typedef std::random_access_iterator_tag iterator_category;

  const_iterator(const fizzbuzz* fb, bool end=false) :
    _fb(fb) {
   if (end) {
    _current = _fb->get_range().second;
   } else {
    _current = _fb->get_range().first;
   }
  }

  const_iterator(const const_iterator& other) {
   *this = other;
  }

  const_iterator& operator=(const const_iterator& rhs) {
   if (this == &rhs)
    return *this;
   this->_fb = rhs._fb;
   this->_current = rhs._current;
   return *this;
  }

  value_type operator*() const {
   if ((_current < _fb->get_range().first) ||
    (_current >= _fb->get_range().second))
    throw std::out_of_range("fizz went buzz(t)");
   return _fb->get_value(_current);
  }

  const_iterator& operator++() {
   _current++;
   return *this;
  }

  const_iterator& operator++(int) {
   _current++;
   return *this;
  }
  
  const_iterator& operator--() {
   _current--;
   return *this;
  }

  const_iterator& operator--(int) {
   _current--;
   return *this;
  }

  value_type operator[](int index) const {
   if ((index < _fb->get_range().first) ||
    (index >= _fb->get_range().second))
    throw std::out_of_range("fizz went buzz(t)");
   return _fb->get_value(index);
  }

  bool operator==(const const_iterator& rhs) const {
   return rhs._current == _current;
  }

  bool operator!=(const const_iterator& rhs) const {
   return !(*this == rhs);
  }

 private:
  const fizzbuzz* _fb;
  int _current;
 };

private:
 bool fizz(int num) const { return num % _fizz_num == 0; }

 bool buzz(int num) const { return num % _buzz_num == 0; }

 const std::string get_value(int num) const {
  if (fizz(num) && buzz(num))
   return _fizz_word + _buzz_word;

  if (fizz(num))
   return _fizz_word;

  if (buzz(num))
   return _buzz_word;

  std::stringstream s;
  s << num;
  return s.str();
 }

 range _range;
 int _fizz_num;
 int _buzz_num;
 std::string _fizz_word;
 std::string _buzz_word;
};

int main()
{
 fizzbuzz fb(fizzbuzz::range(0, 100));
 for (fizzbuzz::const_iterator it(fb.begin()); it != fb.end(); ++it) {
  std::cout << *it << std::endl;
 }
 
 std::cout << std::endl;
 std::cout << "And now for some random access..." << std::endl << std::endl;

 fizzbuzz::const_iterator it(fb.begin());
 std::cout << "it[5]: " << it[5] << std::endl;
 std::cout << "it[15]: " << it[15] << std::endl;
 std::cout << "it[33]: " << it[33] << std::endl;
 std::cout << "it[49]: " << it[49] << std::endl;
 return 0;
}

No comments:

Post a Comment