#include #include #include #include #include #include #include using std::cin; using std::cout; using std::endl; using std::ostream; using std::string; using std::vector; using std::unordered_map; using std::pair; namespace cs427_527 { /** * Folds all values between the given delimiter in the given range * and outputs them through the given iterator. * * @param IIter an input iterator type * @param OIter an output iterator type * @param T the type of the delimiter * @param Op a type callable with U and the iterators' value type * @param U the type of the value to fold * @param start an iterator at the beginning of the range * @param end an iterator past the end of the range * @param out an output iteratoe * @param delimiter the delimiter * @param f the fold function * @param init the initial value for the fold function */ template void split(IIter start, IIter end, OIter out, const T& delimiter, Op f, const U& init); /** * Outputs all the indices in the given range where the given key is found. * * @param IIter a random-access input iterator type * @param OIter an output iterator type * @param T a type that supports equality comparison * @param start an iterator at the beginning of the range to search * @param end an iterator past the end of the range to search * @param out an output iterator * @param key the value to search for matches of */ template void find_indices(IIter start, IIter end, OIter out, const T& key); } namespace std { ostream& operator<<(ostream& os, const pair& p); } int main(int argc, char **argv) { unordered_map< string, pair< unordered_map< string, int >, vector< string > > > venues; string line; while (std::getline(cin, line)) { // split line into vector containing fields vector fields; cs427_527::split(line.begin(), line.end(), std::back_inserter(fields), '|', [](auto& s, const auto& elt) { s += elt; }, string{}); // make sure everything was read correctly if (fields.size() == 8) { // get team names and venue vector teams = {fields[2], fields[4]}; string venue = fields[7]; // for both teams.. for_each(teams.begin(), teams.end(), [&](const auto& t) { // if first time we've seen it, add it if (venues.count(t) == 0) { venues[t] = std::make_pair(unordered_map{ {venue, 1} }, vector{venue}); } else { // otherwise get its map and add/increment venue auto& counts = venues[t].first; if (counts.count(venue) == 0) { counts[venue] = 1; } else { counts[venue]++; } // add venue to sequential list venues[t].second.push_back(venue); } }); } } vector< pair< string, string > > home_venues; // for each entry in the map through map for (auto& entry : venues) { // get venue->count map and sequence of venues auto& counts = entry.second.first; auto& venues = entry.second.second; // for each venue that a team played in 3 or more times... for (auto& venue_entry : counts) { auto& venue_name = venue_entry.first; auto& count = venue_entry.second; if (count >= 3) { // ... get indices in venue sequence to check for non-consecutive vector gameIndices; cs427_527::find_indices(venues.begin(), venues.end(), std::back_inserter(gameIndices), venue_name); if (gameIndices[count - 1] - gameIndices[0] >= count) { // non-consecutive; this is a potential home site home_venues.push_back(std::make_pair(entry.first, venue_name)); } } } } std::sort(home_venues.begin(), home_venues.end(), [&](auto& p1, auto& p2) { return p1.first < p2.first; }); std::copy(home_venues.begin(), home_venues.end(), std::ostream_iterator& >{cout, "\n"}); } namespace cs427_527 { template void split(IIter start, IIter end, OIter out, const T& delimiter, Op f, const U& init) { if (start == end) { return; } // initial value for fold auto curr = init; for (auto i = start; i != end; i++) { if (*i == delimiter) { // see a delimiter -- output previous value and start new one *out = curr; out++; curr = init; } else { // fold current value in f(curr, *i); } } // output last value *out = curr; } template void find_indices(IIter start, IIter end, OIter out, const T& key) { for (auto i = start; i != end; i++) { if (*i == key) { // found a match -- output it (this is where we need random access) *out = i - start; out++; } } } } namespace std { ostream& operator<<(ostream& os, const pair& p) { os << p.first << "|" << p.second; return os; } }