Russian Qt Forum
Ноябрь 15, 2024, 08:48 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 ... 5 6 [7] 8   Вниз
  Печать  
Автор Тема: Итераторы  (Прочитано 47262 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #90 : Апрель 21, 2013, 10:04 »

Давайте мы возьмем поверхность с ландшафтом и будем обстреливать ее снарядами: хочу воронки, разрушение холмов и прочие ямы.
Если интересно я расскажу как решаются такие задачи  Улыбающийся

Наваял решение, критикуйте  Строит глазки
Ну Вы просто "развязали синтаксический террор" Улыбающийся  Как Вы представляете себе поддержку такого кода?  "Хммм... ну ладно, что-то написано, как-то работает и слава богу". А если заклинит - в которой лямбде искать? Улыбающийся И это еще здесь я хорошо знаю задачу и сразу понял что Вы делаете в принципе.

Как у Вас со скоростью? Можно сравнить с вариантом kamre или моим - насколько я помню, у меня время удаления 5-7 миллисекунд.

Ну и общий вопрос - стОит ли так писать? Помогает ли std? Мнение старого ретрограда - нет, только мешает. Не короче, не выразительнее и код не быстрее.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #91 : Апрель 21, 2013, 10:06 »

Если интересно я расскажу как решаются такие задачи  Улыбающийся
Не интересно, я сильно сомневаюсь, что у вас есть подобные знания, а чайники выводить я в детстве отлюбил. Подмигивающий
Ладно, разговор про векторы и OpenGL для себя считаю закрытым.
« Последнее редактирование: Апрель 21, 2013, 10:14 от Old » Записан
alex312
Хакер
*****
Offline Offline

Сообщений: 606



Просмотр профиля
« Ответ #92 : Апрель 21, 2013, 14:52 »

Ну Вы просто "развязали синтаксический террор" Улыбающийся
Спасибо за комплимент  Строит глазки
Как Вы представляете себе поддержку такого кода?  "Хммм... ну ладно, что-то написано, как-то работает и слава богу". А если заклинит - в которой лямбде искать? Улыбающийся И это еще здесь я хорошо знаю задачу и сразу понял что Вы делаете в принципе.
Если вы думаете что ваш код читается на одном дыхании, то вы глубоко заблуждаетесь . А если заклинит - то есть тесты и отладчики.
Как у Вас со скоростью? Можно сравнить с вариантом kamre или моим - насколько я помню, у меня время удаления 5-7 миллисекунд.
Сравнивал по скорости с вашим вариантом - мой отстает примерно в 2 раза, но мой вариант не использует дополнительной памяти.
Ну и общий вопрос - стОит ли так писать? Помогает ли std?
Да, именно так и стоит всегда писать если скорость исполнения достаточная.
Не короче, не выразительнее и код не быстрее.
Теперь по краткости и выразительности.
1. Мой код 34 строки, ваш - 37 (код, который непосредственно относится к решению задачи).
2. В моем коде явно используется 1 цикл, в вашем 5, причем один вложенный. (Это про читаемость и понимаемость)
3. Ваш код гвоздями прибит к вектору, мой код может использовать и списки. Может для вас это не важно, но многие оценят.
(если подправить функцию печати трегольников, но ведь это вспомогательная функция)
Код
C++ (Qt)
   auto print_tr = [&](const std::string& msg, size_t cnt)->void
   {
       size_t pnt_cnt = (cnt > mTriangle.size()) ? mTriangle.size() : cnt ;
       if(pnt_cnt)
           std::cout<<msg<<std::endl;
       for(auto idx = mTriangle.begin(); std::distance(mTriangle.begin(), idx) < pnt_cnt; ++idx)
           {
               std::cout<<"("<<(*idx)[0]<<","
                             <<(*idx)[1]<<","
                             <<(*idx)[2]<<")";
               if( ((std::distance(mTriangle.begin(), idx)+1) % 3) == 0 )
                   std::cout<<std::endl;
               else
                   std::cout<<"\t";
           }
       std::cout<<std::endl;
   };
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #93 : Апрель 21, 2013, 15:25 »

4. Если в качестве входных данных подсунуть не валидные индексы, то не портит по тихому память. Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #94 : Апрель 21, 2013, 16:35 »

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

- скорость. Вы говорите вдвое, это приемлемо. Но судя по коду Вы удаляете всего неск точек а я 10К. Сообщите что у Вас в этом случае.

- binary_search + upper_bound. Мне кажется можно обойтись одним lower_bound

- (заманчивая) общность - ну вряд ли std::distance даст приемлемую скорость напр для std::list. Да и зачем тогда индексы если данные неперемещаемы?

4. Если в качестве входных данных подсунуть не валидные индексы, то не портит по тихому память. Улыбающийся
То палка о двух концах - провалимся если индекс удаления валидный но встречается дважды
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #95 : Апрель 21, 2013, 17:02 »

То палка о двух концах - провалимся если индекс удаления валидный но встречается дважды
Не знаю куда кто провалится, но я про вот это чудо:
Код
C++ (Qt)
// mark deleted points with -1
for (i = 0; i < delIndex.size(); ++i)
tmp[delIndex[i]] = -1;
 
И если у kamre мы хотя бы поймаем assert в операторе [], то у вас в варианте он молча затрет что захочет.

P.S. Пример преждевременной оптимизации во всей красе. Подмигивающий Вы хоть assert'ом проверяйте.

« Последнее редактирование: Апрель 21, 2013, 17:04 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #96 : Апрель 21, 2013, 17:45 »

P.S. Пример преждевременной оптимизации во всей красе. Подмигивающий Вы хоть assert'ом проверяйте.
Да какие глубокие мысли  Улыбающийся  А так чем будете проверять?

Код
C++ (Qt)
std::vector<int> need_del_point = {2, 2, 12, 24, 37, 42, 55, 69, 75, 84, 93 };
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #97 : Апрель 21, 2013, 17:56 »

А так чем будете проверять?

Код
C++ (Qt)
std::vector<int> need_del_point = {2, 2, 12, 24, 37, 42, 55, 69, 75, 84, 93 };
А что вы тут хотите проверить?
Записан
alex312
Хакер
*****
Offline Offline

Сообщений: 606



Просмотр профиля
« Ответ #98 : Апрель 21, 2013, 18:14 »

- скорость. Вы говорите вдвое, это приемлемо. Но судя по коду Вы удаляете всего неск точек а я 10К. Сообщите что у Вас в этом случае.
- binary_search + upper_bound. Мне кажется можно обойтись одним lower_bound
- При 10к точек, мой вариант 0.94с, ваш 0.25с.
 - Без binary_search не обойтись, потому что при использовании xxx_bound нельзя однозначно опеделить отсутствие элемента в контейнере. ( конкретно lower_bound  выдает указатель на начало контейнера при отсутствующем элементе)
Записан
Akon
Гость
« Ответ #99 : Апрель 22, 2013, 11:44 »

Нужно понимать, что итераторы в первую очередь предназначены не для того, чтобы быть альтернативой индексации, а для декларации интерфейса доступа к элементам контейнера. Т.о., интераторы позволяют работать с любым контейнером (который их поддерживает), т.е. достигается абстракция контейнера, что крайне желательно на практике.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #100 : Апрель 22, 2013, 12:04 »

А так чем будете проверять?

Код
C++ (Qt)
std::vector<int> need_del_point = {2, 2, 12, 24, 37, 42, 55, 69, 75, 84, 93 };
А что вы тут хотите проверить?
При таких данных std-вариант будет "молча работать неправильно". Это не его вина (junk in - junk out), но не надо намекать что он якобы "более надежен"  Улыбающийся

- При 10к точек, мой вариант 0.94с, ваш 0.25с.
 - Без binary_search не обойтись, потому что при использовании xxx_bound нельзя однозначно опеделить отсутствие элемента в контейнере. ( конкретно lower_bound  выдает указатель на начало контейнера при отсутствующем элементе)
Ну хорошо, допустим по каким-то причинам использование доп памяти запрещено. Что за причины - хз, ее расход не больше 20% от исходного объема. Ну ладно, нельзя так нельзя. Но и в этом случае я не вижу необходимости хоть каких-то функторов/лямбд и.т.п. Почему бы не решить простейшими базовыми средствами языка? Сделать ф-цию с нормальным человеческим именем напр

Код
C++ (Qt)
typedef std::vector <int> TIntVec;
 
// returns -1 if index is deleted, otherwise a new index
int RemapIndex( int index, const TIntVec & vec )
{
TIntVec::const_iterator it = std::lower_bound(vec.begin(), vec.end(), index);
if (it == vec.end()) return index - vec.size();
if (*it == index) return -1;
return index - std::distance(vec.begin(), it);
}
 
И очевидное удаление элементов из массива - можно размазывать сопли с remove_if (copy_if) а лучше простым и ясным for
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #101 : Апрель 22, 2013, 12:08 »

При таких данных std-вариант будет "молча работать неправильно". Это не его вина (junk in - junk out), но не надо намекать что он якобы "более надежен"  Улыбающийся
Ваш вариант молча убивает память - ошибка в коде.
Для std-варианта вместо вектора индексов удаляемых точек нужно просто использовать набор (std::set). Это еще один вид контейнеров. Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #102 : Апрель 22, 2013, 12:10 »

можно размазывать сопли с remove_if (copy_if) а лучше простым и ясным for
Я думаю двоишникам по программированию и цикл for не ясный, давайте лучше if и goto. Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #103 : Апрель 22, 2013, 12:39 »

Ваш вариант молча убивает память - ошибка в коде.
А чего же Вы забыли добавить "при некорректных входных данных"? Улыбающийся И чего не вдаетесь в анализ что может случиться с любой реализацией в этом случае ?

Я думаю двоишникам по программированию и цикл for не ясный, давайте лучше if и goto. Улыбающийся
А Вам не кажется что цикл for давным-давно имел все достоинства новоиспеченной лямбды? Улыбающийся

Нужно понимать, что итераторы в первую очередь предназначены не для того, чтобы быть альтернативой индексации, а для декларации интерфейса доступа к элементам контейнера. Т.о., интераторы позволяют работать с любым контейнером (который их поддерживает), т.е. достигается абстракция контейнера, что крайне желательно на практике.
Ах как удобно повторять написанное в книжке Улыбающийся Не спорю, концептуально это красиво. Но давайте копнем чуть глубже на том же живом примере. Вот выше утверждалось что с copy_if код пригоден как для вектора, так и для списка. Возможно "работать будет" - но вот делать будет совсем не то что нужно. Чего же мы перемещаем все элементы списка при удалении некоторых? Зачем тогда список если адреса элементов уплывают? Грамотно удалять из списка его методом remove_if или erase в цикле. Но ни то ни другое не обобщается на линейные контейнеры как вектор. Вот и закончилась "концептуальная красота/общность"   Улыбающийся

Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #104 : Апрель 22, 2013, 12:44 »

А чего же Вы забыли добавить "при некорректных входных данных"? Улыбающийся И чего не вдаетесь в анализ что может случиться с любой реализацией в этом случае ?
Вы и читаете не очень?
Вот что я писал в посте #93:
4. Если в качестве входных данных подсунуть не валидные индексы, то не портит по тихому память. Улыбающийся
Какие слова здесь не понятны - спрашивайте.

А Вам не кажется что цикл for давным-давно имел все достоинства новоиспеченной лямбды? Улыбающийся
Улыбающийся Почитайте пожалуйста про "Лямбда-функции и выражения"

Как можно сравнивать циклы и функции?
« Последнее редактирование: Апрель 22, 2013, 12:50 от Old » Записан
Страниц: 1 ... 5 6 [7] 8   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.237 секунд. Запросов: 23.