Портрет 4X_Pro
Был в Сети 26 апр. 2024 г., 14:48
Мультиблог
4X_Pro
Кратко о себе: Web-разработчик. Пишу на PHP, Python, JavaScript. Знаю Ruby и Go, со студенческих времён более-менее помню C и asm. Сейчас специализируюсь на ускорении загрузки сайтов и разработке ботов для Telegram. Linuxоид (использую Debian+LXDE). Сторонник IndieWeb.

Социальные сети


Новости сайта в Telegram

t.me/4x_pro

Лог жизни

Лог моей жизни, где я фиксирую наиболее эмоционально значимые для меня события и текущее настроение. Является продолжением блога, который я вел в ЖЖ с ноября 2004 по апрель 2018 года.


Babylon Tower — достижение взято

4X_Pro
Вчера после долгих поисков нашел на CodinGame задачу, которую легко можно было решить с помощью bash-скрипта. Все-таки сколько я, оказывается, о bash не знаю! В частности, не знал, что там можно использовать массивы, правда, с крайне неудобным синтаксисом. Потом тут же решил легкую задачку на C++ (заодно понял, что ощутим его подзабыл, в отличие от чистого C, на котором хотя бы иногда что-то пишу). В результате до достижения Babylon Tower, которое дают за решение задач на 15 разных языках программирования, осталось использовать всего один язык программирования. Им, как и планировалось, стал Kotlin, изучением которого я хотел заняться уже давно, но, как всегда, бессознательное протестовало против планов, поэтому вместо него стал писать на Lua и Ruby.
Требовалось решить задачу, которая сначала казалась предельно простой: найти минимальное N при котором a^N оказывается меньше N!. Казалось бы, достаточно пройтись циклом, и решение будет найдено. Но я не учел одного: того, что тесты для решения содержали весьма большие числа (такие,что N уходил за тысячу). И для подсчета «в лоб» попросту не хватало разрядности чисел (тем более в Kotlin, как и в Java, максимальная разрядность для чисел с плавающей точкой — 64 бита, а не 80).
Пришлось включать мозг и искать обходное решение. Оно нашлось довольно быстро. Сначала я решил попытаться получить результат через аппроксимацию факториала. Но увы, аппроксимация есть аппроксимация: N находилось с точностью до нескольких соседних чисел. По сути дела, ее можно было использовать как верхнюю оценку N, и дальше уменьшать его, проверяя выполнение неравенства на каждом шаге. Но как проверить неравенство, если и справа и слева значение вылезает за пределы допустимого? Поломав голову, вспомнил совет, когда-то давно виденный на Хабре: работать не с самими числами, а с их логарифмами. Тут я сообразил, что нужно взять логарифм от факториала можно посчитать как сумму логарифмов отдельных множителей. А с другой частью — все и того проще: N*ln(A).
Как только я это реализовал, программа тут же заработала как надо, и я получил долгожданное достижение Babylon Tower (впервые о нем я начал думать еще с лета, если не раньше).

Изменение в себе: обесценивание сделанного самостоятельно

4X_Pro
Ночью осознал одно интересное изменение в себе. Раньше, видя какой-нибудь простой, но полезный онлайн-инструмент, типа кодирования/раскодирования base64 или Punycode, калькулятора хеша, генератора паролей и т.п., я думал «надо бы и у себя такой сделать». И потом, если делал, гордился тем фактом, что могу пользоваться своим, а не чужим. Сейчас же реакция совершенно противоположная: «ну вот, такое уже есть, смысла нет делать что-то аналогичное, все равно там посетителей будет больше». А если и сделать, то все равно особого повода для гордости от того, что теперь есть свое, не будет. Не знаю почему, но как-то в моем восприятии сам факт возможности сделать что-то самому (равно как и владеть потом этим) обесценился почти до нуля.
Пожалуй, это самое худшее изменение в себе за последние 10 лет. И многие мои нынешние проблемы им и вызваны.

Бестолковый день

