diff options
-rw-r--r-- | histogram.cpp | 167 |
1 files changed, 84 insertions, 83 deletions
diff --git a/histogram.cpp b/histogram.cpp index 5bb2133..855776d 100644 --- a/histogram.cpp +++ b/histogram.cpp @@ -3,140 +3,141 @@ #include <vector> #include <algorithm> #include <cmath> +#include <cstdint> #include <cstring> #include <cassert> -using namespace std; +static const char *argv0; -const char *argv0; - -void usage(){ - cerr<<"Usage: "<<argv0<<" [<lowbound> <highbound>] [<nbins>]"<<endl - <<"Prints a simple histogram of stdin data in your terminal, using"<<endl - <<"either the given lower and upper bounds, or the minimum and"<<endl - <<"maximum extracted from the data."<<endl - <<"The number of bins can also be passed."<<endl - <<"Data on stdin is assumed to be a list of floating-point values."<<endl; +void usage() { + std::cerr << "Usage: " << argv0 << " [<lowbound> <highbound>] [<nbins>]" << std::endl + << "Prints a simple histogram of stdin data in your terminal, using" << std::endl + << "either the given lower and upper bounds, or the minimum and" << std::endl + << "maximum extracted from the data." << std::endl + << "The number of bins can also be passed." << std::endl + << "Data on stdin is assumed to be a list of floating-point values." << std::endl; } -double parsefloat(const char *s,const char *errprefix){ +double parsefloat(const char *s, const char *errprefix) { char *endp; - double v=strtod(s,&endp); - if(!s[0]||*endp){ - cerr<<errprefix<<" '"<<s<<"'"<<endl; + double v = strtod(s, &endp); + if (!s[0] || *endp) { + std::cerr << errprefix << " '" << s << "'" << std::endl; usage(); exit(1); } return v; } -int parseint(const char *s,const char *errprefix){ +int64_t parseint(const char *s, const char *errprefix) { char *endp; - int v=strtol(s,&endp,10); - if(!s[0]||*endp){ - cerr<<errprefix<<" '"<<s<<"'"<<endl; + int64_t v = strtoll(s, &endp, 10); + if (!s[0] || *endp) { + std::cerr << errprefix << " '" << s << "'" << std::endl; usage(); exit(1); } return v; } -int main(int argc,char **argv){ - argv0=argv[0]; +int main(int argc, char **argv) { + argv0 = argv[0]; - const int BARWIDTH=80; + const int64_t BARWIDTH = 80; - double low,high; + double low, high; bool havebounds; - int nbins=10; - - if(argc==1){ - havebounds=false; - } else if(argc==2){ - havebounds=false; - nbins=parseint(argv[1],"Invalid number"); - } else if(argc==3){ - havebounds=true; - low=parsefloat(argv[1],"Invalid number"); - high=parsefloat(argv[2],"Invalid number"); - } else if(argc==4){ - havebounds=true; - low=parsefloat(argv[1],"Invalid number"); - high=parsefloat(argv[2],"Invalid number"); - nbins=parseint(argv[3],"Invalid number"); + int64_t nbins = 10; + + if (argc == 1) { + havebounds = false; + } else if (argc == 2) { + havebounds = false; + nbins = parseint(argv[1], "Invalid number"); + } else if (argc == 3) { + havebounds = true; + low = parsefloat(argv[1], "Invalid number"); + high = parsefloat(argv[2], "Invalid number"); + } else if (argc == 4) { + havebounds = true; + low = parsefloat(argv[1], "Invalid number"); + high = parsefloat(argv[2], "Invalid number"); + nbins = parseint(argv[3], "Invalid number"); } else { usage(); return 1; } - if(nbins<1){ - cerr<<"histogram: Invalid number of bins '"<<nbins<<"'"<<endl; + if (nbins < 1) { + std::cerr << "histogram: Invalid number of bins '" << nbins << "'" << std::endl; usage(); return 1; } - if(havebounds&&high<=low){ - cerr<<"histogram: high <= low"<<endl; + if (havebounds && high <= low) { + std::cerr << "histogram: high <= low" << std::endl; usage(); return 1; } - double minval=INFINITY,maxval=-INFINITY; - vector<double> values; - while(true){ + double minval = INFINITY, maxval = -INFINITY; + std::vector<double> values; + while (true) { double v; - cin>>v; - if(!cin)break; + std::cin >> v; + if (!std::cin) break; values.push_back(v); - if(v<minval)minval=v; - if(v>maxval)maxval=v; + if (v < minval) minval = v; + if (v > maxval) maxval = v; } - if(!havebounds){ - low=minval; - high=maxval; + if (!havebounds) { + low = minval; + high = maxval; } - sort(values.begin(),values.end()); + std::sort(values.begin(), values.end()); - vector<int> histogram(nbins); + std::vector<int64_t> histogram(nbins); - int binidx=0,tally=0,maxtally=-1; - for(double v : values){ - if(v<low||v>high){ - // cerr<<"Point "<<v<<" out of range!"<<endl; + int64_t binidx = 0, tally = 0, maxtally = -1; + for (double v : values) { + if (v < low || v > high) { + // cerr << "Point " << v << " out of range!" << endl; continue; } - int bin=(v-low)/(high-low)*nbins; - if(bin==nbins)bin--; - assert(bin>=0&&bin<nbins); - if(bin!=binidx){ - histogram[binidx]=tally; - if(tally>maxtally)maxtally=tally; - binidx=bin; - tally=0; + int64_t bin = (v - low) / (high - low) * nbins; + if (bin == nbins) bin--; + assert(bin >= 0 && bin < nbins); + if (bin != binidx) { + histogram[binidx] = tally; + if (tally > maxtally) maxtally = tally; + binidx = bin; + tally = 0; } tally++; } - histogram[binidx]=tally; - if(tally>maxtally)maxtally=tally; + histogram[binidx] = tally; + if (tally > maxtally) maxtally = tally; - if(maxtally==0){ - cerr<<"histogram: No data in range"<<endl; + if (maxtally == 0) { + std::cerr << "histogram: No data in range" << std::endl; return 1; } - char fullbar[BARWIDTH+1]; - memset(fullbar,'#',BARWIDTH); - fullbar[BARWIDTH]='\0'; - char emptybar[BARWIDTH+1]; - memset(emptybar,' ',BARWIDTH); - emptybar[BARWIDTH]='\0'; - - for(int i=0;i<(int)histogram.size();i++){ - int tally=histogram[i]; - int width=BARWIDTH*tally/maxtally; - cout<<fullbar+BARWIDTH-width<<emptybar+width - <<" ["<<setw(11)<<low+(double)i/nbins*(high-low)<<" - "<<setw(11)<<low+(double)(i+1)/nbins*(high-low)<<")]"[i==(int)histogram.size()-1] - <<" ["<<tally<<"]"<<endl; + char fullbar[BARWIDTH + 1]; + memset(fullbar, '#', BARWIDTH); + fullbar[BARWIDTH] = '\0'; + char emptybar[BARWIDTH + 1]; + memset(emptybar, ' ', BARWIDTH); + emptybar[BARWIDTH] = '\0'; + + for (size_t i = 0; i < histogram.size(); i++) { + int64_t tally = histogram[i]; + int64_t width = BARWIDTH * tally / maxtally; + char terminator = ")]"[i == histogram.size() - 1]; + std::cout << fullbar + BARWIDTH - width << emptybar + width + << " [" << std::setw(11) << low + (double)i / nbins * (high - low) << " - " + << std::setw(11) << low + (double)(i + 1) / nbins * (high - low) << terminator + << " [" << tally << "]" << std::endl; } } |