Skip to content

Instantly share code, notes, and snippets.

@mkamilov
Last active July 1, 2019 03:03
Show Gist options
  • Save mkamilov/a0341ed921167da438b3030468abaec3 to your computer and use it in GitHub Desktop.
Save mkamilov/a0341ed921167da438b3030468abaec3 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <set>
#include <unordered_map>
#include <queue>
#include <time.h>
#include <bitset>
#include <algorithm>
#include <functional>
using namespace std;
int TC = 5;
int MAX_CATEGORY = 32;
int MIN_ITEMS = 1000;
int MAX_ITEMS = 1000;
int MAX_PRICE = 10;
int MIN_PRICE = 2;
int MAX_RAND_VALUE = 100;
int MAX_ITEM_ID = 10000;
int PRICE_TAG = 50;
int TOP_X = 100;
class Item {
public:
// using single unsigned int bitwise check sets
unsigned int category;
int name;
int value;
int price;
Item(unsigned int c, int i, int v, int p) : category(c), name(i), value(v), price(p) {}
void print() {
cout << "name=" << name << " value=" << value << " price=" << price << " category=";
int i = 0;
while (category) {
if (category & 1) {
cout << i << ",";
}
category = category >> 1;
i++;
}
cout << endl;
}
friend bool operator== (const Item &n1, const Item &n2);
};
class ItemSet
{
public:
set<Item> items;
int sum;
};
bool operator== (const Item& item1, const Item& item2)
{
return (item1.category == item2.category) &&
(item1.name == item2.name) &&
(item1.price == item2.price) &&
(item1.value == item2.value);
}
bool operator<(const ItemSet& item1, const ItemSet& item2) {
return item1.sum < item2.sum;
}
bool operator<(const Item& item1, const Item& item2) {
if (item1.value == item2.value) {
if (item1.price == item2.price) {
return item1.name < item2.name;
}
return item1.price > item2.price;
}
return item1.value < item2.value;
}
bool operator>(const Item& item1, const Item& item2) {
if (item1.value == item2.value) {
return item1.price < item2.price;
if (item1.price == item2.price) {
return item1.name > item2.name;
}
}
return item1.value > item2.value;
}
priority_queue<ItemSet> output;
vector<Item> generateTestItem()
{
int items = MIN_ITEMS+rand() % MAX_ITEMS; // amount of items
srand(time(NULL));
vector<Item> v;
set<int> itemDuplicateTester;
for (int j = 0; j < items; ++j) {
int catSize = rand() % 10; // amount of categories for each item
unsigned int cats = 0;
for (int c = 0; c <= catSize; ++c) {
int r = rand() % MAX_CATEGORY;
cats |= 1 << r;
}
int itemId = rand() % MAX_ITEM_ID;
int value = rand() % MAX_RAND_VALUE;
int price = MIN_PRICE + rand() % MAX_PRICE;
// make sure generated item is unique with itemDuplicateTester
if (itemDuplicateTester.find(itemId) == itemDuplicateTester.end()) {
v.push_back(Item(cats, itemId, value, price));
itemDuplicateTester.insert(itemId);
//v.back().print();
}
}
return v;
}
void addOutput(set<Item>& currentItems)
{
ItemSet myset;
int setsum = 0;
for (auto a : currentItems) {
setsum += a.value;
}
myset.items = currentItems;
myset.sum = setsum;
output.push(myset);
}
void helper(vector<Item>& input, set<Item>& currentItems, unsigned int currentCats, int sum, int index)
{
if (index == input.size()) {
// Need to check if currentItems matches the blueprint
// if yes, then call addOutput
addOutput(currentItems);
return;
}
if (output.size() >= TOP_X) {
return;
}
if (sum + input[index].price < PRICE_TAG) {
// this condition needs to be changed
// we need to have category checker method which would return true if we are ok to include
// input[index] item's category as per blueprint
if ((input[index].category & currentCats) == 0) {
currentItems.insert(input[index]);
helper(input, currentItems, currentCats | input[index].category, sum + input[index].price, index + 1);
}
} else {
// Need to check if currentItems matches the blueprint
// if yes, then call addOutput
addOutput(currentItems);
return;
}
if (currentItems.find(input[index]) != currentItems.end()) {
currentItems.erase(input[index]);
}
helper(input, currentItems, currentCats, sum, index + 1);
return;
}
void getTopItems(vector<Item>& items)
{
set<Item> myset;
helper(items, myset, 0, 0, 0);
}
int main()
{
for (int i = 0; i < TC; ++i) {
vector<Item> v = generateTestItem();
cout << "generated items : " << v.size() << endl;
sort(v.begin(), v.end(), greater<Item>());
getTopItems(v);
cout << "got ans " << output.size() << endl;
int j = 0;
while (output.empty() == false) {
set<Item> myset = output.top().items;
output.pop();
int priceSum = 0, valueSum = 0;
for (auto a : myset) {
priceSum += a.price;
valueSum += a.value;
}
j++;
cout << "set size=" << myset.size() << " priceSum= " << priceSum << " valueSum = " << valueSum << endl;
}
}
return 0;
}
@codinghaven
Copy link

Here is the example showing why your solution isn't optimal.

https://awwapp.com/b/uuyfktgxv/

Here is a video going through the example:

https://drive.google.com/open?id=1MSMHb16K5D17ul1LBMCwlRkcC93uokQF

@codinghaven
Copy link

I have figured out a solution I am writing the code now will notify you when done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment