Language C++
Date: | 04/15/09 |
Author: | Jono |
URL: | http://monstavision.com |
Comments: | 0 |
Info: | n/a |
Score: | (2.50 in 8 votes) |
// green_bottles.cpp // by jono <jp@day-one.com> #include <iostream> #include <sstream> #include <string> #include <vector> using std::ostringstream; using std::cout; using std::vector; using std::string; using std::endl; const unsigned MAX_DECIMATE = 1000000000; const unsigned MAX_BOTTLES = 0 - 1; struct BottlesOfBeer { BottlesOfBeer(unsigned n, bool cap = false) :_(n) ,cap_(cap) {} const unsigned _; const bool cap_; }; string englishNumber(unsigned n) { ostringstream os; vector<unsigned> result; unsigned decimate = MAX_DECIMATE; static const char *ONES[] = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }; static const char *TENS[] = { "", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" }; static const char *THOUS[] = { "", "thousand", "million", "billion" }; bool keep = false; for(unsigned tmp = n; decimate > 0; tmp = tmp%decimate, decimate /= 10) { keep = keep ? keep : (tmp >= decimate); if(keep) { unsigned unit = (tmp - tmp%decimate)/decimate; result.push_back(unit); } } bool and = false, space = false, comma = false; unsigned tens = 0; //tens buffer unsigned decades = result.size(); vector<unsigned>::iterator it = result.begin(); for(int cnt = 1; it != result.end(); it++, cnt++) { if(!(tens || *it)) continue; if(comma)os << ','; comma = false; if(space)os << ' '; space = false; switch((decades-cnt)%3) { case 0: { unsigned number = tens + *it; if(!number) continue; if(number && and) os << " and ", and = false; if(number < 20)os << ONES[number]; else { unsigned ones = number%10; os << TENS[number/10]; if(ones) os << ' ' << ONES[ones]; } unsigned dec = (decades-cnt)/3; if(dec)os << ' '; os << THOUS[dec]; comma = true; space = true; } break; case 1: tens = *it * 10; continue; case 2: if(*it) os << ONES[*it] << ' ' << "hundred"; and = true; break; default: break; } } os << std::ends; return os.str(); } inline std::ostream &operator<<(std::ostream &os, const BottlesOfBeer &bottles) { static unsigned nCache = 0; static string sCache; if(!nCache || nCache != bottles._) if(!bottles._)sCache = "no more "; else sCache = englishNumber(bottles._), nCache = bottles._; if(!sCache.length()) throw "a banana"; os << char(bottles.cap_ ? sCache.at(0) - 32 : sCache.at(0)) << sCache.substr(1).c_str(); os << " bottle"; if(bottles._ != 1) os << 's'; os << " of beer"; return os; } struct Bar { Bar(unsigned capacity) : shelving_((capacity <= MAX_BOTTLES) ? capacity : MAX_BOTTLES) , stock_(shelving_) {} inline void open(bool never_close = false); private: const unsigned shelving_; unsigned stock_; }; inline void Bar::open(bool never_close) { static const char coda[] = " on the wall"; static const char next[] = "Take one down and pass it around, "; static const char last[] = "Go to the store and buy some more, "; for(;; stock_--) { std::cout << std::endl << BottlesOfBeer(stock_, true) << coda << ", " << BottlesOfBeer(stock_) << '.' << std::endl << (stock_?next:last) << BottlesOfBeer(stock_?stock_-1:shelving_) << coda << '.' << std::endl ; if(!stock_) if(never_close)stock_ = shelving_; else break; } } int main(int argc, char* argv[]) { Bar bar(0 - 1); bar.open(true); return 0; }
Download Source | Write Comment
Alternative Versions
Version | Author | Date | Comments | Rate |
---|---|---|---|---|
object-oriented version | Tim Robinson | 04/20/05 | 4 | |
hacking style | Tim Robinson | 04/20/05 | 14 | |
extreme template metaprogramming | Richard Wolf | 04/20/05 | 5 | |
meta programming | Arion Lei | 04/20/05 | 5 | |
Preprocessor & self-include recursion | Chocapic | 02/27/07 | 6 | |
feature creep | Jono | 04/27/09 | 1 | |
most extreme template metaprogramming | Henrik Theiling | 12/04/11 | 0 | |
ob fuscated | Tapi (Paddy O'Brien) | 08/11/05 | 4 | |
GUI version | Martyn Davies | 05/28/05 | 1 |
Download Source | Write Comment
Add Comment
Please provide a value for the fields Name,
Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.
Please don't post large portions of code here! Use the form to submit new examples or updates instead!
Comments