LINUX.ORG.RU

Что-то я сильно туплю

 , ,


0

1

Есть ф-ция которая принимает 3 аргумента:

1) актуальный размер стека

2) актуальное положение в стеке

3) новый элемент для вставки (append) в стек

Мы внутри себя храним полную копию чужого стека, эта наша ф-ция дергается извне, когда внешний стек поменялся. Новый элемент для вставки может быть «null», остальные параметры прилетают всегда.

Этот «null» может быть тогда, когда внешний стек просто урезали с конца. Например раньше был размер 10 (и у нас есть старое значение с предыдущего обращения), а стал 3. Значит просто урезаем свой стек и ставим актуальное положение.

А может быть не «null», значит новый элемент надо вставить в конец своего. Но в этом случае стек так же мог быть урезан, и присылается сюда к нам размер стека уже с учетом того что там вовне этот элемент уже вставлен.

И вот я сейчас это все расписал, вроде все понятно, бери и делай. Но как только у меня доходит до написания кода (все эти иф/элзиф и инкремен/декремент размеров и положений изза нулл/ненулл) — я начинаю страшно тупить и ничего не получается.

Да, я уже поспал и выспался — не помогает. Помогите мне пжл, кусочком псевдокода.

ЗЫЖ Писец аж стыдно...

Несовсем ясно как параметры используются, в частности:

2) актуальное положение в стеке

положение чего?

Deleted
()
Ответ на: комментарий от Deleted

Нет, вставлять всегда в конец (после того как правильно урезали), индекс может быть равен индексу элемента, а может быть и нет. Индекс не несет важности при вставке, он просто запоминается и нужен для другого.

deep-purple ★★★★★
() автор топика

Может я чего не понимаю, ну на те псевдокод =)

type * stack_mirror(int size, int position, type * element)
{
    static type elements_stack[];

    if(element == null)
    {
         stack_mirror_resize(&elements_stack,size);
    }else{
         stack_mirror_resize(&elements_stack,size);
         stack_mirror_add(position,element);
         return &elements_stack;
         };
}
Deleted
()
Ответ на: комментарий от Deleted

stack_mirror_resize(&elements_stack,size);

Если элемент не нулл, ты урежешь меньше чем нужно. Ведь прилетевший размер учитывает что там вовне элемент в конец уже вставлен.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Если стек не урезался вовне, то зачем ВСЕГДА пытаться урезать его у себя? И проверку «а надо ли урезать и насколько» нужно нагромоздить именно в этой ф-ции, а не в «stack_mirror_resize» т.к. больше нигде это не используется.

deep-purple ★★★★★
() автор топика
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Тогда как-то так:

void on_change(
    std::size_t size,
    /*second_arg,*/
    value_type* value
)
{
    //assume stack is global object of type std::stack<value_type>
    if (stack.size() != size-1 && !value) { throw some_exception(); }
    if (stack.size() >= size)
    {
        /*execute stack.pop() stack.size()-size+1 times*/
    }
    if (value) stack.push(*value);
}
Первую проверку может как-нибудь поизящнее приделаешь

Deleted
()
Ответ на: комментарий от deep-purple

Если размер внешнего стека стал меньше в соотвецтвии с тем что в функцию передаётся его новый размер и null в качестве нового элемента (тоесть его отсутствия) то значит размер стека урезаем и мы внутри в функции удаляя верх или низ в зависомости от того чё у нас там за структура стека, с верху вниз или с низу вверх.

Тоесть при если size +1 то увеличиваем размер и заносим туда значение

Если size -1 то просто отрубаем с верху или с низу елемент и всё.

Но если в стеке допустимо произвольно добавить элемент в позицию по индексу 33 или удалить от туда элемент, то конечно моё вообще не подходит, тогда можно (если допустимо) удалить элемент под номером 33, взять элемент из головы или низа стека внести в индекс 33 и удалить уже пустой верх или низ.

Кароче я не знаю какие правила обращения к этому «стеку» =))

Deleted
()
Ответ на: комментарий от Deleted

Ну я к тому что если урезан основной стек значит там элемент же удалён, нам пофигу мы просто зеркально урезаем и наш. Ну опять же я наверное просто не понял если всё не так. ))

Deleted
()
Ответ на: комментарий от Deleted

Произвольно в середину никогда не вставляется, только в конец. Смотри, кто-то вовне урезал стек (всегда с конца), было 20, получилось 10, если там еще и вставляли новый элем, то пришлют размер=11 и элем не нулл, иначе пришлют размер=10 и элем нулл.

deep-purple ★★★★★
() автор топика

Много пересекающихся (размытых по нескольким параметрам) вариантов. Например если новый размер меньше предыдущего, а элемент не null? Какой главнее?

А если положение не совпадает это тоже увеличение/уменьшение или забить на этот бессмысленный для стеков параметр?

И да - урезать свой - заманаешься память перевыделять. Так что уменьшать свой стек не надо, надо просто выкидывать лишние элементы.

anonymous
()

cast i-rinat, DELIRIUM, Vit. Эти три головы на изи дадут верный ответ. =) Всё я убежал, хехе.

Deleted
()
Ответ на: комментарий от anonymous

Много пересекающихся

Вот я и туплю.

если новый размер меньше предыдущего, а элемент не null?

Значит новый размер учитывает что элемент уже в том внешнем стеке добавлен.

положение не совпадает

Оно не влияет на размерность, оно просто всегда где-то в пределах стека.

надо просто выкидывать лишние элементы

Не могу иначе — Qt, модель, интерактивная вью, модельиндексы.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Аааааааааааааааа, так там вооон как, а откуда мы хрен знаем последовательность? А если тогда там добавили, урезали снова добавили? Я в расчёте на то что мы при каждом изменении изменяем нашу копию А так размер внешнего тогда нахрен не нужен, просто нужно передавать в наш элемент и его позицию и всё, а у себя внутри мы уже просто вставляем елементы в соответствии с позицией, зеркальность будет обеспечиваться сама собой и не надо следить за границами и прочим, просто храним максимальный индекс элемента как размер стека и всё и чхать нам что там происходит в основном.

Deleted
()
Ответ на: комментарий от Deleted

Несколько добавлений и урезаний за один раз не будет, только разовые и последовательно. Индекс может не указывать на новый элемент, мы можем доверять только присланному размеру. Можешь считать что размер = позиция нового + 1, но это будет верно только если новый элем не нулл, иначе размер это просто размер.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Не, это совсем не то. Я может да, плохо объяснил, есть у меня такая беда. Но тут мы уже обсудили нюансы в других сообщениях, глянь плиз.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Значит новый размер учитывает что элемент уже в том внешнем стеке добавлен.

Значит у аргументов есть приоритет? Распиши его.

Не могу иначе — Qt, модель, интерактивная вью, модельиндексы.

В qt усть qstack. В принципе твой класс должен быть обёрткой над ним. Почему может возникать рассинхронизация стеков?

anonymous
()
Ответ на: комментарий от deep-purple

Теперь уже у меня тупняк начинается, ибо не вижу противоречий. Можешь привести ошибочный сценарий?

Deleted
()
Ответ на: комментарий от anonymous

у аргументов есть приоритет?

Расписал в других сообщениях. Походу он переменчивый.

твой класс должен быть обёрткой над ним

У меня наследник QAbstractListModel юзает (оборачивает) эту копию стека. Тут не суть важно что там у меня за основу стека взято, но в данном случае это QList и тут и вовне.

Почему может возникать рассинхронизация стеков?

Внешний стек в другом треде. А готовые кутевые компоненты которые могли мне подойти, все ковыряются напрямую (в моем случае в QList), рейс кондишн я уже словил. Поэтому я запилил кастомную вью и кастомную модель, которая хранит копию внешнего стека (облегченную, это не копии элементов из внешнего стека, там только тип элемента (они разные) и текст для показа в списке (с разным кол-вом аргументов), тут важна только актуальность размера и порядок элементов). Все сигналы-слоты висят как queued + там еще и мьютекс имеется — порядок выполнения гарантирован.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от RazrFalcon

Предлагаешь их поджарить? Шутка, конечно.

Я еще не дошел до умных. Но, и в данном случае оно работает без нареканий, я осторожен и не забываю чиститься.

А по самому вопросу можешь что сказать?

deep-purple ★★★★★
() автор топика
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от Deleted

if (stack.size() != size-1 && !value) { throw some_exception(); }

Размер моего стека (это старое состояние внешнего) легко может быть не равен размеру нового (вычти еденицу или нет). Эксепшн тут ни к чему.

execute stack.pop() stack.size()-size+1 times

Если эелем нулл, то ты урежешь на один больше чем надо.

deep-purple ★★★★★
() автор топика

начинаю страшно тупить и ничего не получается

Для начала вот всё то, что описал, оформи в виде тестов. Хотя бы в виде набора описаний, которые сможет понять другой человек. Набери ещё разных вариантов, таких как пустой стек, непустой стек, позиция в верхушке, позиция в глубине, позиция где-то посередине. Удаление, добавление, удаление и потом добавление.

i-rinat ★★★★★
()

Это какой-то странный интерфейс и описание такое же. Но всё же попробую угадать.

std::vector<Element *> stack;
int pos;

