I have a class Test which contains two vectors of a Letter class, a user defined type for which the less-than operator (<) has been implemented. How can I best generate all possible permutations of Test?
class Test
{
vector<Letter> letter_box_a;
vector<Letter> letter_box_b;
}
So if letter_box_a contains the letters A and B and letter_box_b contains C and D the valid permutations of Test would be (AB)(CD), (BA)(CD), (AB)(DC) and (BA)(DC).
Although I am able to brute force it, I was trying to write a better (more elegant/efficient) function which would internally call std::next_permutation on the underlying containers allowing me to do
Test test;
while (test.set_next_permutation())
{
// Do the stuff
}
but it appears to be a bit trickier than I first anticipated. I don't necessarily need an STL solution but would like an elegant solution.
I would think you could do something like
bool Test::set_next_permutation() {
auto &a = letter_box_a, &b = letter_box_b; // entirely to shorten the next line
return std::next_permutation(a.start(), a.end()) || std::next_permutation(b.start(), b.end());
}
(Of course, a while loop will skip the initial permutation in any case. You want a do...while loop instead.)
If you want to use std::next_permutation, you need a nested loop for each vector you are permuting:
std::string s0 = "ab";
std::string s1 = "cd";
do
{
do
{
cout << s0 << "" << s1 << endl;
} while (std::next_permutation(s0.begin(), s0.end()));
} while (std::next_permutation(s1.begin(), s1.end()));
Output:
abcd
bacd
abdc
badc
And, in the class:
class Foo
{
public:
Foo(std::string_view arg_a, std::string_view arg_b)
: a(arg_a)
, b(arg_b)
, last(false)
{ }
void reset_permutations()
{
last = false;
}
bool next_permutation(std::string& r)
{
if (last)
return false;
if (not std::next_permutation(a.begin(), a.end()))
if (not std::next_permutation(b.begin(), b.end()))
last = true;
r = a + b;
return true;
}
private:
std::string a, b;
bool last;
};
int main(int argc, const char *argv[])
{
Foo foo("ab", "cd");
string s;
while (foo.next_permutation(s))
cout << s << endl;
return 0;
}
Related
I am quite new to c++ and I am building a model studying certain mutations in genes. My "genes" are defined as a function of two doubles, a and b. A single gene is saved in a std::pair format. The whole genome consists of four of these genes collected in a std:array.
I perform some changes on the genes and want to write the information in a text file for analysis. The way I have currently implemented this is tedious. I have separate functions (8 in total) which collect the information like g[i].first, g[i[.second etc. for every i in the array. I feel this could be done much more efficiently.
Relevant code:
Declaration of data type:
using gene = std::pair<double, double>;
using genome = std::array<gene, 4>;
Function in which I create a genome called g:
genome Individual::init_Individual()
{
double a1, a2, a3, a4 = -1.0;
double b1, b2, b3, b4 = 0.0;
gene g1{ a1,b1 };
gene g2{ a2,b2 };
gene g3{ a3,b3 };
gene g4{ a4,b4 };
genome g{g1,g2,g3,g4};
return g;
}
Example of collect function:
double get_Genome_a1() { return g[0].first; };
Function in which I write information to a text file:
void Individual::write_Statistics(unsigned int &counter)
{
//Generate output file stream
std::ofstream ofs;
ofs.open("data.txt", std::ofstream::out | std::ofstream::app);
ofs << counter << std::setw(14) << get_Genome_a1() << std::setw(14)
<< get_Genome_a2() << std::setw(14) << get_Genome_b1() <<
std::setw(14) << get_Genome_b2() << "\n";
}
ofs.close();
}
etc, etc. So the final result of my data file in this example looks like this:
1 a1 a2 b1 b2
2 a1 a2 b1 b2
3 a1 a2 b1 b2
etc, etc.
My question:
I am currently storing the two doubles in a std::pair, which I collect in a std::array. Is this an efficient storage mechanism or can this be improved?
Is there a way to directly reference an individual element from my custom data type "genome" using only one function to write every element away in the exact same manner as I am doing now (with fourteen spaces between every element)? Something in pseudocode like: get_Genome() {return g;};, and when you call it you can specify the element like: get_Genome([0].first) which would be the first value stored in the first pair of the array, for example.
Happy to learn, any insight is appreciated.
Your storage is good. Neither pair nor array requires indirect/dynamic allocation, so this is great for cache locality.
As for referencing elements, no, not exactly like that. You could have an enum with members FIRST, SECOND then pass that as another argument to get_Genome. But, honestly, this doesn't seem to me to be worthwhile.
Overall, your approach looks great to me. My only suggestions would be:
Re-use one ofstream
…rather than opening and closing the file for every sample. You should see substantial speed improvements from that change.
You could make one in your main or whatever, and have write_Statistics take a std::ostream&, which would also be more flexible!
Initialise a bit quicker
All those declarations in init_Individual may get optimised, but why take the risk? The following is pretty expressive:
genome Individual::init_Individual()
{
const double a = -1.0;
const double b = 0.0;
return {{a, b}, {a, b}, {a, b}, {a, b}};
}
It's worth noting here that your double initialisations were wrong: you were only initialising a4 and b4; your compiler ought to have warned you about this. But, as shown, we don't need all of those anyway as they [are intended to] have the same values!
Your array looks good, however using std::pair in this situation might make it a bit more tedious. I would create 2 simple classes or structures one to represent a gene and the other to represent your genome. I'd still use array. The class might look something like this:
#include <array>
const int genesPerGenome = 4; // change this to set how many...
struct Gene {
double a_;
double b_;
Gene() = default;
Gene(double a, double b) : a_(a), b_(b) {}
};
struct Genome {
std::array<Gene, genesPerGenome> genome_;
int geneCount_{0};
Genome() = default;
void addGene(const Gene& gene) {
if ( geneCount_ >= genesPerGenome ) return;
genome_[geneCount_++] = gene; // post increment since we added one
}
};
Then I would have a stand alone function that would generate your genome as such:
void generateGenome( Genome& genome ) {
for (int i = 0; i < 4; i++) {
// When looking at your example; I notices that the genes were all
// initialized with [-1.0,0.0] so I used Gene's constructor to init
// them with those values.
Gene gene(-1.0, 0.0);
genome.addGene(gene);
}
}
Then to couple these together, I'll just print them to the console for demonstration. You can then take this approach and apply it to what ever calculations that will be done and then writing the results to a file.
#include <array>
#include <iostream>
int main() {
Genome genome;
generateGenome( genome );
// printing to console here is where you would do your calculations then write to file
for ( int i = 0; i < 4; i++ ) {
if ( i >= genome.geneCount_ ) break; // prevent accessing beyond array bounds
std::cout << (i+1) << " [" << genome.genome_[i].a_ << "," << genome.genome_[i].b_ << "]\n";
}
return 0;
}
-Output- - No calculations, only the initialized values:
1 [-1,0]
2 [-1,0]
3 [-1,0]
4 [-1,0]
Maybe this will help. From here you can write a operartor<<() function that will take an ostream reference object and a const reference to a Genome and from there you should be able to print the entire Genome to file in a single function call.
-Edit-
User t.niese left a comment with a valid point that I had overlooked. I was using a static variable in the addGene() function. This would work okay as long as you are working only with a single Genome, but if you had more than one Genome object, every time you'd call the addGene() function this value would increase and you wouldn't be able to add more than gene to each genome due to the condition of the if statement in the addGene() function.
I had modified the original code above to fix this limitation. Here I removed the static variable and I introduced two new variables; one is a const int that represents how many genes per genome as it will be used to define the size of your array as well as checking against how many genes to add to that genome. The other variable I added is a member variable to the Genome class itself that keeps track of how many genes there are per each Genome object.
Here is an example of what i meant in my comment by overloading the operator [].
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
class Genome {
public:
typedef std::pair<double, double> gene;
private:
double a1 = -1.0, a2 = -1.0, a3 = -1.0, a4 = -1.0;
double b1 = 0.0, b2 = 0.0, b3 = 0.0, b4 = 0.0;
gene g1{ a1,b1 };
gene g2{ a2,b2 };
gene g3{ a3,b3 };
gene g4{ a4,b4 };
public:
Genome() {}
const double operator[] (std::string l) const {
if (l == "a1") {return g1.first;}
else if (l == "b1") {return g1.second;}
else if (l == "a2") {return g2.first;}
else if (l == "b2") {return g2.second;}
else if (l == "a3") {return g3.first;}
else if (l == "b3") {return g3.second;}
else if (l == "a4") {return g4.first;}
else if (l == "b4") {return g4.second;}
else {
throw std::invalid_argument("not valid label");
}
}
void setvalue(std::string l, double x) {
if (l == "a1") {g1.first = x;}
else if (l == "b1") {g1.second = x;}
else if (l == "a2") {g2.first = x;}
else if (l == "b2") {g2.second = x;}
else if (l == "a3") {g3.first = x;}
else if (l == "b3") {g3.second = x;}
else if (l == "a4") {g4.first = x;}
else if (l == "b4") {g4.second = x;}
else {
throw std::invalid_argument("not valid label");
}
}
void write_Statistics(unsigned int counter) {
std::ofstream ofs;
ofs.open("data.txt", std::ofstream::out | std::ofstream::app);
ofs << counter
<< std::setw(14) << (*this)["a1"] << std::setw(14) << (*this)["a2"]
<< std::setw(14) << (*this)["b1"] << std::setw(14) << (*this)["b2"] << "\n";
ofs.close();
}
}
};
I don't know if you may find useful to access to the individual genes by a label instead of an index, but this is what this overload do.
int main(int argc, char **argv) {
Genome a = Genome();
std::cout << a["b1"] << std::endl; #this prints 0
a.setvalue("b2", 3.0);
std::cout << a["b2"] << std::endl; #this prints 3
a.write_Statistics(0);
return 0;
}
I am designing a cheat for the game WordBrain. Basically this is just a small program that takes a number of letters, permutes the sequence, then splits the sequence into 'words' which have length attribute, then search my text file to file meaningful permutation to print out.
while (next_permutation(letters.begin(), letters.end())) //loop through possible permutations of the combination
{
int position_marker = 0; //serve specific purpose
for (auto x : substring_collection) //trouble is in this loop
{
string temp;
int k = x.take_length();
try { temp = letters.substr(position_marker, k); }
catch (out_of_range) { cout << "OUT OF RANGE"; }
x.set(temp); //member content does not register change
position_marker += x.take_length(); //also member word_length is 0 now, despite their are no invocation of methods capable of changing it
}
if (all_of(substring_collection.begin(), substring_collection.end(), [&](substring & s) {return !(library.find(s.take_content()) == library.end()); }))
{
for (auto x : substring_collection)
{
cout << x.take_content() + " ";
}
}
}
This is the location the trouble stems from. Basically, substring_collection is a vector<substring>, which contains objects of class substring
Here is how the class looks like:
class substring
{
private:
std::string content;
int word_length;
public:
substring() : content(""), word_length(0) {};
substring(std::string & s, int c) : content(s), word_length(c) {};
void set(std::string & s)
{
content = s;
}
void clear()
{
content.clear();
}
void set_length(int c)
{
word_length = c;
}
void showinfo() const
{
std::cout << "Content is " + content << " Length is : " << word_length;
}
int take_length() const
{
return word_length;
}
std::string take_content() const
{
return content;
}
};
I suspect that the reason the code goes wrong is position_marker, whose value depends on the member 'word_length' of the object substring is set to 0.
In the code prior to this loop, I only the setting method for this member to take data from users' input (from std::cin).
Can you please tell me that is there any hidden mechanism that reset the property, or create brand new objects that I did not aware of?
Also, teachings on coding styles are very welcomed. I just started learning to code so any tips are much appreciated.
for (auto x : substring_collection)
Here, x is of type substring. This is a copy of the element in the vector, and then when you modify it, you only modify the copy, not the original.
You'll have to use a reference to modify the original element in the vector
for (auto& x : substring_collection)
For why word_length is 0, I don't know, it isn't in the code you posted. My guess would be that you resized the vector, which called the default constructor of substring, which set word_length to 0.
I want to remove elements from a std::list with linear complexity (going through each element in the list only once). I need to do so depending on the value of a variable in the stack:
int somevalue= 5;
int count=0;
mylist.remove_if(
[](MyStructure* s)
{
if (s->somefield==somevalue)
{
count++;
return true;
}
else
return false;
});
Of course, this doesn't work - somevalue is a variable in the stack.
I've tried using template functions, only to realize (after illegal operation on bound member function expression) you can't really use them in this situation. I know I need to make a closure somehow, so I've read this question, but I can't use C++0x yet and I failed to adapt the other answer for my usecase, as I don't really understand if there's some magic to operator.
Alternatively, is there some way to remove an element from a list given the current position of an iterator (without going through the whole list again to find the element)?
In terms of the lambda expression (a c++11 feature), you can capture the somevalue by value like this: [somevalue](...) {...}
You need to capture the variable in the sample code:
int somevalue= 5;
mylist.remove_if( [somevalue](MyStructure* s){ s->somefield==somevalue });
If no C++11 could be used you need to make the functor yourself:
// For static constant check
template <int CheckValue>
struct Equal {
operator()(const MyStructure* s) { return s->somefield == CheckValue; }
};
mylist.remove_if(Equal<5>);
..or..
// For dynamic constant check as the sample code
struct Equal {
Equal(int check_value) : m_check_value(check_value) {}
operator()(const MyStructure* s) { return s->somefield == m_check_value; }
private:
int m_check_value;
};
mylist.remove_if(Equal(somevalue));
You must capture somevalue in your lamdba expression to use it:
Example (live here) :
struct MyStructure
{
int somefield;
};
int main(int argc, char** argv) {
std::list<MyStructure> my_list = { { 1 }, { 2 }, { 1 }, { 3 }, { 2 }, { 1 } };
int somevalue = 2;
my_list.remove_if( [somevalue](MyStructure s){ return s.somefield == somevalue; });
// ^^^^^^
// Capture
for(auto& s : my_list)
std::cout << s.somefield << " ";
return 0;
}
Iterate on the elements to identify which one you want to remove. Use erase to remove the identified elements and continue to iterate from the returned iterator.
Something like that:
int somevalue=5;
std::list<MyStructure*> myList;
// ...
std::list<MyStructure*>::iterator it=myList.begin();
while(it!=myList.end())
{
if ((*it)->somefield==somevalue)
{
it = myList.erase(it);
}
else
{
++it;
}
}
I tried STL sample program using "map".
http://ideone.com/LB8xvh
#include <iostream>
#include <map>
#include <cstring>
using namespace std;
class ItemName
{
char name[80];
public:
ItemName(char *s) { strcpy(name, s); }
char *get() { return name; }
};
bool operator<(ItemName a, ItemName b)
{
return strcmp(a.get(), b.get()) < 0;
}
class ItemObj
{
char str[80];
public:
ItemObj(char *s) { strcpy(str, s); }
char *get() { return str; }
};
char itemdata[][80] = {
"potion", "heal HP",
"key", "unlock a door",
"lamp", "light",
};
int main() {
map<ItemName, ItemObj> items;
for(int i=0; i<3; i++) {
items.insert(
pair<ItemName, ItemObj>(
ItemName(itemdata[i*2]),
ItemObj(itemdata[i*2+1]))); // ***** pair *****
}
map<ItemName, ItemObj>::iterator p;
char str[80];
const int kMaxLoop = 5;
int nLoop = 0;
while(nLoop < kMaxLoop) {
cout << "> ";
cin >> str;
p = items.find(str);
if(p != items.end() ) {
cout << p->second.get() << endl;
} else {
cout << "unknown item." << endl;
}
nLoop++;
}
return 0;
}
In this example, I am not quite sure where the operator "<" is used.
If I comment out the definition of the operator "<", I receive lots of errors.
std::map has a parameter to specify how to compare elements in the map (needed because a map always maintains its contents sorted in order by key). By default, that's std::less<T>.
std::less<T>, in turn, will do the comparison using operator<.
You can create a map of items for which operator< isn't defined, but to do it you need to specify the comparison function/functor explicitly.
That said: your ItemData and ItemObj are both really just doing things that std::string can already do. You could reduce most of the code above to something like this:
std::map<std::string, std::string> items{
{ "potion", "heal HP" },
{ "key", "unlock a door" },
{ "lamp", "light" }
};
It is used internally by the map to place and find entries. Otherwise, find would have to compare the key you supply it against literally every single other entry one by one and you couldn't iterate the map in key order.
Basically, maps efficiently store elements in order. To do that, they have to have some way to know what the order is, and they do that by calling operator< (unless you specify otherwise).
I have a custom class 'team' and one of its attributes is its 'name.' After each 'team' is created, I add it to a vector teamList.
I would like to implement a function that continuously prompts the user for a team name which is not already taken by a team within the teamList. I have the following code:
while (true) {
string newString;
bool flag = true;
getline(cin, newString);
for (int i = 0; i < teamList.size(); i++) {
if (teamList[i].name.compare(newString) == 0) flag = false;
}
if (flag == true) {
return newString;
} else {
cout << "name already taken." << endl;
}
}
However, this code is really ugly; is there a better way to check? Also, a more general question- faced with an issue of ugly code (like this one), what kinds of steps can I take to find a new, cleaner implementation? Thanks.
I would use std::set, which deals with duplicates for you. As an example, you can see that the class is sorted by the string member, and when three are inserted in main, only two stay because two of the insertions have the same string, so they are treated equal.
#include <iostream>
#include <set>
#include <string>
struct SetThing {
SetThing(int value, const std::string &value2) : i(value), s(value2){}
int i;
std::string s;
bool operator<(const SetThing &other) const {
return s < other.s;
}
};
int main() {
std::set<SetThing> s;
s.insert(SetThing(5, "abc"));
s.insert(SetThing(4, "def"));
s.insert(SetThing(6, "abc"));
std::cout << s.size();
}
Now for inserting, you can just reprompt while the second member of the returned pair is false:
do {
//get input
} while (!teamList.insert(somethingBasedOnInput).second);
define an equality operator in team that can compare a team to a string:
bool team::operator==(string s) const
{
return(s==name);
}
Then you can use find:
vector<team>::const_iterator itr = find(teamList.begin(), teamList.end(),
newString);
if(itr!=league.end())
cout << "name already taken" << endl;