enum CigaretteContainers
{
CigaretteItself = 1,
CigarettePack = 20,
CigaretteBlock = 200,
CigaretteBox = 4000
};
Нестандартная реорганизация значений TList - алгоритм
Имеется перечисление:
Код:
Значения перечисления хранятся в списке TList cig_container.
Необходимо при добавлении нового указтеля в список, делать следующее:
1) Если значений (CigaretteItself / 20 > 0) , то заменить все количество сигарет кратное 20 на значения CigarettePack.
(Заменить подразумевает удаление старых элементов и добавление нового(ых)).
2) Если значений (CigarettePack / 10 > 0) , то заменить все количество пачек кратное 10 на значения CigaretteBlock.
(Заменить подразумевает удаление старых элементов и добавление нового(ых)).
3) Если значений (CigaretteBlock / 20 > 0) , то заменить все количество блоков кратное 20 на значения CigaretteBox.
(Заменить подразумевает удаление старых элементов и добавление нового(ых)).
Я сделал очень незатейливо):
Код:
void Seat::ReOrganizeTheContainers()
{int cig_count, pack_count, block_count;
cig_count = 0;
pack_count = 0;
block_count = 0;
this->cig_container->Sort(CompareContainers);
for (int i = 0; i < this->cig_container->Count; i++)
{
CigaretteContainers *cig_item = (CigaretteContainers*)this->cig_container->Items;
if (*cig_item == (CigaretteContainers)CigaretteItself)
{
cig_count++;
}
else
{
break;
}
}
while ((cig_count / 20) > 0)
{
for (int i = 0; i < 20; i++)
{
CigaretteContainers *cig_item = (CigaretteContainers*)this->cig_container->Items[0];
this->cig_container->Remove(cig_item);
delete cig_item;
cig_item = 0;
}
cig_count -= 20;
this->AddTheContainer((CigaretteContainers)CigarettePack);
}
this->cig_container->Sort(CompareContainers);
for (int i = cig_count; i < this->cig_container->Count; i++)
{
CigaretteContainers *cig_item = (CigaretteContainers*)this->cig_container->Items;
if (*cig_item == (CigaretteContainers)CigarettePack)
{
pack_count++;
}
else
{
break;
}
}
while ((pack_count / 10) > 0)
{
for (int i = 0; i < 10; i++)
{
CigaretteContainers *cig_item = (CigaretteContainers*)this->cig_container->Items[cig_count];
this->cig_container->Remove(cig_item);
delete cig_item;
cig_item = 0;
}
pack_count -= 10;
this->AddTheContainer((CigaretteContainers)CigaretteBlock);
}
this->cig_container->Sort(CompareContainers);
...
}
{int cig_count, pack_count, block_count;
cig_count = 0;
pack_count = 0;
block_count = 0;
this->cig_container->Sort(CompareContainers);
for (int i = 0; i < this->cig_container->Count; i++)
{
CigaretteContainers *cig_item = (CigaretteContainers*)this->cig_container->Items;
if (*cig_item == (CigaretteContainers)CigaretteItself)
{
cig_count++;
}
else
{
break;
}
}
while ((cig_count / 20) > 0)
{
for (int i = 0; i < 20; i++)
{
CigaretteContainers *cig_item = (CigaretteContainers*)this->cig_container->Items[0];
this->cig_container->Remove(cig_item);
delete cig_item;
cig_item = 0;
}
cig_count -= 20;
this->AddTheContainer((CigaretteContainers)CigarettePack);
}
this->cig_container->Sort(CompareContainers);
for (int i = cig_count; i < this->cig_container->Count; i++)
{
CigaretteContainers *cig_item = (CigaretteContainers*)this->cig_container->Items;
if (*cig_item == (CigaretteContainers)CigarettePack)
{
pack_count++;
}
else
{
break;
}
}
while ((pack_count / 10) > 0)
{
for (int i = 0; i < 10; i++)
{
CigaretteContainers *cig_item = (CigaretteContainers*)this->cig_container->Items[cig_count];
this->cig_container->Remove(cig_item);
delete cig_item;
cig_item = 0;
}
pack_count -= 10;
this->AddTheContainer((CigaretteContainers)CigaretteBlock);
}
this->cig_container->Sort(CompareContainers);
...
}
и т.д.)
Функция сортировки:
Код:
int __fastcall CompareContainers(void *Item1, void *Item2)
{
CigaretteContainers *cig_item1 = (CigaretteContainers *) Item1;
CigaretteContainers *cig_item2 = (CigaretteContainers *) Item2;
if (*cig_item1 > *cig_item2)
{
return 1;
}
else if (*cig_item1 < *cig_item2)
{
return -1;
}
else
{
return 0;
}
}
{
CigaretteContainers *cig_item1 = (CigaretteContainers *) Item1;
CigaretteContainers *cig_item2 = (CigaretteContainers *) Item2;
if (*cig_item1 > *cig_item2)
{
return 1;
}
else if (*cig_item1 < *cig_item2)
{
return -1;
}
else
{
return 0;
}
}
По-моему нелепо получилось..
Как можно оптимизировать алгоритм(я не говорю, что то, что я написал - это алгоритм)) нахождения таких наборов и замены их на большее значение?
Код из C++Builder 6.
Код:
int __fastcall CompareContainers (const void *Item1, const void *Item2)
{
const CigaretteContainers &cig_item1 = *(const CigaretteContainers *) Item1;
const CigaretteContainers &cig_item2 = *(const CigaretteContainers *) Item2;
return (cig_item1 > cig_item2) ? 1 : (cig_item1 < cig_item2) ? -1 : 0;
}
{
const CigaretteContainers &cig_item1 = *(const CigaretteContainers *) Item1;
const CigaretteContainers &cig_item2 = *(const CigaretteContainers *) Item2;
return (cig_item1 > cig_item2) ? 1 : (cig_item1 < cig_item2) ? -1 : 0;
}
Зачем такая нелепая организация? Куда удобнее и правильнее (т.к. это разные сущности) разделить единый контейнер на три: сигареты, пачки, блоки. А если пойти дальше, то возникает вопрос: а зачем вообще контейнеры? Достаточно трех счетчиков: счетчик сигарет, счетчик пачек, счетчик блоков.
Просто, вопрос из разряда: "я просунул правую руку между ног, скажите, как мне теперь почесать за левым ухом?"
Спасибо, конечно, но я не спрашивал, как написать 'в одну строку' метод сортировки!!!!!!!!!!!!!!!!!!!!! :D
Читай пост еще раз!!
To Green:
Возможно, ты прав.
Не "возможно", а именно прав. Зачем вся эта нелепость с хранением кучи значений в списке? Если только для практикования в проектировке маразмов... ;)
Сорри, это я погорячился..
Насчет того, что ты прав - так или иначе перечисление все-таки необходимо использовать.
И хранить указатели на значения перечисления в TList, как я и сказал..
Перечисление CigaretteContainers - выдуманное.. как я считал для наглядности.
Про разные сущности: можно привести пример с денежными купюрами, к примеру:
Код:
enum RUBBanknotes
{
Chirik = 10,
Poltinnik = 50,
Sotka = 100,
Pyatihat = 500,
Shtuka = 1000
};
{
Chirik = 10,
Poltinnik = 50,
Sotka = 100,
Pyatihat = 500,
Shtuka = 1000
};
:) Забавное перечисление получилось..
В общем задача осталась прежняя - как организовать замену набора меньших элементов перечисления на один элемент большего наминала.
Понимаешь, ты пытаешься поставить обобщенную задачу, которая в обобщенном виде выглядит несколько нелепо. Поэтому, когда ты пытаешься представить её в виде некого примера, она становится ещё более нелепой.
Можно, конечно, посоветовать некоторый обобщенный ответ, но каков вопрос таков ответ. Поэтому, если ты хочешь, получить действительно дельный совет, тебе либо придется раскрыть реальные причины такой организации, либо пересмотреть свою архитектуру для того, чтобы она была более рациональной.
Пока же я не вижу необходимости в хранении в контейнере. Для второго примера я вообще бы сделал один единственный счетчик валюты и по необходимости пересчитывал бы по купюрам (не храня результат пересчета).
Если уж так хочется хранить в контейнере, то оптимальным будет введение некоторой избыточности, т.е. хранишь текущее значение валюты в счетчике и при каждом добавлении пересчитываешь значения по купюрам, помещая результат в предварительно очищенный контейнер. Т.е. контейнер используется лишь для хранения результата, но значения из него не используются для расчета.
Менее оптимальный вариант - пробегать по всему контейнеру, формируя общую сумму, потом очистить контейнер и внести в негшо результаты пересчета на основе полученной суммы. Т.е. от предыдущего отличие в том, что сумма не хранится, а каждый раз пересчитывается.
Прочие варианты IMHO будут ещё менее оптимальны.
Да я все понимаю..
Но вопрос же был не как организовать хранение данных..
Хотя согласен, что предложенное решение может, иногда, оказаться правильнее.
Организация хранения данных, используемая мной для поставленной задачи, представляется мне наиболее уместной, поэтому вопрос был именно про нестандартную реорганизацию значений TList.
Ответ был получен!
+1 to Green