4X_Pro
Опять чувствую растерянность в жизни. Возможно, из-за отсутствия четких целей, когда хочу заниматься одним, надо заниматься другим, а по факту — занимаюсь третьим. В частности, сегодня учудил Р.Л. У него вдруг стал медленнее работать сайт. Сначала он пытался оптимизировать картинки товаров, но из-за того, что мы не учли то, что их перегенерация вызовет скачок нагрузки на сервер, получилось еще хуже: часть их них стала просто недоступна с ошибкой 503. Пока я думал, что к чему, и что с этим делать, он успел взять и откатить сайт до ночного backupа, отменив тем самым результаты своей оптимизации. Но даже это не помогло: сайт все равно продолжал подтормаживать, а некоторые картинки — не отображаться.
Из переписки с техподдержкой мы узнали, что проблема в том, что картинки с параметром отдаются не nginxом, а передаются на обработку Apache, число процессов которого на хостинге весьма жестко лимитировано. Пришлось срочно придумывать, как избавиться от этого параметра (в нем передавался token для генерации уменьшенной картинки) так, чтобы не пострадала безопасность. Но зато результат порадовал: сайт с кучей картинок и тяжелых скриптов без кеша стал грузиться всего за 3.1 секунду! Правда, тут еще сказывается, что хостинг недавно наконец-то сделал поддержку HTTP/2. Но вот загружать оптимизированные картинки Р.Л. придется теперь заново.
Потом я занялся доработкой своего алгоритма для Code vs Zombies на CodinGame. Реализовал две идеи, но одна из них себя в целом не оправдала. На паре карт она позволяла спасти больше людей, но на остальных результат становился только хуже, и итоговый показатель был на 2000 очков меньше примерно. Пришлось от нее пока отказаться, и попробовать другую — поправить алгоритм так, чтобы игрок уничтожал зомби не последовательно, одного за другим, а старался накрыть одним ходом несколько (за это дается существенный бонус). Отчасти получилось, но результат оказался меньше ожидамого: ~56000 вместо 50600 и подъем в рейтинге примерно на сотню позиций. В общем, рост есть, прорыва нет. И вообще, видимо, надо пока переключиться на другие игры, так как тут пока больше идей нет, что еще можно попробовать.
А вообще, конечно, чувствую, как мне не хватает знаний именно по чисто математическим алгоритмам типа проверки принадлежности точки многоугольнику или пересечения двух отрезков.
Сегодня ночью наткнулся на очередной сайт по тренировке внимания, памяти и интеллекта — Wikium. Но если все предыдущие были почти полностью платными, тут вроде по одной из трех программ можно тренироваться бесплатно. (Впрочем, ничто не мешает сделать несколько аккаунтов.)

Совместная прогулка с Tellой

4X_Pro
В начале недели решили с Tellой, что сходим в пятницу в кино. Она выбрала фильм под названием «На границе миров», рекламу которого мы видели прошлый раз, но потом упомянула об этом фильме в одном чате. Там ее начали троллить тем, что если она вытащит меня на такое, то это будет нашим последним походом куда-либо. Она нашла отзывы об этом фильме, почитала, и так впечатлилась, что расхотела идти сама. Это заинтересовало, в свою очередь, уже меня. Я тоже посмотрел отзывы, и пришел к выводу, что это правильное решение.
Поэтому мы решили просто прогуляться в парк за Дворцом Молодежи на Фрунзенской. Я там собирался побывать давно, и даже дважды летом проходил мимо, но внутрь попасть все не складывалось. Впрочем, парк оказался даже меньше, чем я думал, даже меньше нашего Перовского. Но зато там гораздо более красивый пруд, да и вечерний вид на окружающие дома тоже понравился.
Сделав пару кругов по парку, задумались, что делать дальше. Я предложил отправиться к Новодевичьему пруду, где не был уже достаточно давно. Пришли туда, сфотографировали башни Сити и монастырь в ночном освещении, побродили немного по дорожкам, и решили ехать на Киевскую и там поесть в ТЦ «Европейский». Но на переходе на Парке Культуры я запутался (уж очень там планировка необычная) и вместо перехода на Кольцевую мы вышли на поверхность. Решили обратно не спускаться. В пути я рассказал Telle про то, что DarLik недавно удалось сделать почти нереальное: уговорить меня попробовать незнакомую кухню, в данном случае грузинскую. Tella вспомнила, что поблизости есть одна хинкальная, где она когда-то отмечала окончание университета, и предложила сходить туда. Но там не оказалось мест, и мы пошли искать другое заведение. Нашли довольно быстро (но уже не с грузинской кухней, а совсем другое). Там еще просидели какое-то время, а потом отправились до Октябрьской, так как я вспомнил о своем давнем желании снять несколько ночных видов с Крымского моста.
В общем, прогулка получилась весьма длинной, но в целом позитивной!

Бестолковый день с ранним подъемом

4X_Pro
Сегодня проснулся гораздо раньше обычного, так как вернулся к тому, чтобы спать в холоде. В результате день получился длинный, но довольно бестолковый. Сел было писать заметку про то, как избыточный выбор обесценивает все, но как всегда, бессознательное взбунтовалось против планов. В заметке потребовалось вспомнить автора книги «Парадок выбора», я стал искать эту книгу у себя в планшете. В итоге наткнулся на совсем другую — «Человек убежденный» Эрика Хоффнера. Ее я скачал очень давно и благополучно забыл, а сейчас начал читать с огромным интересом, поскольку в ней затрагивается одна из важнейших для меня тем: как происходит возникновение и распад массовых движений. В общем, примерно полдня ушло на эту книгу.
А вечером решил еще пару задач на CodinGame на языке Lua. Но в нем я сейчас сильно разочаровался. Многие вещи приходится делать вручную. Например, там нет готового split. Да и вообще, работа со строками ужасно сделана. В общем, реально язык хорош только там, где экономия ресурсов важнее всего остального. А в других случаях лучше писать на Ruby (вот этот язык мне в последнее время нравится все больше и больше) или на Python.
Еще было бы интересно провести тестирование производительности — сравнить Ruby, Lua, PHP и Python на каких-нибудь типовых задачах типа чисел Фибоначчи или решения систем уравнений, но вряд ли до этого дойдут руки.

Жизнь вроде бы налаживается

4X_Pro
До субботы всё было совсем плохо, а потом, как это ни странно, жизнь начала налаживаться. Сменился эмоциональный фон. А за воскресенье и понедельник столкнул большую часть из тех доделок, о которых писал в предыдущих сообщениях. Ещё съездил в гости к Р.Л., доделали кое-что и по его сайту.
И вообще, не раз уже замечал, что если растянуть проблему во времени, она проблемой быть перестаёт, решение рано или поздно находится, а необходимая для его реализации энергия — накапливается (или я получаю ее от людей, заинтересованных в решении).
На CodingGame решил ещё одну оптимизационную задачу (правда, решение пока далеко от идеала и позволило подняться только в TOP-70%) — Code vs Zombies. И в общем рейтинге поднялся примерно до 1230 места.
А сегодня с DarLik ходили в кино. Посмотрели фильм «Репродукция», где поднимается тема клонирования и переноса сознания. Хотя сначала я отнесся к идее сходить на этот фильм без энтузиазма, но в итоге совершенно не жалею, что посмотрел. Даже несмотря на некоторые явные нелогичности в фильме.
Ещё вчера совершил сеанс технонекромантии — оживил свой старый планшет, купленный в 2015 году. В нем от долгого хранения в разряженном состоянии начал портиться аккумулятор. И получалось вот что: на этапе перехода от зарядки малым током к обычной планшет пытался включить экран, чтобы показать индикатор. Но экран начинал потреблять столько энергии, что уровень заряда тут же снова падал ниже критического, и планшет отключался. Часа два я держал его на зарядке и надеялся, что это как-то решится. А потом пришлось прибегнуть к хитрости: вскрыть планшет и отключить экран вообще. Физически вынуть шлейф из разьема. Я не верил, что это даст результат, и ожидал, что все, планшет придется признать сдохшим, но, к огромному моему удивлению, это сработало! Но увы, в процессе вскрытия случилась другая неприятность: отломились провода от динамика, который приклеен к задней крышке. Так что устройство теперь в вечном беззвучном режиме. Потом ещё удалил с него KingRoot (весьма вредная утилита, которая кроме основной задачи — получения root-прав, пытается делать кучу ненужного: то систему оптимизировать, то рекламу на экране блокировки показывать).

Неприятности продолжаются

4X_Pro
В пятницу забил на все, и на какой-то момент показалось, что жизнь улучшилась. А сегодня опять все плохо! Какое-то непонятное сочетание усталости и злости на все вокруг без видимых причин. И опять все из рук валится. На CodinGame сыграл несколько clashей. Сначала все было хорошо, поднялся с 95 до 74 места. А потом сначала затупил на одной задаче по реверсу, а потом прилетела неадекватно сложная задача в shortest mode, которую даже просто за 15 решить сложно, не говоря уж об оптимизации. И тут же свалился обратно на 94-ое, аннулировав тем самым все достигнутое.
Да еще отец достает ерундой разной. Хочется звуконепроницаемую дверь с двумя замками как минимум в комнату поставить!
Зато от злости наконец-то принял решение удалить Ask. А то в последнее время там доля нормальных вопросов упала до 20%, если не меньше, остальное — полнейший дебилизм. Да и криво работающие уведомления в приложении тоже давно уже доставали.
В общем, нужно уходить в спячку до конца декабря!

Осенние проблемы и неприятности

4X_Pro
Наступила настоящая осень с серыми и мрачными днями, и это тут же сказалось на настроении. Раздражает все! В частности, то, что вчера, несмотря на то, что хотел наладить режим и выключить компьютер в 3:10, засиделся в Сети до 3:45, а спать лег каким-то образом все равно в 5 ночи. Тем не менее, сегодня заставил себя встать в 11:15, и теперь все валится из рук.
Еще опять посыпались проблемы. Всего пару дней назад я думал, что все, столкнул очередную freelance-задачу и теперь свободен, и уже почти было собрался прожить месяц в режиме «в Интернет только с МЦК», но тут посыпались неприятности. Сначала попытались подкинуть еще одну задачу, потом по завершенной задаче вылезло несколько мелких, но очень противных доработок. А потом вдруг написал один мой давний знакомый, с которым мы пытались сделать одну доработку его сайта в январе, но дело забуксовало, а теперь он о нем вспомнил.
А самое главное, что голова совсем не соображает, и поэтому ничего не могу делать: осенняя погода давит на психику. Весной или летом бы я все то же самое воспринял бы как мелкие неприятности, да и только. А сейчас все кажется мрачным и беспросветным. Причем вот что забавно: раньше я от жизненных неприятностей пытался убежать в Сеть, а сейчас ситуация меняется на обратную: хочу спрятаться в оффлайне, от всяких наведенных «надо», идущих из Сети.

Две прогулки: Кусково и Пресня

4X_Pro
Вчера отправился на длинную прогулку в Кусково. Как обычно, вышел из дома позже, чем хотел, где-то после 16 часов. Зато дошел до моста из Новогиреево в Кусково как раз в тот момент, когда закатное солнце отражается в рельсах железной дороги, проходящей под мостом, создавая удивительную игру света. И даже удалось это сфотографировать! Помнится, года два я собирался это сделать, и вот получилось. Правда, фотография все равно не передает полноту впечатлений.
А когда я дошел до Большого Дворцового пруда, уже начало темнеть. Я немного посидел на берегу. Подумал о том, что вот, какой уже раз прихожу сюда с мыслью «нужно бросить все и начать настоящую жизнь», где будет больше прогулок и впечатлений, а внимание не будет постоянно расфокусировано Интернетом. С другой стороны, также хочется заняться капитально своим сайтом и сайтовым движком. Но потом возвращаюсь домой и все снова получатся как обычно: поток жизни захватывает меня и тащит неизвестно куда.
Потом я еще прогулялся вдоль дальнего берега пруда и канала, а затем отправлся домой. Перехода по мостику над ж/д станцией Кусково нашел забавную надпись: «Народ проснись!» и ответ другим цветом и шрифтом: «Еще пять минуточек!». Сфотографировал ее и выложил в Instagram.
Сегодня с Tellой отправились в парк Красная Пресня. Туда собирались съездить очень давно, еще то ли с весны, то ли даже с прошлого года, но все никак не складывалось. Парк очень небольшой, но в целом произвел хорошее впечатление, несмотря на то, что некоторые его части сейчас отгорожены забором и недоступны. Необычен он прудом, который в нем имеется: по сути дела, это даже не пруд, а достаточно широкий канал необычной формы с несколькими мостами. В канале плавало немало уток, которые при виде нас сначала оживились, но когда поняли, что еды не будет, утратили к нам всякий интерес. Еще запомнилась необычная подсветка и вид на башни Москва-Сити, верхняя часть которых исчезала где-то в тумане. Еще был момент, когда чуть не поругались с Tellой из-за того, что она затронула неприятную для меня тему, а я на это резко отреагировал фразой «фильтруй базар!».
На обратном пути попали под холодный и неприятный дождь. А сейчас я в каком-то странном состоянии, и весь остаток дня ни на чем не могу сосредоточиться…

