Skip to content

Instantly share code, notes, and snippets.

@thadeuluiz
Last active August 29, 2015 14:20
Show Gist options
  • Save thadeuluiz/b21a3003b51c3a343c3b to your computer and use it in GitHub Desktop.
Save thadeuluiz/b21a3003b51c3a343c3b to your computer and use it in GitHub Desktop.
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
class Animal;
class AnimalKingdom; //Contains all known animals
class AnimalSet; //All known animals that share a property
ostream& operator<<(ostream&, const Animal&);
istream& operator>>(istream&, Animal&);
class Animal {
public:
static const char DELIMITER = ';';
bool has_attribute(const string& attribute) const {
return attributes.find(attribute) != attributes.end();
};
string name;
set<string> attributes;
};
//serialized inputs and outputs
ostream& operator<<(ostream& os, const Animal& animal){
os << animal.name << Animal::DELIMITER;
for(auto attribute: animal.attributes)
os << attribute << Animal::DELIMITER;
return os;
}
istream& operator>>(istream& is, Animal& animal){
string line;
getline (is, line);
stringstream linestream{line};
getline( linestream, animal.name, Animal::DELIMITER );
animal.attributes.clear();
for( string attr; getline(linestream, attr, Animal::DELIMITER); )
animal.attributes.insert(attr);
return is;
}
class AnimalKingdom{
public:
AnimalKingdom(string t_ifile_name, string t_ofile_name=""):
ifile_name{t_ifile_name}, ofile_name{t_ofile_name}{
ifstream animals_record{ifile_name};
for(Animal animal; animals_record >> animal;){
animals.push_back(animal);
}
};
~AnimalKingdom(){
if(!ofile_name.empty()){
ofstream animal_record{ofile_name};
for(auto& animal : animals)
animal_record << animal << endl;
}
};
string ifile_name, ofile_name;
vector<Animal> animals;
};
class AnimalSet{
public:
size_t count() const {
return filtered_animals.size();
};
string most_common_attribute() const {
map <string, int> attribute_frequency;
for(auto filtered_animal_p: filtered_animals )
for(auto attribute: filtered_animal_p->attributes){
if(filtered_attributes.find(attribute) == filtered_attributes.end()) //attribute is not within current filter
++attribute_frequency[attribute];
}
int max = 0;
string most_frequent;
for(auto pair = attribute_frequency.begin(); pair!=attribute_frequency.end(); ++pair)
if(pair->second > max) {
most_frequent = pair->first;
max = pair->second;
}
return most_frequent;
};
AnimalSet filter_with(const string& attribute, bool positive = true) {
AnimalSet new_set;
new_set.filtered_attributes = filtered_attributes;
if(positive) new_set.filtered_attributes.insert(attribute);
copy_if(filtered_animals.begin(),
filtered_animals.end(),
back_inserter(new_set.filtered_animals),
[&attribute, positive](const Animal* animal){
return positive == animal->has_attribute(attribute);
});
return new_set;
}
vector<Animal*> filtered_animals;
set<string> filtered_attributes;
};
int main (){
AnimalKingdom kingdom{"animal_kingdom.txt", "animal_kingdom.txt"};
AnimalSet current_set;
transform(kingdom.animals.begin(),
kingdom.animals.end(),
back_inserter(current_set.filtered_animals),
[](Animal& animal){return &animal;});
cout << "Welcome to ANIMAL. Think of an animal and type Y. --> ";
istream_iterator<char> response{cin};
for(;tolower(*response)!='y';++response){
cout << "Ok. type Y when ready. --> ";
};
while(current_set.count() > 1){
string common = current_set.most_common_attribute();
cout << "is your animal: "<< common << "? --> ";
for(char c = tolower(*(++response)); c != 'y' && c != 'n'; c =*++response)
cout << "Oops, i didnt understand that. Type Y/N --> ";
current_set = current_set.filter_with(common, *response=='y');
}
if(current_set.count() == 1){
cout << "is your animal the " << current_set.filtered_animals.front()->name << "? --> ";
for(char c = tolower(*++response); c != 'y' && c != 'n'; c =*++response)
cout << "Oops, i didnt understand that. Type Y/N --> ";
if(tolower(*response) == 'y'){
cout << "Haha!, I knew it!" << endl;
return 0;
}
}
//we dont know this animal
Animal new_animal;
cin.ignore(numeric_limits<streamsize>::max(), '\n'); //clean of '\n's
cout << "Ok, i give up, which animal is it?: ";
getline(cin, new_animal.name);
cout << "Which unique attribute does it have? ";
string new_attribute;
getline(cin, new_attribute);
new_animal.attributes = current_set.filtered_attributes;
new_animal.attributes.insert(new_attribute);
kingdom.animals.push_back(new_animal);//insert into the kingdom
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment