Евгений Степанищев

Этот сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

Принтер, MacOS и IPv6 часть вторая

К сожалению, ни отключение IPv6, ни фиксирование адреса IPv4 (ещё одна мера, которую я попробовал) не излечили полностью проблемы с принтером. Но в процессе копания в настройках, я обратил внимание, что у него очень старая прошивка — 2012 года. Подумал, может обновление решит проблему?

На сайте последняя прошивка датируется началом 2020-го, но беда в том, что программа под «МакОС», которая обновляет мою модель принтера, перестала поддерживаться много лет назад и просто не запускается (у меня — HP LaserJet Pro P1102w).

До и после обновления прошивки

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

В общем, поскольку под «МакОС» программа не работает, пришлось обновлять прошивку через «Виндоуз», благо у меня уже развёрнута виртуалка с Windows XP, которую я использую, чтобы переписывать фотографии, сделанные винтажными часами «Касио».

Поставил туда драйвер от принтера и программу для обновления прошивки. Где-то в интернете я прочитал, что прошивку следует обновлять через USB и потратил много времени, чтобы разыскать дома шнурок (в принтере используется USB-B), но оказалось, что всё происходит через вайфай.

Почему-то драйвера долго не хотели ставится, но в итоге с какой-то попытки установились. Что было не так — непонятно. После этого всё прошло без проблем — программа обновления прошивки сразу нашла принтер и за несколько минут его обновила.

Теперь остаётся наблюдать — решилась ли проблема.

Принтер, MacOS и IPv6

Я выключил IPv6 на принтере, но позже оказалось, что полностью проблема не решилась

Какое-то время назад один из домашних принтеров стал плохо работать с МакОСью — наши с женой «Макбуки» стали видеть его только после отключения от сети и включения обратно.

Я вообще привык, что в МакОСи постоянно что-то ломают, поэтому обычно просто жду, когда починят. Бывает, что ожидания не обманываются. Но тут время шло, раздражение росло, но ничего не менялось. Причём принтер нам нужен частенько и вот так с ним возиться каждый раз, когда надо печатать — очень неудобно.

Вчера решил зайти в его веб-интерфейс, подумал, вдруг замечу что-нибудь, что поможет решить проблему. Интуиция легонько звякнула, когда я увидел галочку IPv6. Решил попробовать выключить.

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

Веб-интерфейс принтера я нашёл следующим образом.

Cначала запустил из командной строки сканирование сети:

$ dns-sd -B _printer._tcp
Browsing for _printer._tcp
DATE: ---Mon 28 Apr 2025---
21:09:21.373  ...STARTING...
Timestamp     A/R    Flags  if Domain               Service Type         Instance Name
21:09:21.374  Add        2  14 local.               _printer._tcp.       HP LaserJet Professional P1102w

Потом запросил информацию о найденном принтере:

$ dns-sd -L "HP LaserJet Professional P1102w" _printer._tcp local.
Lookup HP LaserJet Professional P1102w._printer._tcp.local.
DATE: ---Mon 28 Apr 2025---
21:09:59.306  ...STARTING...
21:09:59.306  HP\032LaserJet\032Professional\032P1102w._printer._tcp.local. can be reached at NPI78BD4A.local.:515 (interface 14)
 txtvers=1 qtotal=1 rp=auto pdl=application/vnd.zeno-zjs,application/vnd.cups-raster ty=HP\ LaserJet\ Professional\ P1102w product=\(Hewlett-Packard\ HP\ LaserJet\ Professional\ P1102w\) priority=50 adminurl=http://192.168.0.127 usb_MFG=Hewlett-Packard usb_MDL=HP\ LaserJet\ Professional\ P1102w Transparent=T Binary=T

Адрес, на который надо зайти браузером, находится после подстроки adminurl=.

Митап по PHP

Признаюсь, я как-то подрастерял былой пыл в ведении моих записей, поэтому отлыниваю написать даже о самых ярких событиях, к которым я недавно имел отношение. Например, в прошлую субботу, 19 апреля наша компания устаивала митап по языку программирования PHP, а я был одним из её центральных организаторов.

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

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