CodinGame: конкурс A*Craft завершился

4X_Pro
Сегодня закончился конкурс A*Craft на CodinGame. В отличие от предыдущих, он длился всего два с половиной дня и был не на игры, а на оптимизацию: нужно было расставить стрелки на карте так, чтобы сделать суммарный путь роботов по ней максимальным. Я занял 150-ое место из 2456! (Правда, примерно последние 500 участников — те, кто зарегистрировался, но даже не попытался прислать хоть какой-то код, и поэтому получившие 0 очков.) Это гораздо лучший показатель, чем во всех предыдущих конкурсах. Если считать в относительных показателях, то до этого мне максимум удавалось подняться до 84%, а в этот раз — до 93%, что близко к моему верхнему порогу амбициозности!
И это несмотря на то, что толком на конкурс не настроился, и до воскресенья подходил к нему как-то лениво. Впрочем, задачи по оптимизации даются мне проще сами по себе. Кроме того, код был основан примерно на том же рекурсивном алгоритме, который я впервые пытался применить еще в Code of Ctulu. Написал я его достаточно быстро, но потом обнаружился какой-то совершенно непонятный баг, на борьбу с которым ушла половина воскресенья. А причина оказалась банальной: я дважды использовал одно и то же имя result в одной функции, но подразумевая при этом две совершенно разных переменных: одну для поиска максимума, вторую — для хранения значения, которое будет возвращено из функции. В результате вместо максимума возвращался последний результат.
Из-за этого я только вечером воскресенья обнаружил, что хотя алгоритм хорошо справляется с картами из узких длинных коридоров, но дает довольно посредственные результаты на картах с большими смежными областями. Для таких карт я задумал было еще один алгоритм с совершенно другим подходом, но так его и не реализовал. Во-первых, не хватало времени, чтобы тщательно его обдумать и вытащить из зоны неуверенности. Во-вторых, нашел один случай, когда первый алгоритм (который рекурсивный) давал неоптимальный результат. Сначала казалось, что ошибка простая и ее удастся устранить быстро. Но все оказалось не так: я провозился с ней до глубокой ночи. А потом выяснилось, что ошибка действительно примитивная: я забываю вызвать .copy() при рекурсивном вызове функции, в результате чего вместо копии карты для поиска на следующем шаге передается ее исходный вариант и результаты поиска пути в разных направлениях начинают влиять друг на друга. Странно, что на остальных картах это работало! Причем выяснилось, что если на каждом шаге создавать копию карты, это занимает много времени, и в итоге на многих тестах начинается вылет по таймауту. Пришлось применить «костыльное» решение: написать условие, по которому принимается решение, делать копию или нет.
Поэтому вместо второго алгоритма сделал простую проверку: если карта с большими смежными областями, и роботов много, то для последних строить путь только до ближайшей уже размещенной стрелки. И, как это ни странно, это дало определенный результат: вместо 5400 очков, которые я набирал изначально, стало получаться 5700! А вот исправление того бага с копией дало всего лишь жалких 17 очков (впрочем, их оказалось достаточно, чтобы подняться еще на несколько мест).
Но вообще, наверное, надо было писать не на Python, а на PHP. Там и код быстрее выполняется (если в PHP 7), и копии массивов создаются автоматически (так что я бы не возился полдня с первым багом и, может быть, успел бы и второй алгоритм реализовать), причем в режиме copy-on-write, что тоже дало бы неплохую оптимизацию. Но увы, нельзя применять в качестве ключей для хеша связки из нескольких значений (то, что в Python называется tuples). Впрочем, при желании это можно было бы легко обойти.
Но в любом случае, я доволен результатом!

Задать вопрос

Здесь можно задать мне вопрос или спросить совета по любой теме, затронутой в блогах или на форуме. После того, как я отвечу, вопрос и ответ появятся в соответствующем разделе. Но не забываем, что я — сторонник slow life, поэтому каких-либо сроков ответов не обещаю. Самые интересные вопросы станут основой для новых тем на форуме или записей в блоге.
Сразу предупреждаю: глупости, провокации, троллинг и тому подобное летит прямо в /dev/null.