How Do I Search For Struct Items In A Vector? - c++

I'm attempting to create an inventory system using a vector implementation, but I seem to be having some troubles. I'm running into issues using a struct I made. NOTE: This isn't actually in a game code, this is a separate Solution I am using to test my knowledge of vectors and structs!
struct aItem
{
string itemName;
int damage;
};
int main()
{
aItem healingPotion;
healingPotion.itemName = "Healing Potion";
healingPotion.damage= 6;
aItem fireballPotion;
fireballPotion.itemName = "Potion of Fiery Balls";
fireballPotion.damage = -2;
vector<aItem> inventory;
inventory.push_back(healingPotion);
inventory.push_back(healingPotion);
inventory.push_back(healingPotion);
inventory.push_back(fireballPotion);
if(find(inventory.begin(), inventory.end(), fireballPotion) != inventory.end())
{
cout << "Found";
}
system("PAUSE");
return 0;
}
The preceeding code gives me the following error:
1>c:\program files (x86)\microsoft visual studio
11.0\vc\include\xutility(3186): error C2678: binary '==' : no operator found which takes a left-hand operand of type 'aItem' (or there is no
acceptable conversion)
There is more to the error, if you need it please let me know. I bet it's something small and silly, but I've been thumping at it for over two hours. Thanks in advance!

find looks for something that's equal to the item in the vector. You say you want to search using strings, but you haven't written code for that; it's trying to compare the entire struct. And you haven't written code to compare entire structs, so it's giving you an error.
The simplest solution is to use an explicit loop instead of find.
If you want to find things by string, use the find_if variant and write a predicate function that looks at the string. Or if you want to find things by the entire struct you can define an operator == on the struct that compares both itemName and damage.
Or you might also consider using the map or unordered_map data structures instead of vector. The map containers are designed for fast lookup using a key (such as the string).

The find method does not know how to compare two aItem objects for equality. You need to define the == operator in your struct definition, like this:
bool operator==(aItem other)
{
if (itemName == other.itemName && damage == other.damage)
return true;
else
return false;
}
This will allow find to determine if two aItem objects are equal, which is necessary for the algorithm to work.

try something like:
#include <iostream>
#include <vector>
using namespace std;
struct item {
item(string const name,int const damage):name_(name),damage_(damage) {
}
string name_;
int damage_;
};
int main(int argc, char** argv) {
vector<item *> items;
item healingPostion("cure light",-10);
item fireballPostion("fireball",10);
items.push_back(&healingPostion);
items.push_back(&fireballPostion);
if(find(items.begin(), items.end(), &fireballPostion) != items.end()) {
cout << "Found";
}
return 0;
}

Related

how to make a set using self-defined duplicated judge function?

I want to use STL set to:
insert a struct into this set, like struct {int id, string info};
for each insert, if the id is existed, don't insert
make the element sorted
I tried the following code:
#include <iostream>
#include <set>
using namespace std;
struct song
{
int m_id;
int m_hot;
song(int id,int hot)
{
this->m_id = id;
this->m_hot = hot;
}
bool operator<(const struct song & right)const
{
if(this->m_id == right.m_id) { // remove duplicated
return false;
}
if(this->m_hot != right.m_hot)
{
return this->m_hot > right.m_hot;
}
else
{
return this->m_id > right.m_id;
}
}
};
int main()
{
std::set<song> mySet;
song s1(10,100);
song s2(40,700);
song s3(40,300);
song s4(30,200);
song s5(300,200);
song s6(300,900);
mySet.insert(s1);
mySet.insert(s2);
mySet.insert(s3);
mySet.insert(s4);
mySet.insert(s5);
mySet.insert(s6);
for(auto it:mySet)
{
std::cout<<"id:"<<it.m_id<<",hot:"<<it.m_hot<<std::endl;
}
}
the output is :
id:300,hot:900
id:40,hot:700
id:300,hot:200
id:30,hot:200
id:10,hot:100
As you can see, the id 40 removed the duplicated successfully, but 300 failed.
I think the id 300 part should not appear twice, can someone help me with it?
Your operator< does not satisfy strict weak ordering and your requirements cannot be expressed as such.
The problem is that you have two keys, m_id (for uniqueness) and m_hot (for ordering). You can't choose to order only by m_hot. You always have to order (and ignore equivalent-comparing elements) by both, and you can only choose the precedence. Thus, you cannot establish equivalence between {id=0, hot=0} and {id=0, hot=1}.
^ If your comparator cannot be written as std::tie(lhs.keys...) < std::tie(rhs.keys...), it's no good.
At the moment, I can only think of postponing ordering by m_hot at the places you need it (by copying into a std::vector and sorting it or inserting to a std::set with different comparator).

Sorting a struct vector

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 am trying to make a hashmap of of string functions

I am trying to make a map which stores a string as an identifier and a function that returns a string i have tried typedef but i kept running into problems because i couldn't convert my typedef string (command)() to a regular string i have also tried map commands but it gives me an expression expected error but it does work if i replace string with int. Does anybody know a way of doing this? This is what my code looks like
#include "iostream"
#include <map>
#include <functional>
using namespace std;
class GameController {
public:
void inputReader();
private:
bool gameOver = false;
map<string,string(*)()> commands;//Does not work
//commands
string commandReader(string* inputCommand);
void initCommands();
//both
char* end();
string run();
//while attacking
string attack();
string usePotion();
string useItem();
//while in room
string engage();
string searchRoom();
string rest();
string checkBag();
string checkMap();
string checkStats();
//string save();
};
#endif //ROGUE_GAMECONTROLLER_H
#include "GameController.h"
GameController::GameController(){
initCommands();
}
void GameController::inputReader() {
while (!gameOver){
string x;
getline(cin,x);
cout << commandReader(&x) << endl;
}
}
string GameController::commandReader(string *inputCommand) {
for (map<string,string>::iterator it = commands.begin(); it!=commands.end(); ++it)
{
if(it->first == *inputCommand)
{
return it->second;
}
}
return "Computer says no type help for commands";
}
void GameController::initCommands() {
commands["end"] = end;
//while attacking
commands["run"] = run;
commands["attack"] = attack;
commands["use potion"] = usePotion;
commands["use item"] = useItem;
//while in room
commands["engage"] = engage;//TODO
commands["search"] = searchRoom;
commands["rest"] = rest;
commands["check bag"] = checkBag;
commands["map"] = checkMap;
commands["stats"] = checkStats;
}
This question is tagged C++11, so here's a concise example which uses unordered_map (a real hash map, unlike std::map which my STL reference says is commonly implemented using binary search trees), and std::function.
#include <iostream>
#include <functional>
#include <string>
#include <unordered_map>
std::string foo()
{
return "foo!";
}
struct MyClass
{
static std::string bar()
{ return "bar!"; }
std::string FizzBuzz() const
{ return "FizzBuzz!"; }
std::string operator()() const
{ return "Myclass!"; }
};
int main(int argc, char **argv)
{
MyClass mc;
std::unordered_map<std::string, std::function<std::string()>> commands;
commands["myfoo"] = foo;
commands["mybar"] = MyClass::bar;
commands["myfb"] = std::bind(&MyClass::FizzBuzz, mc);
commands["myclass"] = mc;
for( const auto &f : commands)
std::cout << f.second() << std::endl;
std::cout << commands["myfoo"]() << std::endl;
return 0;
}
Pointers to member functions is not like pointers to free functions or even static methods. For one thing all member functions have a hidden this pointer in the function parameters that makes all of this object magic work.
Going through step by step:
First, define a helper:
typedef string (GameController::*funcp)();
This defines type funcp which represents a pointer to a member function of GameController (to partly take care of the this problem) that takes no parameters and returns string
Then, modify your map to use funcp
map<string, funcp> commands;
Then you have to change the assignment of the member functions a bit to be brutally explicit that it is a pointer and a member of GameController
commands["end"] = &GameController::end;
You can also save yourself some runtime trouble and use an initializer list here rather than a function and a map in every single GameController object. That'll take a bit of extra explaining and I have to be on the move in a few minutes. Sorry about that. A static map with static initializing really is better and worth your time researching, though.
The next bit I stole from the C++ Super FAQ. Read this link. Worth reading all of it, because it heads off a lot of the question you will have.
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
This makes calling the function awesomely easy.
return CALL_MEMBER_FN(*this, it->second)();
And that should about do it for you.
edit:
Tweej demonstrates the generally better way to do this, std::function and std::bind, in their answer. Since I'm advocating the ancient ways, I'd like to explain why.
Two reasons: one is tunnel vision directly answering OP's question.
The second is With the ancient ways I could easily make commands static and save having to create a new copy of commands for every instance of GameController. When using std::bind, you have to have the bound object, and that ruins the static idea.
Poking around at the idea of just using std::function seems to have born fruit and rendered obsolete the ancient ways. gone is the CALL_MEMBER_FN macro. Gone is the funcp typedef
The map is now defined as static, what I was aiming for the the old-pre C++11 approach. Note the funcp typedef is replaced by a function that takes a pointer to GameController to supply this.
static map<string, std::function<string(GameController*)>> commands;
And the map is now rigged to use a static initializer list. No function required. This initializer needs to sit outside the class definition because... I'm not sure why. I think this is changed in C++14.
map<string, std::function<string(GameController*)>> GameController::commands
{
{"end", &GameController::end},
{"run", &GameController::run},
{"attack", &GameController::attack},
{"use potion", &GameController::usePotion},
{"use item", &GameController::useItem},
{"engage", &GameController::engage},
{"search", &GameController::searchRoom},
{"rest", &GameController::rest},
{"check bag", &GameController::checkBag},
{"map", &GameController::checkMap},
{"stats", &GameController::checkStats}
};
The map is initialized once and only once. All GameControllers will use the same commands, so the constructor is really dumb
GameController::GameController()
{
// init function is gone
}
Command reader gets a big rip-up, mostly because the point of a map is you can search it by the key. So I search for the key rather than iterating. The function call is now obvious and dead simple:
string GameController::commandReader(const string &inputCommand)
{
map<string, std::function<string(GameController*)>>::iterator found = commands.find(inputCommand);
if (found != commands.end())
{
return found->second(this);
}
return "Computer says no type help for commands";
}