Мы начали примерно за два месяца, тем не менее, кое-что пришлось делать буквально в последнюю неделю — например, только в последнюю неделю стало понятно сколько примерно народу придёт, потому что люди записывались и записывались. От количества зависело сколько арендовать стульев для сидения и столов для кофе-брейка, а так же количество еды.

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

Большое спасибо докладчиками — Александру Макарову, Максиму Пестову и Станиславу Кошевому за то, что вызвались поучаствовать и интересные доклады.

Видео я показать не могу, верьте на слово, — мы его принципиально не записывали. Если мы сделаем наши митапы регулярными, не будем записывать и впредь — наша идея в том, чтобы люди больше общались, хотя бы вынуждено, приходя вот на такие события.

Я (справа) объясняю что-то Максиму Пестову — одному из выступающих на нашем митапе
Александр Макаров, один из лидеров разработки фреймворка yii выступает на нашем митапе

Зима, угомонись

Когда мы были первый раз в Турции, помню, поразило, что, при всей компактности страны, можно за один день, сев в автомобиль, побывать в трёх климатических зонах.

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

P. S. Это новый для меня опыт — страдать аллергией на цветение посреди снегопада.

Первая дочкина программа

Время не сохранило мою первую программу. Из своих дневников жизни я прочитал, что она была на Бейсике для компьютера «Радио-86РК». Я едва помню сам этот факт, не говоря уже о том, что же я тогда написал. Жаль я не записал в дневник что делала та программа, сейчас мне самому интересно было бы взглянуть.

Поэтому я решил сохранить первую дочкину самостоятельную программу. Она написана на языке «Скретч». Два дня назад мы вместе попробовали написать программу по уроку на «Ютубе», а вчера дочка перед сном написала свою собственную.

Конечно, очень простая — нажимаешь на пробел, собака лает. Фон и звук взят из стандартной библиотеки.

Интернет всё мертвее

Теория мёртвого интернета — моя любимая конспирологическая теория, я полюбил её за то, что она единственная из всех может со временем стать реальностью. В этом году мы стали к её осуществлению немного ближе. Компания «Имперва» опубликовала исследование, согласно которому 51% всех пользователей интернета — это боты. Судя по опубликованным графикам, их доля от года к года растёт.

51 процент всех пользователей интернета — боты

Ну и вдогонку.

Я помню, где-то видел статью по поводу того, что самый популярный язык программирования — PostScript, на нём пишется больше всего программ. Дело в том, что он используется в принтерах. Каждый раз, когда вы что-то печатаете, ваши документы превращаются в программу на языке PostScript, которую пишет робот для принтера.

Если ещё вспомнить, что в Солнечной системы всего две населённые планеты — Земля и Марс, причём последняя населена исключительно роботами…

В общем, роботы уже общаются больше нас, программируют больше нас и отжали себе целую планету, где людям не место!

Старый Новый Завет

Чуть больше года назад у жены умерла бабушка со стороны мамы. Она была очень хорошей, доброй женщиной, мы все её очень любили. Дочка до сих пор плачет иногда, когда её вспоминает.

Мы попросили отдать нам какие-нибудь её вещи, чтобы в нашей семье осталась память о ней и получили старинный Новый Завет. Он в плохом состоянии, титульник утрачен, но по очень характерному рисунку на обложке я определил издание — это вторая половина 19-го века, синоидальная типография Санкт-Петербурга. Сейчас книга находится на реставрации в мастерской «Ваш реставратор».

Этот Новый Завет достался семье жены от прадедушки по линии бабушки — Александра Ивановича Андриянова. В молодости, ещё до революции Александр батрачил, а его будущая жена была дочерью богатых купцов Шуралёвых, живших в Арском районе. Её родители активно жертвовали на храм Казанской иконы Божией Матери, построенный в 1830 году в селе Старое Чурилино.

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

Александр Иванович Андриянов (4 ноября 1903—20 июля 1989) в центре, чуть правее — брат жены

В 1930 году храм закрыли: после последней службы чекисты выдворили верующих, а монахов и монахинь арестовали. Здание превратили в зернохранилище, позже — в склад ГСМ и резервный объект Казанского завода. Новый Завет, вероятно, попал к Александру Ивановичу в те годы, когда угроза закрытия церкви стала очевидной. Мама жены, его внучка вспоминает, что, по рассказам дедушки, он получил книгу ещё до брака. Значит это произошло до 1924 года, когда у него родился первый ребёнок. В советские годы книгу не афишировали, она лежала дома.

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

Аллергия-2025

Каждый год весной меня мучает аллергия. В этом году из-за тёплой весны она до меня добралась раньше, чем в прошлом — сразу по прилёте из Китая. Таблетки, как водится, помогают лишь ограниченно. Вроде должны были с прошлого года где-то остаться медицинские маски, но куда они подевались — непонятно, не нашёл. Заказал на «Озоне» новые, завтра должны прийти, дотерплю на таблетках.

Знаю парочку людей, которые этот период «переживают» — маски не носят, таблетки не пьют, терпят. Если про таблетки я ещё как-то понимаю, — есть много людей с иррациональным страхом любых медикаментов, то что не так с масками мне непонятно, спрашивать постеснялся.

С днём старого программиста!

Сегодня, оказывается старый день программиста или, как его ещё называют в шутку, «день старого программиста». 22 апреля совпадало когда-то с номером специальности 2204 или «Программное обеспечение вычислительной техники и автоматизированных систем», на которой учились советские ещё программисты, поэтому праздник праздновали в эти даты.

«Справочник для поступающих в высшие учебные заведения Российской Федерации в 1990 году», гос. из-во «Советская наука», 1990

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

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

Кроссплатформенность и bc

Как мы все знаем, в мире существует две версии bc — более скромная по возможностям версия GNU, которая используется в Линуксе, и более развитая, которая, например, используется в командной строке МакОСи.

Они довольно серьёзно различаются — когда я писал игру «Виселица» на этом языке, мне пришлось сделать две версии для разных синтаксисов.

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

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

Каким же образом мы можем это сделать?

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

Такую особенность я нашёл — она заключается в приоритете обработки операции отрицания, которая записывается как восклицательный знак.

Из-за этой разницы две версии по-разному вычисляют конструкцию !1+1. В продвинутой версии порядок выполнения следующий: (!1)+1, что даёт нам единицу, а в гнушной приоритет другой и конструкция выполнится так: !(1+1), что даёт нам ноль.

Основываясь на этом, мы можем написать универсальную функцию для получения случайного числа:

define rnd() {
    /* Checking the bc version */
    if (!1+1) {
        return rand()
    } else {
        return random() * random()
    }
}

P. S. Надо помнить, что в гну-версии функция получения случайного числа сломана, но есть надежда, что скоро её починят и ей можно будет пользоваться.

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

Джетлаг

В черновиках у меня давно лежала заметка как я прекрасно справляюсь с джетлагом.

В самом деле, обычно мне хватало дня-двух, чтобы перестроиться. Я считал, что это оборотная сторона моей «совиности» — как «сова» я привязан к суточному ритму солнца, что помогает мне справляться со сдвигом времени. По прилёте в Китай так и было.

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

Непонятно что такое во мне сломалось, может ли быть, что я потихоньку теряю свою «совиность» из-за того, что встаю не в своё время вот уже почти 14 лет?

Может быть и другое объяснение, конечно. Мы очень рано встали в день перелёта — в 4³⁰ утра, очень долго ждали посадки, потом ещё дольше летели. Может быть это просто сильная усталость от перелёта, наложившаяся на сдвиг часового пояса.

Последняя фотография, сделанная в Китае. Мы встали в 4³⁰ утра, чтобы сдать номер

Анонимные функции в PHP

Относительно недавно в ПХП появился новый способ создания анонимных функций. Раньше мы писали array_filter($strs, 'strlen'), теперь можем писать array_filter($strs, strlen(...)).

В первом случае у нас указывается строка, во втором — анонимная функция. Последнее намного лучше, конечно, потому что помогает строгой типизации и лучше понимается редакторами кода.

