Thanks.
I wanted to see how conventional C++17 code fares against the C++20
Range-based pipeline stuff in the linked to article
https://medium.com/@vgasparyan1995/a-little-bit-of-code-c-20-ranges-c6a6f7eae401
So the code below is what I came up with. It relies on two of my own
libraries for some small stuff that avoids a details mess.
To me this conventional code is easier to read and to reason about than
the Ranges code, but to the author of that article it's evidently
opposite. I suspect that most of those who love Ranges are of a
mathematical inclination, and that it reminds them of functional
programming. Maybe.
--------------------------------------------------------
// * ASCII text.
#include <cppx-core-language/all.hpp> //
https://github.com/alf-p-steinbach/cppx-core-language
#include <cpp/all.hpp> //
https://github.com/alf-p-steinbach/Cpp-Header-Collections
namespace app {
$use_std( cin, cout, endl, quoted, string, string_view, vector, min );
template< class Key, class Value > using Map_ =
std::unordered_map<Key, Value>;
$use_cppx( Truth, Size, Index, hopefully, fail, span_of, string_to_ );
namespace ascii = cppx::ascii;
using namespace cppx::syntax; // String assembly via
"<<".
auto sans_punctuation( const string_view& s )
-> string
{
string result;
for( const char ch: s ) {
if( not ascii::is_punctuation( ch ) ) {
result += ch;
}
}
return result;
}
auto words_and_counts()
-> auto
{
Map_<string, Size> result;
using In_it = std::istream_iterator<string>;
for( const string& s: span_of( In_it( cin ), In_it() ) ) {
const string word = ascii::to_lowercase( sans_punctuation(
s ) );
if( word.length() != 0 ) {
++result[word];
}
}
return result;
}
struct Word_info { string text; Size count; };
auto order_by_decreasing_counts( const Word_info& a, const
Word_info& b )
-> Truth
{ return a.count > b.count; }
void run( const vector<string_view>& command_parts )
{
hopefully( command_parts.size() == 2 )
or fail( "Usage: "s << command_parts[0] << " N_ITEMS" );
const Size n = string_to_<Size>( command_parts[1] );
vector<Word_info> sorted;
for( const auto& pair: words_and_counts() ) {
sorted.push_back( {pair.first, pair.second} );
}
sort( $items_of( sorted ), order_by_decreasing_counts );
$repeat_times( min<Size>( n, sorted.size() ) ) {
cout << _i + 1 << ": "
<< quoted( sorted[_i].text ) << ' ' <<
sorted[_i].count << " time(s)"
<< endl;
}
}
} // namespace app
auto main( int n_args, char** args )
-> int
{
$use_std( vector, string_view, exception, cerr, endl );
try {
app::run( vector<string_view>( args, args + n_args ) );
return EXIT_SUCCESS;
} catch( const exception& x ) {
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
--------------------------------------------------------
- Alf