How to Represent a Set of Pointers with Customized Compare but Maintaining the Original Raw Pointer Duplicate Comparison

Basically, I want to save a set of pointers, which should be sorted by my customized compare function, but the uniqueness should still be determined by the pointer itself.
However:
#include <iostream>
#include <string>
#include <set>
#include <utility>
#include <functional>
using namespace std;
// count, word
typedef pair<int, string> WordFreq;
struct WordFreqPointerCmp
{
bool operator()(const WordFreq* lhs, const WordFreq* rhs) const
{
return lhs->first > rhs->first;
}
};
int main()
{
set<WordFreq*, WordFreqPointerCmp> s;
s.insert(new WordFreq(1, "word1")); // Inserted
s.insert(new WordFreq(1, "word2")); // This is not inserted
s.insert(new WordFreq(3, "word3")); // Inserted
cout << s.size() << endl;
for (set<WordFreq*, WordFreqPointerCmp>::iterator it = s.begin();
it != s.end(); ++it)
{
cout << (*it)->second << ": " << (*it)->first << endl;
}
return 0;
}
/* Output:
2
word3: 3
word1: 1
*/
As you can see that the ordering is correct, but the duplicate testing is wrong. What I am trying to do is:
For ordering, I want to use WordFreqPointerCmp;
For duplicate testing, I want to use the original meaning of raw Pointer comparsion, i.e., the address comparison, which means, even the following set should have two entries in the set;
set<WordFreq*, WordFreqPointerCmp> s;
s.insert(new WordFreq(1, "word1"));
s.insert(new WordFreq(1, "word1"));
I also tried the following, but same result:
template<>
struct greater<WordFreq*>
{
bool operator()(WordFreq* const& lhs, WordFreq* const& rhs) const
{
return lhs->first > rhs->first;
}
};
set<WordFreq*, greater<WordFreq*> > s;
while this post is ancient, I've just faced the same issue, so it may help somebody..
In your code you only handle one value, but what if values are the same? Then set treats it as the same element. The proper solution would be to extend your compare function to give set additional information how to test for duplicates. It can be something arbitrary like comparing strings, for example in your case:
struct WordFreqPointerCmp
{
bool operator()(const WordFreq* lhs, const WordFreq* rhs) const
{
if (lhs->first == rhs->first)
return lhs->second > rhs->second;
else
return lhs->first > rhs->first;
}
};
I am not sure what the problem is. Since you want the first component of your pair to be the key that determines uniqueness, inserting two "WordFreq" with key = 1 should lead to the second evict the first. Results match expectation here.
Update: I guess, I misunderstood something. Since you want duplicate keys, you are probably looking for multimap.
Update 2: To make this work you need to add a step before adding a new object: Iterate over all values of the same key, and kick those out that point to the object being added. Also, I forgot to mention there is multiset which is probably what you'd prefer.
I admit, here is where Java's HashSet with it's separate order and equality tests come in handy. Maybe you can find a C++ version of it.

Bin packing implementation in C++ with STL

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.