This is my first time using this site so sorry for any bad formatting or weird formulations, I'll try my best to conform to the rules on this site but I might do some misstakes in the beginning.
I'm right now working on an implementation of some different bin packing algorithms in C++ using the STL containers. In the current code I still have some logical faults that needs to be fixed but this question is more about the structure of the program. I would wan't some second opinion on how you should structure the program to minimize the number of logical faults and make it as easy to read as possible. In it's current state I just feel that this isn't the best way to do it but I don't really see any other way to write my code right now.
The problem is a dynamic online bin packing problem. It is dynamic in the sense that items have an arbitrary time before they will leave the bin they've been assigned to.
In short my questions are:
How would the structure of a Bin packing algorithm look in C++?
Is STL containers a good tool to make the implementation be able to handle inputs of arbitrary lenght?
How should I handle the containers in a good, easy to read and implement way?
Some thoughts about my own code:
Using classes to make a good distinction between handling the list of the different bins and the list of items in those bins.
Getting the implementation as effective as possible.
Being easy to run with a lot of different data lengths and files for benchmarking.
#include <iostream>
#include <fstream>
#include <list>
#include <queue>
#include <string>
#include <vector>
using namespace std;
struct type_item {
int size;
int life;
bool operator < (const type_item& input)
{
return size < input.size;
}
};
class Class_bin {
double load;
list<type_item> contents;
list<type_item>::iterator i;
public:
Class_bin ();
bool operator < (Class_bin);
bool full (type_item);
void push_bin (type_item);
double check_load ();
void check_dead ();
void print_bin ();
};
Class_bin::Class_bin () {
load=0.0;
}
bool Class_bin::operator < (Class_bin input){
return load < input.load;
}
bool Class_bin::full (type_item input) {
if (load+(1.0/(double) input.size)>1) {
return false;
}
else {
return true;
}
}
void Class_bin::push_bin (type_item input) {
int sum=0;
contents.push_back(input);
for (i=contents.begin(); i!=contents.end(); ++i) {
sum+=i->size;
}
load+=1.0/(double) sum;
}
double Class_bin::check_load () {
return load;
}
void Class_bin::check_dead () {
for (i=contents.begin(); i!=contents.end(); ++i) {
i->life--;
if (i->life==0) {
contents.erase(i);
}
}
}
void Class_bin::print_bin () {
for (i=contents.begin (); i!=contents.end (); ++i) {
cout << i->size << " ";
}
}
class Class_list_of_bins {
list<Class_bin> list_of_bins;
list<Class_bin>::iterator i;
public:
void push_list (type_item);
void sort_list ();
void check_dead ();
void print_list ();
private:
Class_bin new_bin (type_item);
bool comparator (type_item, type_item);
};
Class_bin Class_list_of_bins::new_bin (type_item input) {
Class_bin temp;
temp.push_bin (input);
return temp;
}
void Class_list_of_bins::push_list (type_item input) {
if (list_of_bins.empty ()) {
list_of_bins.push_front (new_bin(input));
return;
}
for (i=list_of_bins.begin (); i!=list_of_bins.end (); ++i) {
if (!i->full (input)) {
i->push_bin (input);
return;
}
}
list_of_bins.push_front (new_bin(input));
}
void Class_list_of_bins::sort_list () {
list_of_bins.sort();
}
void Class_list_of_bins::check_dead () {
for (i=list_of_bins.begin (); i !=list_of_bins.end (); ++i) {
i->check_dead ();
}
}
void Class_list_of_bins::print_list () {
for (i=list_of_bins.begin (); i!=list_of_bins.end (); ++i) {
i->print_bin ();
cout << "\n";
}
}
int main () {
int i, number_of_items;
type_item buffer;
Class_list_of_bins bins;
queue<type_item> input;
string filename;
fstream file;
cout << "Input file name: ";
cin >> filename;
cout << endl;
file.open (filename.c_str(), ios::in);
file >> number_of_items;
for (i=0; i<number_of_items; ++i) {
file >> buffer.size;
file >> buffer.life;
input.push (buffer);
}
file.close ();
while (!input.empty ()) {
buffer=input.front ();
input.pop ();
bins.push_list (buffer);
}
bins.print_list ();
return 0;
}
Note that this is just a snapshot of my code and is not yet running properly
Don't wan't to clutter this with unrelated chatter just want to thank the people who contributed, I will review my code and hopefully be able to structure my programming a bit better
How would the structure of a Bin packing algorithm look in C++?
Well, ideally you would have several bin-packing algorithms, separated into different functions, which differ only by the logic of the algorithm. That algorithm should be largely independent from the representation of your data, so you can change your algorithm with only a single function call.
You can look at what the STL Algorithms have in common. Mainly, they operate on iterators instead of containers, but as I detail below, I wouldn't suggest this for you initially. You should get a feel for what algorithms are available and leverage them in your implementation.
Is STL containers a good tool to make the implementation be able to handle inputs of arbitrary length?
It usually works like this: create a container, fill the container, apply an algorithm to the container.
Judging from the description of your requirements, that is how you'll use this, so I think it'll be fine. There's one important difference between your bin packing algorithm and most STL algorithms.
The STL algorithms are either non-modifying or are inserting elements to a destination. bin-packing, on the other hand, is "here's a list of bins, use them or add a new bin". It's not impossible to do this with iterators, but probably not worth the effort. I'd start by operating on the container, get a working program, back it up, then see if you can make it work for only iterators.
How should I handle the containers in a good, easy to read and implement way?
I'd take this approach, characterize your inputs and outputs:
Input: Collection of items, arbitrary length, arbitrary order.
Output: Collection of bins determined by algorithm. Each bin contains a collection of items.
Then I'd worry about "what does my algorithm need to do?"
Constantly check bins for "does this item fit?"
Your Class_bin is a good encapsulation of what is needed.
Avoid cluttering your code with unrelated stuff like "print()" - use non-member help functions.
type_item
struct type_item {
int size;
int life;
bool operator < (const type_item& input)
{
return size < input.size;
}
};
It's unclear what life (or death) is used for. I can't imagine that concept being relevant to implementing a bin-packing algorithm. Maybe it should be left out?
This is personal preference, but I don't like giving operator< to my objects. Objects are usually non-trivial and have many meanings of less-than. For example, one algorithm might want all the alive items sorted before the dead items. I typically wrap that in another struct for clarity:
struct type_item {
int size;
int life;
struct SizeIsLess {
// Note this becomes a function object, which makes it easy to use with
// STL algorithms.
bool operator() (const type_item& lhs, const type_item& rhs)
{
return lhs.size < rhs.size;
}
}
};
vector<type_item> items;
std::sort(items.begin, items.end(), type_item::SizeIsLess);
Class_bin
class Class_bin {
double load;
list<type_item> contents;
list<type_item>::iterator i;
public:
Class_bin ();
bool operator < (Class_bin);
bool full (type_item);
void push_bin (type_item);
double check_load ();
void check_dead ();
void print_bin ();
};
I would skip the Class_ prefix on all your types - it's just a bit excessive, and it should be clear from the code. (This is a variant of hungarian notation. Programmers tend to be hostile towards it.)
You should not have a class member i (the iterator). It's not part of class state. If you need it in all the members, that's ok, just redeclare it there. If it's too long to type, use a typedef.
It's difficult to quantify "bin1 is less than bin2", so I'd suggest removing the operator<.
bool full(type_item) is a little misleading. I'd probably use bool can_hold(type_item). To me, bool full() would return true if there is zero space remaining.
check_load() would seem more clearly named load().
Again, it's unclear what check_dead() is supposed to accomplish.
I think you can remove print_bin and write that as a non-member function, to keep your objects cleaner.
Some people on StackOverflow would shoot me, but I'd consider just making this a struct, and leaving load and item list public. It doesn't seem like you care much about encapsulation here (you're only need to create this object so you don't need do recalculate load each time).
Class_list_of_bins
class Class_list_of_bins {
list<Class_bin> list_of_bins;
list<Class_bin>::iterator i;
public:
void push_list (type_item);
void sort_list ();
void check_dead ();
void print_list ();
private:
Class_bin new_bin (type_item);
bool comparator (type_item, type_item);
};
I think you can do without this class entirely.
Conceptually, it represents a container, so just use an STL container. You can implement the methods as non-member functions. Note that sort_list can be replaced with std::sort.
comparator is too generic a name, it gives no indication of what it compares or why, so consider being more clear.
Overall Comments
Overall, I think the classes you've picked adequately model the space you're trying to represent, so you'll be fine.
I might structure my project like this:
struct bin {
double load; // sum of item sizes.
std::list<type_item> items;
bin() : load(0) { }
};
// Returns true if the bin can fit the item passed to the constructor.
struct bin_can_fit {
bin_can_fit(type_item &item) : item_(item) { }
bool operator()(const bin &b) {
return item_.size < b.free_space;
}
private:
type_item item_;
};
// ItemIter is an iterator over the items.
// BinOutputIter is an output iterator we can use to put bins.
template <ItemIter, BinOutputIter>
void bin_pack_first_fit(ItemIter curr, ItemIter end, BinOutputIter output_bins) {
std::vector<bin> bins; // Create a local bin container, to simplify life.
for (; curr != end; ++curr) {
// Use a helper predicate to check whether the bin can fit this item.
// This is untested, but just for an idea.
std::vector<bin>::iterator bin_it =
std::find_if(bins.begin(), bins.end(), bin_can_fit(*curr));
if (bin_it == bins.end()) {
// Did not find a bin with enough space, add a new bin.
bins.push_back(bin);
// push_back invalidates iterators, so reassign bin_it to the last item.
bin_it = std::advance(bins.begin(), bins.size() - 1);
}
// bin_it now points to the bin to put the item in.
bin_it->items.push_back(*curr);
bin_it->load += curr.size();
}
std::copy(bins.begin(), bins.end(), output_bins); // Apply our bins to the destination.
}
void main(int argc, char** argv) {
std::vector<type_item> items;
// ... fill items
std::vector<bin> bins;
bin_pack_first_fit(items.begin(), items.end(), std::back_inserter(bins));
}
Some thoughts:
Your names are kinda messed up in places.
You have a lot of parameters named input, thats just meaningless
I'd expect full() to check whether it is full, not whether it can fit something else
I don't think push_bin pushes a bin
check_dead modifies the object (I'd expect something named check_*, to just tell me something about the object)
Don't put things like Class and type in the names of classes and types.
class_list_of_bins seems to describe what's inside rather then what the object is.
push_list doesn't push a list
Don't append stuff like _list to every method in a list class, if its a list object, we already know its a list method
I'm confused given the parameters of life and load as to what you are doing. The bin packing problem I'm familiar with just has sizes. I'm guessing that overtime some of the objects are taken out of bins and thus go away?
Some further thoughts on your classes
Class_list_of_bins is exposing too much of itself to the outside world. Why would the outside world want to check_dead or sort_list? That's nobodies business but the object itself. The public method you should have on that class really should be something like
* Add an item to the collection of bins
* Print solution
* Step one timestep into the future
list<Class_bin>::iterator i;
Bad, bad, bad! Don't put member variables on your unless they are actually member states. You should define that iterator where it is used. If you want to save some typing add this: typedef list::iterator bin_iterator and then you use bin_iterator as the type instead.
EXPANDED ANSWER
Here is my psuedocode:
class Item
{
Item(Istream & input)
{
read input description of item
}
double size_needed() { return actual size required (out of 1) for this item)
bool alive() { return true if object is still alive}
void do_timestep() { decrement life }
void print() { print something }
}
class Bin
{
vector of Items
double remaining_space
bool can_add(Item item) { return true if we have enough space}
void add(Item item) {add item to vector of items, update remaining space}
void do_timestep() {call do_timestep() and all Items, remove all items which indicate they are dead, updating remaining_space as you go}
void print { print all the contents }
}
class BinCollection
{
void do_timestep { call do_timestep on all of the bins }
void add(item item) { find first bin for which can_add return true, then add it, create a new bin if neccessary }
void print() { print all the bins }
}
Some quick notes:
In your code, you converted the int size to a float repeatedly, that's not a good idea. In my design that is localized to one place
You'll note that the logic relating to a single item is now contained inside the item itself. Other objects only can see whats important to them, size_required and whether the object is still alive
I've not included anything about sorting stuff because I'm not clear what that is for in a first-fit algorithm.
This interview gives some great insight into the rationale behind the STL. This may give you some inspiration on how to implement your algorithms the STL-way.
Related
I have a big problem..I'm beginner with programming and I try to make a program in C++ for a football league ranking which have to sort the teams depending on their points.
Can someone help with an idea, please?
I created a struct for the teams with the name and the number of points.
How can I sort the teams?P.S. Sorry for my bad English.
This is my code:
#include <iostream>
#include <algorithm>
using namespace std;
//I created a struct for the team.
struct team
{
char name;
int pct;
}v[20];
int main()
{ int i,sw,aux;
for(i=1;i<=4;i++)//read the names
{
cout<<"Team "<<i<<endl;
cin>>v[i].name;
}
for(i=1;i<=4;i++)//get the points
{
cout<<"Team "<<v[i].name<<" points"<<endl;
cin>>v[i].pct;
}
//bubble sort(not working)
do
{
sw=0;
for(i=1;i<=4;i++)
{
if(v[i].pct<v[i+1].pct)
aux=v[i].pct;
v[i].pct=v[i+1].pct;
v[i+1].pct=aux;
sw=1;
}
}while(sw==1);
for(i=1;i<=4;i++)
{
cout<<v[i].pct<<endl;
}
return 0;
}
You need to modify your sort part like this. Assuming you are sorting in desc order.
do
{
sw=0;
for(i=1;i<4;i++) //< not <= ,because in case of the last element you wont have any other element after it to compare
{
if(v[i].pct<v[i+1].pct) // use curly brace as you want all 4 following lines to be executed when its true
{
aux=v[i]; //swap entire struct not just one variable
v[i]=v[i+1];
v[i+1]=aux;
sw=1;
}
}
}while(sw==1);
Also you might need to edit variable type of team name as it can be string.
As you are using C++ there is a one liner function that you can use to sort
//#include<algorithm>
//define comparator function
bool cmp(team a, team b)
{
return a.pct < b.pct;
}
sort(v+1,v+4+1,cmp);
Also you can simply write the comparator inside the struct and then use the sort function:
struct team
{
char name;
int pct;
bool operator<(team other) const
{
return pct > other.pct;
}
}v[20];
sort(v+1,v+4+1);
I'm curious about why you include algorithm but do not use any of it. Do you know STL? Since you include algorithm, I guess you may know some simple functions such as swap, sort and copy. They are easy to use, you just need to type one line instead of writing a bubble sort by yourself. Before you use the sort function, you should define which order can take effect on these teams. Just like this:
bool compareTeams(const Team &t1, const Team &t2) {
if (t1.getScore() == t2.getScore()) {
return t1.getName() < t2.getName();
}
else {
return t1.getScore() < t2.getScore();
}
}
The code above defines a direction we consider to sort the teams, first we sort them by scores, if both of the scores are equal, then we sort them by their names.
Finally We can use the sort function which is ready-made in STL. Now the order we defined can be used. (I guess the array v[] stands for the teams. Am I right?)
std::sort(v, v + 20, compareTeams);
I'm trying to understand how I should implement an associative array which gives constant time for search operations, right now my implementation looks like this:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template <class Key, class Value> class Dict {
private:
typedef struct Item {
Value value;
Key key;
} Item;
vector<Item> _data;
public:
void clear() {
_data.clear();
}
long size() {
return _data.size();
}
bool is_item(Key key) {
for (int i = 0; i < size(); i++) {
if (_data[i].key == key) return true;
}
return false;
}
bool add_item(Key key, Value value) {
if (is_item(key)) return false;
Item new_item;
new_item.key = key;
new_item.value = value;
_data.push_back(new_item);
return true;
}
Value &operator[](Key key) {
for (int i = 0; i < size(); i++) {
if (_data[i].key == key) return _data[i].value;
}
long idx = size();
Item new_item;
new_item.key = key;
_data.push_back(new_item);
return _data[idx].value;
}
Key get_key(long index) {
if (index < 0) index = 0;
for (int i = 0; i < size(); i++)
if (i == index) return _data[i].key;
return NULL;
}
Value &operator[](long index) {
if (index < 0) index = 0;
for (int i = 0; i < size(); i++) {
if (i == index) return _data[i].value;
}
return _data[0].value;
}
};
A simple test for this:
class Foo {
public:
Foo(int value) {
_value = value;
}
int get_value() {
return _value;
}
void set_value(int value) {
_value = value;
}
private:
int _value;
};
template <class Key, class Value> void print_dict(Dict<Key, Value> &dct) {
if (!dct.size()) {
printf("Empty Dict");
}
for (int i = 0; i < dct.size(); i++) {
printf("%d%s", dct[dct.get_key(i)], i == dct.size() - 1 ? "" : ", ");
}
printf("\n");
}
int main(int argc, char *argv[]) {
printf("\nDict tests\n------------\n");
Dict<string, int> dct;
string key1("key1");
string key2("key2");
string key3("key3");
dct["key1"] = 100;
dct["key2"] = 200;
dct["key3"] = 300;
printf("%d %d %d\n", dct["key1"], dct["key2"], dct["key3"]);
printf("%d %d %d\n", dct[key1], dct[key2], dct[key3]);
print_dict(dct);
dct.clear();
print_dict(dct);
Dict<Foo *, int> dct2;
Foo *f1 = new Foo(100);
Foo *f2 = new Foo(200);
dct2[f1] = 101;
dct2[f2] = 202;
print_dict(dct2);
}
Here's the thing, right now the search operation is linear time and I'd like it to become constant time and I'm wondering about a simple/lightweight way to achieve this.
I've seen hashtables are a possible option but I'd prefer not having to implement a hash function per object. Maybe something similar to an unordered_map... dunno.
Could anyone give some ideas or maybe providing a simple lightweight implementation of what I'm trying to achieve here?
In this fictional example I'm using std::vector to avoid making the question bigger and more complex than what it is but my the real use-case won't be using the STL at all (ie: i'll be coding my own custom implementation of std::vector)
CONSTRAINTS
The reason of not using the STL at all is not because that implementation is not good (fast,generic,full-featured) enough but more because is quite heavy for my size-constrained projects (final exe <=65536bytes). Even this small implementation of the STL is actually quite big to be used as it is
I don't need a full implementation of an associative array but just providing the interface i've already implemented above (main problem being the linear-time search)
I don't care about inserting/deleting methods being slow but definitely I'd like the search/lookup being near to constant time
I guess I'd need to convert the above implementation in an associative array using a hash table but I'm unsure about the relevant implementation details (which hash functions per object, which table size, ...)
Let me address some issues you've raised in your question.
Here's the thing, right now the search operation is linear time and I'd like it to become constant time and I'm wondering about a simple/lightweight way to achieve this.
A simple lightweight way to achieve this, i.e., to have an associative array (a.k.a. key-value-store), is to use one provided by the standard library.
You are coding in a recent version of C++, you are in the lucky position that the standard library actually provides one that satisfies your constant-time requirements:
http://en.cppreference.com/w/cpp/container/unordered_map
The implementation of the data structures shipped as part of a standard library of any decent compiler these days, are probably better than anything you could come up with. (Or why did you ask for give me the code?).
I've seen hashtables are a possible option but I'd prefer not having to implement a hash function per object. Maybe something similar to an unordered_map... dunno.
A std::unordered_map actually is a hash table, and as you can see in the docs, it takes a hash function. As you can see written in the docs there are lots of specializations for lots of types already available, that can help you derive a custom hash function for your custom object types:
http://en.cppreference.com/w/cpp/utility/hash
Could anyone give some ideas or maybe providing a simple lightweight implementation of what I'm trying to achieve here?
Just have a look at the example code to std::unordered_map to see how it's used. If you worry about performance, don't forget to measure. If you really want to consume some input on implementation of hash tables, I liked these talks on the Python dictionary:
https://www.youtube.com/watch?v=C4Kc8xzcA68
https://www.youtube.com/watch?v=p33CVV29OG8
Also have a look at the wikipedia page (if you haven't already):
https://en.wikipedia.org/wiki/Associative_array
In this fictional example I'm using std::vector to avoid making the question bigger and more complex than what it is but my the real use-case won't be using the STL at all (ie: i'll be coding my own custom implementation of std::vector)
Unless you are doing this for educational/recreational purposes, don't do it. Don't be ashamed to base your endeavours on the shoulders of giants. That the standard library wasn't invented in your project is not a problem.
If you want to keep code size small, you should avoid templates as much as possible. At least templates that create non-trivial amounts of code.
For your hash map, that means: stick to one key type and only store void pointers to the values. If you don't want to deal with void* and the casts that go along with it all over in your code, implement one non-template hash map that stores void* as value, with all "no inline" functions. Then create an "all inline" (maybe even all "force inline") wrapper class that uses the void* map internally and just converts T* <-> void*.
If you really really really need different key types, see if you can stick to PODs without padding (memcpy copyable and memcmp comparable). That way you can still use the same hash map class for everything: you just have to tell the map (at runtime) what the key-size is. Then you can copy the keys into the map using memcpy, compare using memcmp and hash them using any hash algorithm that can hash byte sequences (=almost every hash algorithm).
Of course you'll also want to do a lot of other stuff, e.g. avoid inlining any non-trivial functions, avoid C-Runtime library functions, disable exception handling and RTTI etc., but that's a different topic.
Or, maybe just stick to plain C :)
Here's my issue, I would like to call the getters/setters of one of my objects, but not directly, I want to do it by using a std::string.
I found this but it won't work on my case I think it is because my function aren't defined in my main method but in my square class. Also my function are not all defined the same way there's void(std::string) std::string() void(int)...
here's an exemple of what a would like to do.
my object square
#include <map>
#include <functional>
#include <string>
class Square{
private:
std::string name;
int width;
float happinessPoint; //extremly important for your square.
public:
void setName(std::string);
void setWidth(int);
void setHappinessPoint(float);
std::string getName()
int getWidth()
float getHappinnessPoint()
}
and my main
#include "Square.h/cpp"
int main(){
Square square = Square("Roger",2,3.5);
// here in my magicalFunction I ask to the users the new values for my square (all in std::string for now)
vector <std::string> newValueForSquare = magicalFunction();
for (unsigned int i=0; i < newValueForSquare.size(), i++){
//here I have a function which tell me if my std::string
// is in fact a float or an int
// and I would like to call each of my setters one by one to
// sets my Square to some value I asked to the user before all that.
// something like that:
// someFunction("setName","Henry")
}
}
I hope i have been clear it's pretty hard to explain something you don't know how to do. If you want me to be more specific tell me and I'll do what I can.
EDIT: What I want to do is to call for example my square.setName() with a str::string without writting this square.setName in my main.
To call functions, based on a string, you have some choices. Before I list the choices, please search the internet for "C++ factory design pattern".
If-else ladder
Lookup table
Map / Associative array
Hash table
There may be other methods, but the above come to mind.
if-else ladder (a.k.a. switch)
The problem with this method is that the switch statement doesn't work with strings nor text literals. So you'll have to suffice with if statements:
if (string == "Roger")
{
Process_Roger();
}
else if (string == "Felicity")
{
Process_Felicity();
}
else
{
Display_Error_Message();
}
Anytime you need to add a new string, you will have to add another "else if" statement to the ladder. Not only do you have to change the code, but you also have to retest it.
Lookup Table
You will need to understand function pointers for this technique and the map technique. Consider this a prerequisite.
Use a structure for mapping text strings to function pointers:
struct Text_Function_Pointer
{
const char * name;
Function_Pointer p_function;
};
static const Text_Function_Pointer table[] =
{
{"Larry", Process_Larry},
{"Felicity", Process_Felicity},
};
static const unsigned int table_size =
sizeof(table) / sizeof(table[0]);
//...
for (unsigned int i = 0; i < table_size; ++i)
{
if (search_name == table[i].name)
{
// Execute the processing function.
table[i].p_function(search_name);
break;
}
}
An issue with this technique is that all the function pointers must have the same signature. This is true for the map as well.
A nice feature is that the data in the table is constant, so it can be placed in Read-Only Memory.
Also, to add more associations, add an entry to the the table. The search / processing function hasn't changed, so it doesn't need to be tested again.
Map / Associative Array
Prerequisite: Function pointers.
Declare a std::map<std::string, Function_Pointer_Type>. Add your names and functions to the map:
std::map<std::string, Function_Pointer_Type> dispatch_table;
dispatch_table["Roger"] = Process_Roger;
dispatch_table["Felicity"] = Process_Felicity;
dispatch_table["Larry"] = Process_Larry;
//...
// Execute appropriate processing function:
(dispatch_table[search_name])();
One issue with this method is that the std::map data structure needs to be initialized; it can't be directly accessed or loaded from executable code.
Again, all functions must have the same signature.
Hash Table
The idea here is to have an array of function pointers or an array of structures with text & function pointers. Create a hash function that generates a unique array index based on the name string. Use the index to get the function pointer from the array, then execute the function via the function pointer.
Several solutions are available to you. You basically want to parse user input to fill your Square class attribute.
One way is to use the std::stoi family of functions:
std::vector<string> values { "Roger", "2", "3.5" };
std::string name = values[0]; // No problem, two strings
int width = std::stoi(values[1]); // stoi = stringToInt
float happiness = std::stof(values[2]); // stof = stringToFloat
I'm not sure why you'd need the for loop, unless there is something I didn't understand in your question. I'll update my answer accordingly.
Update 1
After reading other answers, I would like to propose my solution to your problem. As stated several times in my comments, this is not an easy answer !
I needed such a class to write a generic test engine, and this is the code I used. It works really well with any type of function (except for routines with a return type of void -- a simple template specialization would solve it though)
# include <functional>
# include <tuple>
template<int ...>
struct seq
{
};
template<int N, int ...S>
struct gens : gens<N - 1, N - 1, S...>
{
};
template<int ...S>
struct gens<0, S...>
{
typedef seq<S...> type;
};
struct callable_base
{
virtual void operator()() = 0;
virtual ~callable_base()
{ }
};
class Task
{
private:
template<class RT, class Functor, class ...Args>
struct functor : public callable_base
{
functor(RT& result, Functor func, Args ...args)
: _ret(result)
{
_func = func;
_args = std::make_tuple(args...);
}
void operator()()
{
_ret = call(typename gens<sizeof...(Args)>::type());
}
template<int ...S>
RT call(seq<S...>)
{
return (_func(std::get<S>(_args)...));
}
private:
std::function<RT(Args...)> _func;
std::tuple<Args...> _args;
RT& _ret;
};
public:
Task()
{
_functor = nullptr;
}
template<class RT, class Functor, class ...Args>
Task(RT& result, Functor func, Args... args)
{
_functor = new functor<RT, Functor, Args...>(result, func, args...);
}
void operator()()
{
(*_functor)();
}
~Task()
{
delete _functor;
}
private:
callable_base *_functor;
};
The idea behind this code is to hide the function signature in the inner class Task::functor and get the return value in the first parameter passed to the Task(...) constructor. I'm giving this code first because I think it might help some people, but also because I think it is an elegant solution to your problem. Bear in mind that to understand most of the code, you need solid C++ knowledge. I'll detail the code in subsequent updates if needed.
Here's how you'd use it:
int main()
{
int retVal;
std::string newName;
std::map<std::string, Task *> tasks {
{"setName", new Task(retVal, &Square::setName, &newName)}
...
}
/* Modify the name however you want */
...
tasks["setname"]();
}
This whole class could be optimized, of course, primarily thanks to C++14 and move semantics, universal references and all, but I kept it simple ~
A major problem is that you have to use pointers if you don't know the values of the parameters at the time you fill the task map. I'm working on another version to simplify this aspect, but I wanted to show you that C++ is not designed to do what you ask simply. Maybe you come from a functional or JS world, in which this would be trivial x)
Update 2
I just wanted to point out that with C++14, you could omit the first 3 structures that are here to help me expand my tuple in an argument list using interger_sequence
Alright, so I've always struggled with this in programming, and now, I'm starting on a very difficult programming assignment and this is suppose to be one of the easier portions of the assignment... but basically, here's what I'm supposed to do (I'll copy and paste the prompt, and then write what it means, just to clarify):
Your first task is to write a template for an accumulator, InOrder, that
accepts a sequence of items via a .put(item) method and returns true or false via a .get() method indicating whether the sequence is in order.
Alright, so it's probably not difficult for some of you, but basically what I'm supposed to do is write the header code for this class, then it uses this method:
// The put method of anAccumulator has been applied
// to all values accessed by interators begin up to end.
template<typename A, typename I>
void
apply(A & anAccumulator, I begin, I end)
{
for (I iter = begin; iter != end; ++iter)
{
anAccumulator.put( *iter);
}
}
and here is what I've got so far for my TInOrder.h header file:
// Declares the class for InOrder.
#include <algorithm>
#include <vector>
#ifndef __INORDER_H_
#define __INORDER_H_
template <typename T>
class InOrder
{
public:
InOrder() : _count(0)
{};
void put(T item)
{
data = item;
while (item < data)
{
yOrder = true;
}
}
bool get()
{
if (yOrder == true)
{
return true;
}
else
{
return false;
}
}
private:
bool yOrder;
bool _count;
T data;
};
#endif
obviously, I've got no clue what I'm doing. But, to my understanding, I'm supposed to use the .put() and .get() methods in some manner without a list, vector, stack, or queue. Here's what my TA wrote to me in an e-mail, I think he better explains it than I do:
I hope this helps. From the instructions in your email it doesn't seem like your class needs to get its input from the command line. You just need to define the .put() method. (i.e) your class doesn't care where the input comes from. Now since your class only gets one input at a time, I'm sure you'll be able to figure out how to tell if the sequence seen so far is in order or not and you don't even need to store all the values seen so far. Do not use a vector, list or any other container for this.
So my real question is: how do you use the .put() method to test whether or not the user input is in order? I'm really struggling to figure all of this out, and I hope someone can help me understand the logic behind it. I know it's supposed to be something involving comparison and overwriting, but not much more than that. An example would be great. I appreciate it so much, thank you!
You just have to keep the old value and compare new item with it.
Assuming that T is default contructible and copyable:
template <typename T>
class InOrder
{
public:
InOrder() : inOrder(true), initialized(false), oldValue() {}
void put(const T& item)
{
if (initialized && item < oldValue) {
inOrder = false;
}
oldValue = item;
initialized = true;
}
bool get() const { return inOrder; }
private:
bool inOrder;
bool initialized;
T oldValue;
};
boost::optional<T> may replace bool initialized; T oldValue;.
I'm working on a problem which requires me to use the STL linked list class to represent a polynomials. I've made a good start on getting the class definition, however I'm a little confused as to where to go next (novice programmer - please excuse my potential ignorance).
class Polynomial
{
public:
Polynomial(); //Default constructor
Polynomial(pair<double,int>); //Specified constructor
void add(Polynomial);
Polynomial multiply(Polynomial);
void print();
private:
list<int> order_terms;
list<double> coeffs;
};
I have two questions:
1) It seems more elegant to store the terms and coefficients as a pair - however I'm unsure how to get that working using the STL list.
2) Regarding the add member function, I'm unsure how to implement it such that I can define a Polynomial and then add terms to it like this:
Polynomial test(pair<3.14,0>);
Polynomial test_2(pair<2,1>);
test.add(test_2);
The main thing I'm having issues with understanding how to access the terms stored in the other object and linking it to the first Polynomial.
Any help greatly appreciated.
EDIT: Code for the add() function - currently not working
void Polynomial::add(const Polynomial& rhs)
{
//Perform some sort of sort here to make sure both lists are correctly sorted
//Traverse the list of terms to see if there's an existing nth order
//term in the list on the left-hand-side polynomial.
list<int>::iterator itr;
list<int>::iterator itl;
for(itr=rhs->terms.begin(); itr!=rhs->terms.end(); itr++)
{
bool match=0;
//See if there's an existing terms, if so add to it
for(itl=terms.begin(); itl!=terms.end(); itl++)
{
if(*itl->second)==*itr->second)
{
*itl->first+=*itr->first;
match = 1;
}
}
//If not, this is the first nth order term so just push it onto the list
if(!match){ terms.push_back(*itr); //Perform the sort again }
}
To use a pair in a list you can do:
list<pair<double, int> > - note the space between the >. It's also nice to do something like
typedef pair<double, int> TermCoeff;
list<TermCoeff> equation;
To sort a list:
list<TermCoeff> equation;
// insert items
equation.sort(coeff_compare);
There are pre-defined comparator functions for a pair in the <utility> header. They compare the first elements and then the second ones if first is equal.
For your second question you should remember that an object of a class can access the member variables of an object of the same class, even if they are private. If you don't leave any gaps in your coefficients (in the constructor fill in missing ones with the second value of the pair set to 0) this means your add method can look like:
Polynomial& Polynomial::add(const Polynomial& rhs) {
// constructor should sort all terms and enforce that all terms are present
// lhs = current object (left hand side of operator)
// rhs = other object (right hand side of operator)
// example: lhs.add(rhs)
list<TermCoeff>::const_iterator rhs_iter = rhs.terms.begin();
list<TermCoeff>::iterator lhs_iter = terms.begin();
while(rhs_iter != rhs.terms.end()) {
if (lhs_iter != terms.end()) {
// add because we aren't at the end of current object's terms
lhs_iter->second += rhs_iter->second;
++lhs_iter;
} else {
// insert because we are at the end of current object's terms
terms.push_back(*rhs_iter);
lhs_iter = terms.end(); // keep the iterator at the end
}
++rhs_iter;
}
return *this;
}
int main (int argc, const char * argv[])
{
list<TermCoeff> first, second;
first.push_back(TermCoeff(0, 0.0)); // empty
first.push_back(TermCoeff(1, 5.0));
first.push_back(TermCoeff(2, 5.0));
second.push_back(TermCoeff(0, 6.0));
second.push_back(TermCoeff(1, 0.0)); // empty
second.push_back(TermCoeff(2, 8.0));
second.push_back(TermCoeff(3, 9.0));
Polynomial first_eq(first);
Polynomial second_eq(second);
first_eq.add(second_eq);
first_eq.print();
return 0;
}
Note that I returned a reference to the current object. This is a nice thing to do in an addition method because then you can chain additions:
first.add(second).add(third);
or
first.add(second.add(third));
Others have explained list<pair<double, int> > (and I like shelleybutterfly's suggestion to derive Polynomial from the list, except that I'd make it protected, not public, so that outside code is not too free to mess with the contents of the list).
But the add function is a little tricky, because adding two polynomials doesn't generally mean concatenating them or adding their terms together. The operation is actually more like merging-- and you'll soon see that the lists must be sorted. (In fact, it's more natural to represent polynomials as vectors, but I guess that's not the assignment.)
I suggest you implement Polynomial::add(pair<double, int>), first, then implement the other one (add(Polynomial &)) in terms of that.
I don't want to spell it out too much, since this looks like homework. Is this enough to point you in the right direction?
EDIT:
Your new code looks correct (albeit inefficient) if you fix a couple of bugs:
void Polynomial::add(const Polynomial& rhs)
{
// Don't forget to implement the sorting routine.
// The iterators must be of the correct type. And itr must be const,
// since you have declared rhs to be a const reference. The compiler
// will not allow you to have an iterator with the power to alter
// a const thing.
list<pair<double,int> >::const_iterator itr;
list<pair<double,int> >::iterator itl;
for(itr=rhs->terms.begin(); itr!=rhs->terms.end(); itr++)
{
bool match=false;
for(itl=terms.begin(); itl!=terms.end(); itl++)
{
// You have an extra parenthesis here, and too much dereferencing.
if(itl->second == itr->second)
{
itl->first+=itr->first;
match = true;
}
}
if(!match)
{ terms.push_back(*itr); //Perform the sort again
} // Be careful not to catch the closing brace in a comment
}
}
Once it is working, you can think about ways to make it cleaner and more efficient. For example, if you insert the new term in the right place, the list will always be in the right order and there will be no need for a sort routine.
As for using a pair, why not use a list<pair<double, int>> (list< pair<double, int> > for older compilers)? Or you could even define a separate class to hold your pair like so:
// example is implemented inline, you could always pull it out to
// your source file; although it's even possible that you could
// do everything inline if you want to allow just including a
// header but not having to link a separate file.
class CoeffAndTerm : public pair<double,int>
{
public:
// if you need it you should put extra functions here to
// provide abstractions:
double getTotalValue()
{
return first * second;
}
}
and then use
list<CoeffAndTerm> Polynomial;
as your variable, or even
// same stuff goes for this class RE: the inline function definitions
class Polynomial : public list<CoeffAndTerm>
{
public:
// same goes here for the abstraction stuff maybe things
// like in your current Polynomial class; assuming some
// functions here ...
Polynomial Multiply(Polynomial other)
{
Polynomial Result = new Polynomial();
for (int i=0; i < size(); ++i)
{
Result.addCoeffAndTerm(
new CoeffAndTerm(
other.first * first,
other.second * second
);
}
return Result;
}
}
so that you've got Polynomial being a derivation of the list itself. Not sure the exact usage of the Polynomial, so it's hard for me to speak to which makes more sense, but I like this way better as a general rule for a type such as this; seems to be that the polynomial "is a" list of coefficient and terms, it doesn't just "have" one. :) I'm sure that's debatable, and again it depends on the actual usage of your code.
for the operations, you could do reference returns, as in one of the other examples, but I have implemented the multiply without modifying the existing value, which you could also do for Add, Subtract, etc. so, assuming First, Second, Third, etc. are other polynomials
Polynomial Result = First.Multiply(Second).Add(Third).Subtract(Fourth);
you could also implement copy constructor, operator =, operator +, operator *, operator / and then do things that look like normal math:
Polynomial Result = First * Second + Third - Fourth;
While it's possible to use std::pair to group the term order and coefficient, I would recomment against it: it's not very readable - it's not clear what 'first' and 'second' means, and C++ will implicitly cast between numeric types - and you get no benefit from the added functionality of pair (ordering).
Instead, create a class like:
class Term {
double coeff_;
int exp_;
public:
Term(double coeff, int exp): coeff_(coeff), exp_(exp) {}
double coefficient() const { return coeff; }
int exponent() const { return exp; }
[...]
};
class Polynomial {
std::list<Term> terms;
[...]
Making fields public (e.g. by using struct or publicly deriving from pair) for performance reasons is not a good idea: inline constructor, getters and setters are just as fast as reading or writing the variable directly, and they have the advantage of encapsulating the implementation.
For that matter, you may want to create separate types to wrap polynomial coefficients and exponents themselves, in order to avoid mixing up numeric types, and performing nonsensical operations e.g.:
class Coefficient {
double val;
public:
explicit Coefficient(double value): val(value) {}
double getValue() { return val; }
double operator*(double rhs) { return val*rhs; }
Coefficient operator+(const Coefficient& rhs) {
return Coefficient(val+rhs.val);
}
[...]
};
etc.
Another possibility: instead of using a class, you could make as struct to represent the term and coefficient; you still can define methods on it just like a class, but the members are public by default which may make sense for efficiency reasons, especially if you're doing a lot of processing with these things. So, maybe:
struct CoeffAndTerm
{
int Term;
double Coeff;
private CoeffAndTerm(int parTerm, double parCoeff)
{
Term = parTerm;
Coeff = parCoeff;
}
public static CoeffAndTerm Make(int parTerm, double parCoeff)
{
return new CoeffAndTerm(parTerm, parCoeff);
}
// etc. and otherwise you can just do things as given in the example
// with the classes deriving from list<pair<int, double>>, e.g.,
// silly example again
public double getTotalValue()
{
return first * second;
}
}
and same applies otherwise as in the first example, again giving more direct access than that example had, but still allowing for the abstraction methods to be placed directly on the object
struct Polynomial : public list<CoeffAndTerm>
{
list<CoeffAndTerm> CoefficientsAndTerms;
Polynomial Multiply(Polynomial other)
{
Polynomial Result = new Polynomial();
for (int i=0; i < size(); ++i)
{
Result.addCoeffAndTerm(
new CoeffAndTerm(
other.first * first,
other.second * second
);
}
return Result;
}
// etc.
}