Category: it

Category was added automatically. Read all entries about "it".

nyaload

Все течет, все меняется

Тонкая ошибка в такой схеме базы данных про книги и их авторов:


таблица 1: id книжки (ключ) | список id авторов книги | название книжки

таблица 2: id автора (ключ) | имя автора

Суть ошибки:
при изменении имени автора мы
* либо заводим новый id и теряем информацию что это тот же автор старых книг,
* либо же мы теряем старое имя автора, и имя автора на реальной бумажной книге перестает совпадать с именем автора в базе данных.

--------------------------------------------------------------
Никогда-никогда-никогда-никогда не буду больше использовать доставку EMS россии. Единственное что там лучше чем Почта России - это хорошая поддержка по телефону.

В остальном - тоже самое, заполнять паспортные данные и свой адрес при вручении посылки, а чуть что-то нестандартное с посылкой - необходимо ехать в офис, который сильно дальше чем ближайшее отделение обычной почты. Если в 8 утра не ответил на единственный звонок от курьера - считается, что "вручить не удалось"

--------------------------------------------------------------

А ещё я почти научился фотореалистичным срисовкам (на фото сверху IRL натюрморт, на экране снизу - срисованное):
Collapse )
nyaload

CR LF

В некоторых файлах в некоторых контекстах надо байты '\r\n' интерпретировать так же, как как байт '\n' (например, чтение значения из рукописного конфига key=value). Иногда так делать ни в коем случае нельзя ("битый архив", hex-dump).

Иногда '\r\n' и '\n' можно нормализовать при выводе в какой-то конкретный. Иногда так делать нельзя, и всеми силами стараться сохранить в выводе то, что при пришло на вход (при обработке сложнее чем "пропустить часть и переставить местами строки" это не всегда очевидно, что такое "сохранить").

А когда так надо делать и в каких ситуациях - это область гуманитарных наук, а не computer science.
nyaload

Как закрыть панель в Blender

Blender - наиболее популярный свободный и кроссплатформенный редактор для создания 3d-анимации. В добавление к созданию анимации - там есть поддержка монтажа нарендеренного. Сегодня немножко потыкался в его UI. Как ни странно, это единственная программа которую я нашёл, в которой можно редактировать видео для простого монтажа в разных форматах. В других - то .wmv не загружается, то .mov не загружается (и похоже нет ни одной программы, которая могла бы резать видео по key-frames без перекодировки в разных форматах-контейнерах, включая mov, wmv, avi, mkv).

Чтобы закрыть панель в Blender, нужно посмотреть - эта панель часть вертикального или горизонтального стека окон. Если это часть вертикального стека, то нужно зажать кнопкой мыши на треугольник в углу панели, и вести мышку вверх (если горизонтального - то вправо) к следующей панели в стеке, затем обратно на эту же панель.
Если это самое верхняя (правая) панель и следующей панели нет, то нужно модифицировать эту логику - взять предпоследнюю панель с начала стека, зажать треугольник, и вести мышку ввех (вправо), и отпустить в той панели, которую мы хотим закрыть.
В обоих случаях нужно отпустить кнопку мышки в той панели, которую мы хотим закрыть, но отличается то, с какой панели нужно начать.

Если вы не осознали, что тут выше написано - то ничего страшного, я тоже не понял, пока я не посмотрел ролик на ютубе.

На самом деле при закрытии панели - нужно указать не только закрываемую панель, но и то, какую другую панель использовать для оставшейся дырки. Универсальность и точность!


Вопрос на stackexchange, как закрывать панели в blender - http://blender.stackexchange.com/questions/1223/how-to-close-open-a-view-panel
Ролик на ютубе, объясняющий как закрывать панели в blender - https://www.youtube.com/watch?v=AMBi1R7KB48
Человек полгода работающий в blender, спрашивает как закрывать панели - http://blenderartists.org/forum/showthread.php?234374-Closing-Split-Screens

Говорят, что это более удобно, чем то что было в более ранних версиях, <2.6

Видно, не один я был в тупике, как же это делается:


Это не единственная непривычная вещь в интерфейсе. Ещё есть кастомный Open/Save File диалог, в котором нельзя открыть файл по его абсолютному пути (два отдельных текстовых поля для директории и имени файла). И кастомная логика сохранения проекта. Благодаря которой я несколько раз закрыл проект, не сохранив - дефолтная кнопка при закрытии это "да, выйти не сохранив", вместо привычного "выйти и сохранить". Если закрыть по 20-летней привычке Open/Save File диалог крестиком - то закроется текущий проект, а не этот диалог. Если не прочитать внимательно модальный диалог при закрытии Open/Save - то выход будет без сохранения. Это то, об что я стукнулся лбом при освоении самой базовой функциональности и UI блендера.

Видимо, разработчики Блендера совсем не наблюдали, какие проблемы возникают у начинающих, и не считают благим делом сокращение времени обучения.
nyaload

Иммутабельность мешает иммутабельности

Всё-таки мутабельность объектов в небольших пределах - иногда весьма облегчает написание алгоритмов. Это здорово, когда можно в небольшом обозримом участке кода создать объект A, перебросить на него указатели из другого уже созданного объекта B (который мы только что создали), и отложить заполнение полей A до того момента, когда они станут известны. Но в иммутабельном языке - невозможно создать объект, пока мы не знаем все параметры для его создания, и это дико мешает при переложении известных алгоритмов на такой язык. Нужно вводить дополнительные структуры данных, чтобы поменять порядок создания объектов A и B, так как мы в случае иммутабельности не можем создать A, а потом провести из него указатель в B.

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

Это, например, мешает переписывать из википедии алгоритм персистентного красно-черного дерева на такой язык. Там есть подзадача, похожая на такую: в односвязном списке поменять значение ноды с удаляемым значением где-то внутри списка на значение из ноды в конце списка. Список персистентный, поэтому "поменять" означает "создать клон с нужным изменением".
В языке, где можно менять значения полей объекта - всё тривиально, решается в один проход от начала до конца списка.
Идем от начала до нужной внутренней ноды списка, пока идём - создаем дубликаты проходимых нод. Когда нашли нужную ноду - запоминаем указатель на её дубликат, доходим до конца списка, копируем значение в созданный дубликат. Лишней памяти, при условии что нам надо сохранить и старый список (персистентность в copy-on-write её варианте) - не тратится.


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

π++

в С++ нет числа π в стандартной библиотеке. M_PI/_USE_MATH_DEFINES зачем-то сломали в g++ при использовании -std=c++11, а взамен ничего не предложили.

http://stackoverflow.com/questions/1727881/how-to-use-the-pi-constant-in-c

В результате проще в каждом cpp файле копипастить строчку «const double pi = 3.14159265358979323846;» (или «constexpr auto pi = 3.14159265358979323846» в c++11, или acos(-1) вместо константы).

--------------
PS. этот пост дубликат предыдущего, предыдущий я удалил из-за этого бага. Уже оставленные чужие коментарии достал из почты, скопирую в комментарии.
nyaload

Adobe vs GNU - outline

Попробовал для разнобразия редактировать картинки не в фотошопе. Задача - вырезать объект из кадра фильма, написать над ним текстом смешную подпись.

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

Типичный tutorial для GIMP -
* сделать из текста path (сразу в selection нельзя, иначе будет обводка будет из пикселей без antialiasing),
* path сконвертировать в selection,
* раздуть selection пунктом из меню,
* создать новый пустой слой под текстом,
* в новом слое залить selection.

Это куча кликов мышкой, и невозможно редактировать текст после этого.
upd: ещё нашёл туториал по установке нужного плагина, но его нужно применять каждый раз после редактирования (удалив старый слой, "Reapply Effect" во-первых не работает, во-вторых видимо что-то не так с плагином или архитектурой плагинов, раз нужно вручную давить кнопки для применения).

Photoshop:
* в списке эффектов слоя с текстом (по дабл-клику в списке layers) выбираем Stroke.
Дальше можно редактировать текст, эффект автоматически применится.

---------------------------
"Intelligent Scissors" vs "Quick Select" фотошопа - разный набор возможностей, багов, ограничений, и разный способ разметки, но в целом в GIMP я потратил где-то 5 минут на обводку картинки, а на обводку той же картинки в фотошопе - 10 секунд. Часть времени в GIMP потрачена на юзабилити баги "неосторожный клик мимо крошечной точки убивает несколько минут работы без возможности undo/save"
---------------------------
В GIMP при создании нового документа нет профиля "создать canvas под картинку из буфера обмена". Я нашёл способ "Вставить, Fit canvas to layer, вставить ещё раз", но потратил на это довольно много времени. update: есть готовый пункт меню в File->Create, доступный по Ctrl+Shift+V
---------------------------
Планшет плохо совместим как с GIMP и Inkscape - после использования планшета в GIMP или Inkscape отключается мышка (включается обратно только после клика на ползунки прокрутки). Так же почему-то нужно покопаться в опциях и поставить галочку "используй давление стилуса планшета". Так же при использовании планшета начинаются тормоза, GIMP/Inkscape не успевают за вводом планшета (на Core i7/32Gb/Win7-64/Wacom Bamboo CTL-740). upd: оказывается, багу уже 8 лет, и он не только под Windows - http://ubuntuforums.org/archive/index.php/t-702254.html
---------------------------
Inkscape: Tracing Bitmap - нет, проще обвести вручную, чем отчистить сгенерированное (corner nodes втыкаются где не надо, и не втыкаются где надо). Live Preview результата - нет (только результат применения threshold к картинке). Булевские операции и заливка - неточные, оставляют зазоры (и куча дублирующих друг друга багов про это в их трекере, я так и не понял, собираются ли они заменить примерную растеризацию на точные векторные операции ). эффект Power Stroke - регулярно крашит программу. GUI-баги вида "внезапное изменение размера окна" или недоделки "undo не запоминает выделение".
---------------------------
В несомненный плюсик GIMP, экономящий время - его проще скачать и установить, без выяснения "какая платная версия не слишком дорогая мне нужна" или "есть ли вирусы в этом торренте и как запустить кейген". Так же есть справка на русском и других языках, что поможет быстрее пролистать её глазами.
nyaload

хитрые требования к пакетным менеджерам

Цитата с linux-форума. Скопировал сюда для демонстрации, почему пакетный менеджер программ - это сложнее, чем "алгоритм обхода графа зависмостей".

kde это метапакет, который служит для простоты установки рабочего окружения KDE. При установке этого пакета вы автоматически получаете довольно много программ. При попытке удалить любую из них вам будет предложено удалить все пакеты, входящие в метапакет kde
nyaload

(no subject)

Скрипт youtube-dl скачивания видео с ютуба (youtube-dl-2015.08.23.tar.gz) - занимает несколько мегабайт питоньего кода. Одноминутный поверхостный вгзляд показал, что это в основном рукописный осмысленный код, а не кодогенерация. Из которых около мегабайта - относится именно к ютубу (и ещё пара мегабайт - библиотека для парсинга других видео-хостингов).

Мегабайты кода на питоне - это как-то овер-дохрена, это несколько человеколет. Ради скачивания видероликов (с разнообразными опциями, типа выбора языка субтитров, качества видео, и вызовом тулзов пост-процессинга видео для пережатия в другие форматы).
Среди файликов - ./jsinterp.py, на 12 килобайт (парсящий регулярками и исполняющий маленькое подмножество javascript).
nyaload

shared_ptr

У std::(boost::)shared_ptr в блоке, который хранит счетчик, есть ещё указатель на функцию удаления (deleter), который запоминается в момент создания shared_ptr
Это позволяет:
* не париться с виртуальным деструктором, если мы кастуем shared_ptr<derived> в shared_ptr<base> (not recommended, если shared_ptr это не единственный указатель в проекте).
* не париться с переносом деструктора из .h в .cpp, когда делаем PImpl
* передавать shared_ptr в другой модуль, у которого свой собственный аллокатор памяти и свой delete
* Вообще не привязывать способ удаления к типу в shared_ptr (можно использовать свой кастомный аллокатор, и пользователям shared_ptr<T> не нужно знать, какой аллокатор использовался при создании T).

Так же у shared_ptr есть отдельный счетчик для weak-ссылок (иногда нужно в многопоточном программировании и прочих случаях "мы не можем статически отследить вложенность lifetime").

Функция make_shared позволяет не делать две аллокации на счетчик и объект, объединяя их в один кусок памяти.
nyaload

binary search

В книге "жемчужины программирования" сообщается, что невозможно написать binary search с первого раза.

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

Если не осознаёшь инвариант цикла, то с большой вероятностью будет одна из ошибок:

* mid = (lo+hi)/2 или hi/2+lo/2 ? (и нет, дело не в overflow, эти формулы просто разные (1+3)/2 != 1/2 + 3/2 ).Collapse )

Как писать двоичный поиск чтобы он не бажил:
* Выбрать инвариант "если искомый элемент существует, то он в [lo, hi)", изначально выбрать lo,hi = 0, N.
* mid = lo+(hi-lo)/2 (при этом для кода верно утверждение "промежуток длиннее 1 всегда укоротится").
* Если ищем первый среди равных - то сравнение выглядит как key<=array[mid-1], если последний - key<array[mid]
* в зависимости от сравнения присваиваем mid в lo или hi (в любом случае, не mid-1).



Двоичный поиск для равномерно распределённых ключей (хешей) ускоряется простым хаком "для каждого из 65536 двубайтовых префиксов запомнить, где он начинается", это убирает 16 начальных итераций.Collapse )