Когда этот синтаксис появился, в моей голове он стал частным случаем стрелочного синтаксиса. В самом деле, ведь fn($t) => sin($t) и sin(...) — это одно и то же. Но недавно я понял, что у второго синтаксиса есть побочный эффект. По какой-то причине раньше мне это было не очевидно.

Если посмотреть на код ниже, всё должно стать понятно, но если нет, то я поясню.

Тут мы видим класс, конструктор которого печатает код, находящийся в строке, которая его вызвала. Ниже класса создаются две анонимные функции, одна — стрелочная через fn(), вторая — через многоточие.

Этот код позволяет проиллюстрировать разницу.

В случае создания анонимной функции через fn(), конструктор будет вызван каждый раз заново на любой вызов функции.

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

То есть каждый способ имеет особенности, которые надо учитывать.

class Sample
{
    public function __construct()
    {
        $bt = debug_backtrace();
        ['line' => $line, 'file' => $filename] = end($bt);

        echo file($filename)[$line - 1];
    }

    public function method(): void
    {
    }
}

$a = fn() => (new Sample)->method(); // не выведет ничего
$b = (new Sample)->method(...); // выведется «$b = (new Sample)->method(...);»

$a(); $a(); // выведется «$a(); $a();» два раза
$b(); $b(); // не выведет ничего

GNU bc и random()

Я не задумывался об этом раньше, но это здорово сбивает с толку, что в мире есть две различающиеся версии bc — одна является частью проекта GNU и поставляется в дистрибутивах Линукса, а вторая развивается другим коллективом авторов и входит, например, в состав МакОСи.

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

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

Я подумал — чем чёрт не шутит? Если предложить своё исправление и в этот проект, то, может, его тоже примут? Так как открытого репозитория кода у bc проекта GNU нет, свой патч я отправил на почту мантейнеру.

Он ответил почти сразу, поблагодарил за исправление бага и написал, что сейчас же внесёт исправление в код. Так что, вероятно, следующая версия bc выйдет уже с нормально работающей функцией random()!

Задача «Шпионы и яд»

Давно хотел проверить не забыл ли я язык «Эр» («R»). В 2017-м много на нём программировал — было интересно изучить, но с тех пор как-то и не трогал. Интересно было посмотреть что в мозге осталось, а что улетучилось за восемь лет.

А тут — оказия, у Романа Парпалака в блоге появилась небольшая заметка о задаче «Шпионы за круглым столом»:

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

Он там её решает аналитически, а я подумал, что это удобный случай запрограммировать что-нибудь на «Эре». Притворимся, что не верим Роману и попробуем сравнить найденное решение и эксперимент (у меня проводится сто тысяч экспериментов на каждое число шпионов за столом).

Написал сначала, разумеется, «в лоб» — цикл в цикле в цикле: для каждого числа шпионов цикл по количеству экспериментов, где каждый шпион в цикле решает кого он будет травить. Получилось медленно — «Эр» не очень быстрый язык.

После чего я сделал всё более параллельно — сначала готовлю матрицу выбора, где строки — эксперименты. Каждый элемент матрицы содержит выбор — будет отравлен сосед слева или справа. Следующим шагом преобразую эту матрицу в другую, которая содержит уже позиции отравляемых за столом. Дальше в строках подсчитываются уникальные значения и получается количество отравленных. Если вычесть его из количество шпионов за столом, получится количество выживших. После этого уже совсем просто подсчитать требуемое.

С матрицами получилось намного быстрее, но недостаточно. Поэтому я применил ещё и модуль parallel, который умеет раскидывать задачи по ядрам. Там используются немного другие функции, но в остальном всё работает так же.

Если кому-нибудь хочется посмотреть на синтаксис «Эра», код есть у меня в репозитории.

Переводчик с китайского

Настоящая китайская загадка — где китайцы берут переводчик, которым переводят свои надписи. Больше половины надписей везде, куда ни кинь в Китае взгляд, написаны с какими-то совершенно дикими ошибками. Причём, не просто орфографическими, а смысловыми — иногда слова выглядят взятыми просто наобум.

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

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

Не желаете ли скачать торрент?
Ранее Ctrl + ↓