Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Нестандартная реорганизация значений TList - алгоритм

263
25 января 2007 года
koltaviy
816 / / 16.12.2004
Вообщем, ситуация следующая:
Имеется перечисление:
 
Код:
enum CigaretteContainers
{
        CigaretteItself = 1,
        CigarettePack = 20,
        CigaretteBlock = 200,
        CigaretteBox = 4000
};

Значения перечисления хранятся в списке 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 __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;
  }
}

По-моему нелепо получилось..
Как можно оптимизировать алгоритм(я не говорю, что то, что я написал - это алгоритм)) нахождения таких наборов и замены их на большее значение?
Код из C++Builder 6.
309
25 января 2007 года
el scorpio
1.1K / / 19.09.2006
То же самое в одну строку, а ещё можно использовать ссылки
 
Код:
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;
}
3
25 января 2007 года
Green
4.8K / / 20.01.2000
Я позволю себе смотреть в корень проблемы.
Зачем такая нелепая организация? Куда удобнее и правильнее (т.к. это разные сущности) разделить единый контейнер на три: сигареты, пачки, блоки. А если пойти дальше, то возникает вопрос: а зачем вообще контейнеры? Достаточно трех счетчиков: счетчик сигарет, счетчик пачек, счетчик блоков.

Просто, вопрос из разряда: "я просунул правую руку между ног, скажите, как мне теперь почесать за левым ухом?"
263
25 января 2007 года
koltaviy
816 / / 16.12.2004
To el scorpio:
Спасибо, конечно, но я не спрашивал, как написать 'в одну строку' метод сортировки!!!!!!!!!!!!!!!!!!!!! :D
Читай пост еще раз!!

To Green:
Возможно, ты прав.
11K
25 января 2007 года
.nornad
125 / / 04.01.2007
Не "возможно", а именно прав. Зачем вся эта нелепость с хранением кучи значений в списке? Если только для практикования в проектировке маразмов... ;)
263
25 января 2007 года
koltaviy
816 / / 16.12.2004
To Green:
Сорри, это я погорячился..
Насчет того, что ты прав - так или иначе перечисление все-таки необходимо использовать.
И хранить указатели на значения перечисления в TList, как я и сказал..
Перечисление CigaretteContainers - выдуманное.. как я считал для наглядности.
Про разные сущности: можно привести пример с денежными купюрами, к примеру:
 
Код:
enum RUBBanknotes
{
       Chirik = 10,
       Poltinnik = 50,
       Sotka = 100,
       Pyatihat = 500,
       Shtuka = 1000
};

:) Забавное перечисление получилось..
В общем задача осталась прежняя - как организовать замену набора меньших элементов перечисления на один элемент большего наминала.
3
25 января 2007 года
Green
4.8K / / 20.01.2000
Какая-то секретная у тебя задача получается. :)
Понимаешь, ты пытаешься поставить обобщенную задачу, которая в обобщенном виде выглядит несколько нелепо. Поэтому, когда ты пытаешься представить её в виде некого примера, она становится ещё более нелепой.
Можно, конечно, посоветовать некоторый обобщенный ответ, но каков вопрос таков ответ. Поэтому, если ты хочешь, получить действительно дельный совет, тебе либо придется раскрыть реальные причины такой организации, либо пересмотреть свою архитектуру для того, чтобы она была более рациональной.
Пока же я не вижу необходимости в хранении в контейнере. Для второго примера я вообще бы сделал один единственный счетчик валюты и по необходимости пересчитывал бы по купюрам (не храня результат пересчета).

Если уж так хочется хранить в контейнере, то оптимальным будет введение некоторой избыточности, т.е. хранишь текущее значение валюты в счетчике и при каждом добавлении пересчитываешь значения по купюрам, помещая результат в предварительно очищенный контейнер. Т.е. контейнер используется лишь для хранения результата, но значения из него не используются для расчета.
Менее оптимальный вариант - пробегать по всему контейнеру, формируя общую сумму, потом очистить контейнер и внести в негшо результаты пересчета на основе полученной суммы. Т.е. от предыдущего отличие в том, что сумма не хранится, а каждый раз пересчитывается.
Прочие варианты IMHO будут ещё менее оптимальны.
263
25 января 2007 года
koltaviy
816 / / 16.12.2004
To Green:
Да я все понимаю..
Но вопрос же был не как организовать хранение данных..
Хотя согласен, что предложенное решение может, иногда, оказаться правильнее.
Организация хранения данных, используемая мной для поставленной задачи, представляется мне наиболее уместной, поэтому вопрос был именно про нестандартную реорганизацию значений TList.
Ответ был получен!
+1 to Green
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог