В этом году мы с товарищами (ForNever, Minoru, Hagane, grouzen) опять взялись участвовать в ICFPC. Если кто не в курсе, что это такое — см мой предыдущий пост или серию постов товарища adept.
В этот раз для разнообразия мы не писали AI для игрушки. Организаторы были из Японии, и поэтому мы весь уик-енд… складывали оригами. Кто-то из кода, а кто-то нет.
Задача состояла в том, чтобы из квадратного «листа бумаги» складывать разные (плоские) фигуры. В качестве задачи даётся описание нужной фигуры, а решение — набор складок на квадрате и описание, какие вершины в какие переходят при складывании. Первая сотня фигур была предложена организаторами, а дальше задачи могли отправлять участники, и за отправку задач тоже давали очки.
При этом, на самом деле, это было «не настоящее оригами». Были допустимы решения, невозможные с бумагой — части листа могли проходить друг через друга при складывании. При отправке решений чужих задач можно было даже «рвать бумагу» (при отправке своих задач — нельзя). Момент про разрешено ли разрезание мы уточняли долго и сложно.
Контест в этот раз проходил с утра пятницы по вечер воскресенья в моём часовом поясе.
В пятницу
с утра я «по-быстрому» написал скачивалку задач с сервера и закачивалку решений (на python, просто потому что там было REST API, а у меня уже был опыт использования для этого питоньей библиотеки requests). Ещё я написал парсер предложенного формата задач и рендерилку, которая рисует фигуры из задач в виде svg (на Haskell). Сразу пригодился хаскельный модуль Data.Ratio. Дело в том, что в задачах использовались координаты в виде рациональных чисел, причём размеры числителя и знаменателя не были ограничены. Так что быстро образовалась строчка type Number = Ratio Integer.
Потом я посмотрел на результаты рендера и увидел, что первые семь задач тривиальные (там просто квадрат, сдвинутый или повёрнутый, но не сложенный), решения для них легко написать вручную. Решил и залил.
Потом мы начали думать над задачей (я уже писал, у меня всегда так — сначала код, потом думать).
Когда нет ограничения на разрезание бумаги, задача сводится к тому, чтобы разрезать квадрат на эн многоугольников и сложить из них нужную фигуру. Насколько я знаю, подобные темы широко и глубоко изучены, но я не знаком с конкретными работами и алгоритмами. (в университете был даже какой-то спецкурс по оригами, как разделу геометрии, но я на него не попал). Поэтому я долго и упорно думал в эту сторону, но ничего не придумал.
В чате довольно быстро образовалось несколько идей:
- Разрезать требуемую фигуру на треугольники и попытаться из таких треугольников сложить квадрат.
- Какой-нибудь вариант генетических алгоритмов: разрезаем квадрат как попало и складываем как попало, оцениваем скор в соответствии с правилами организаторов.
- Быстро придумался простой алгоритм для складывания любого достаточно маленького выпуклого многоугольника: пройти по всем его рёбрам и сложить бумагу вдоль них. Если останутся торчащие «хвосты», то опять пройти по рёбрам и подвернуть вдоль них.
- Кроме силуэта фигуры, в задачах приводился её «скелет» — набор всех рёбер в положении после складывания. При этом, правда, было указание, что это только подсказка, складывать в соответствии с этим скелетом не обязательно. Так вот, появилась идея брать этот скелет и пытаться разворачивать его до квадрата.
Товарищ grouzen произвёл обширные изыскания существующих научных работ на тему оригами и около, и обеспечил нас пейперами для чтения на всю неделю. К сожалению, применить их мы не смогли.
Потом начался как всегда разброд и шатание, каждый стал заниматься чем-то своим.
Я решил начать с написания какого-никакого «фреймворка» для дальнейшей работы — набора функций для разрезания многоугольников, объединения и т.п. Некоторые из геометрических алгоритмов тривиальны (отражение многоугольника относительно прямой), зато другие зубодробительны (объединение произвольных многоугольников). Для таких алгоритмов я стал гуглить существующие реализации, по возможности на Haskell (т.к. парсер задач уже был на Haskell). Нашёл только clipper. Это биндинги к одноимённой библиотеке на C++. Сразу обнаружилась особенность: Clipper работает с целочисленными координатами (видим
Текущие проекты
Давно я что-то сюда не писал. Замотался совсем. В частности, несколько неожиданно для себя стал техническим писателем 🙂
Пока что задокументирую несколько проектов, которые у меня сейчас в более-менее вялотекущей разработке. Пожалуй, в хронологическом порядке.
Framework
Это фреймворк (не очень высокого уровня, на настоящий момент) для создания web-приложений на Haskell. Страница проекта тут, haddock-документация тут. Проект в значительной мере исследовательский: насколько сложно/просто писать веб-приложения на Haskell? А фреймворки? Какие новые идеи способен привнести Haskell в эту область? Кроме того, изначально я задумывал фреймворк для разработки приложений высокой нагруженности (так что само собой предполагаются всякие кэширования, работа со многими СУБД и мн.др.). Во фреймворке в настоящий момент много чего не хватает (начиная с названия) — нет полноценной ORM, нет генерации произвольных диалектов SQL… Вероятно, как раз в этих областях что-нибудь интересное получится в результате. Кое что [на мой взгляд] оригинальное в фреймворке уже есть. Т.к. Haskell — компилируемый язык, то всё приложение — это один бинарник. Включая шаблоны. Шаблоны пишутся в синтаксисе, похожем на Django-вский (вообще, я многие идеи старался взять из django), при сборке приложения по ним генерируется haskell-исходник и компилируется вместе с приложением. Достоинства и недостатки, собственно, очевидны: нет затрат времени на парсинг шаблонов на каждый запрос (но и затрат сложности на кэширование шаблонов тоже нет), генерация html по шаблонам быстрее, но при изменении шаблонов надо пересобирать приложение (но если речь идёт о большой нагрузке, шаблоны будут меняться редко).
MyPaint
Как несложно догадаться из названия, MyPaint (http://mypaint.intilinux.com) — это программа для рисования (дословно — что-то вроде «моя живопись»; исторически, это название — ссылка на программу paint.exe от microsoft). Программ для рисования сейчас довольно много, в том числе и свободных, и под Linux (конечно, в первую очередь на ум приходит Gimp). Особенность MyPaint — это программа в первую очередь именно для рисования, а не для обработки готовых изображений (собственно, MyPaint даже не умеет таких вещей, как «кроп» или «уровни»; за такими функциями добро пожаловать в тот же Gimp). На самом деле, ближайшие конкуренты MyPaint — это Corel Painter и ArtRage (NB: это не означает, что они идут ноздря-в-ноздрю, просто это программы одного назначения).
Этим летом мои родные-художники дорвались до компьютера, а именно до mypaint, и засыпали меня багрепортами и фичреквестами. В связи с чем я начал разрабатывать свою ветку mypaint. Сейчас мои наработки будут постепенно вливаться в основную ветку.
Коротко изменения — i18n и перевод на русский (сейчас уже в основной ветке, вместе с переводами на французский, норвежский, шведский, упрощённый китайский и др.); палитра; что-то наподобие масок; диалог слоёв; группировка кистей; поддержка наклона пера. Подробнее на вики mypaint, там же рядом бурное обсуждение интерфейса.
Надеюсь в ближайшее время сделать отдельную статью про MyPaint. А пока, «с первого и по тринадцатое», собираюсь поплотнее заняться разработкой с целью сделать мои нововведения пригодными для вливания в основную ветку — релиз планируется сразу после этого мержа.
Todos
Ещё один проект без нормального названия 🙂 Это простецкий TODO-менеджер на Haskell. Собственно, сами TODO пишутся в любом текстовом редакторе в plain-text файлике (желательно, с названием TODO) в простецком формате:
[spaces]status [TAGS] title (depends) description
где
Некоторые хитрости в использовании xmonad
Некоторое время назад я публиковал здесь статьи по настройке ion3. Всё течёт, всё меняется, и сейчас я использую другой фреймовый оконный менеджер — xmonad. С русской документацией по нему сейчас дело обстоит лучше, чем обстояло с ion3, когда я начал писать о нём. Именно, есть довольно основательная статья xmonad: функциональный оконный менеджер. Так что с вопросами «что такое xmonad» отсылаю туда. Однако, когда есть одна только вводная документация — этого всё-таки недостаточно. Хочется примеров настройки и всяческих вкусностей. И их есть у меня! 😉