void
stackChanged(int size, int position, Element *element)
{
    stack.resize(size);
    pos = position;

    if (element != nullptr) {
        stack.back() = element;
    }
}

Я бы поменял интерфейс или разбил бы его на несколько операций, которые бы обрабатывал отдельно (раз по аргументам можно определить, что происходит).

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 1)
Ответ на: комментарий от xaizek

Если элемент не нулл, сайз учитывает что элемент уже есть во внешнем стеке. Твой пример недоурежет стек и добавит новый как «лишний».

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от xaizek

Ты правильно угадал что это слот. Я бы не разбивал, ибо обновлять лучше «атомарно».

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Там нету добавления кроме ресайза. Т.е. либо старый элемент будет переиспользован, либо ресайз создаст новый, который тут же будет затёрт.

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 1)
Ответ на: комментарий от deep-purple

проверка хрень

fix: (stack.size()+bool(value) <= size). Защита от случая: размер увеличивается на 100500 за один вызов, а элемент для вставки только один.

Если элемент нулл, то ты урежешь на один больше чем надо.

Точно, провтыкал этот факт. Фикс, впрочем, очевидный: s/stack.size()-size+1/stack.size()-size+[b]bool(value)[/b]/

Deleted
()
Ответ на: комментарий от Deleted

bool(value)

Вложенный тег не сработал

Deleted
()
Ответ на: комментарий от xaizek

Наш стек: A, B, C, D (index=3)

Изменяться может например с такими вариантами:

а) Внешний стек: A, B, E => stackChanged(3, 2, E_info)
б) Внешний стек: A, B => stackChanged(2, 1, null)
в) Внешний стек: A, F => stackChanged(2, 1, F_info)

Как я уже говорил — урезает только с конца. И еще надо учесть когда стек еще совсем пуст.

deep-purple ★★★★★
() автор топика
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Я не вижу, чтобы хотя бы один из этих случаев не сработал с тем кодом. Он всего лишь делает правильный размер и выборочно устанавливает значение последнего элемента. Какой из вариантов тебе кажется нерабочим?

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

А, черт, перезаписывает, я опять протупил, да. Щас попробую.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Может лучше подойти с другой стороны? Перечисли как именно вызываются элементы этогостека из других мест.

anonymous
()
x.realloc(max(capacity, size + (elem?1:0)));
x.resize(size);
if(elem)
    x.push(elem);
MyTrooName ★★★★★
()
Ответ на: комментарий от anonymous

Из других мест в копию стека попасть никак нельзя, она варится сама по себе и приватна, копия стека нужна для отображения пользаку и интерактивности — выбор индекса (какой элемент стека выделил пользак), какой выбрали, такой просим установить во внешнем стеке. Т.е. список может только менять currentIndex внешнего стека.

Из других мест во внешний стек можно только «попытаться» добавить новый элемент: «externalStack->push(new someTypeStackItem(foo, bar))».

Попытаться потому, что стек проверяет, не пытаемся ли мы добавить дубликат айтема (и тот же ли это объект и по значениям), который сидит сейчас в стеке на currentIndex + 1.

Если мы пытаемся добавить дубликат, то стек просто инкрементирует currentIndex.

Если мы добавляем не дубликат, то, стек урезается до размера currentIndex и добавляет новый элемент.

В обоих случаях стек сигналит: «stackChanged(actualSize, actualCurrentIndex, maybeNewElemInfoMaybeNull)»

Вот и все. На основе этих данных нужно «атомарно», в одном слоте, обновить копию стека (вьюшка).

deep-purple ★★★★★
() автор топика

У стека нет «актуального размера» и «актуального положения», у него есть только push и pop.

aedeph_ ★★
()

(все эти иф/элзиф и инкремен/декремент размеров и положений изза нулл/ненулл)

Эталонный говнокод. Выкинь нахрен эти многоэтажные условия и сделай конечный автомат.

no-such-file ★★★★★
()
Ответ на: комментарий от deep-purple

Не совсем понял что ты имеешь ввиду

Что тут непонятного? У тебя есть копия стека и операции на ней (состояния автомата). У тебя есть 3 переменные, в зависимости от которых происходит переход из одного состояния в другое. Это типичный конечный автомат https://ru.wikipedia.org/wiki/Автоматное_программирование

И вот я сейчас это все расписал, вроде все понятно, бери и делай

Надо не расписывать, а рисовать схему, при каких условиях какие переходы выполняются.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)

Дядьки! i-rinat, xaizek, MyTrooName.

После отдыха с пивом, отвлечения от всего этого..

Все получилось сходу. С вашей помощью — оценка вариантов, использование мин/макс. Вобщем спасибо всем троим что наставили на правильный путь. Отмечаю решенной.

deep-purple ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.