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

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

Лампочка во рту

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

Неясно было правда это или нет, но дураков экспериментаторов пробовать не было. Тогда другие времена были — интернет ещё не придумали. Но сейчас-то он есть, а в нём есть экспериментаторы!

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

Входит и замечательно выходит. Снято в более искреннюю эпоху — ещё на кнопочный телефон

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

Было, кстати, несколько видео, где лампочку вставить в рот не удалось, видимо это зависит от физических возможностей.

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

Контент смертен, это полбеды, плохо, что он смертен внезапно

Я застал время, когда в интернете только начинали появляться поисковые машины. Работали они неважнецки. Хорошо помню как от нечего делать пытался вводить в адресную строку придуманные из английских слов домены, чтобы найти хоть что-нибудь интересное. Житие тогда было тяжкое.

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

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

Но никакой поиск — это полбеды. Хуже всего, что со временем этот контент исчезнет навсегда. «Телеграм» помрёт, как умерла когда-то сверхпопулярная «аська», «Фейсбук» исчезнет, как исчез МайСпейс. Никакой «Веб-архив» это всё не сохранит.

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

Ещё немного про random() в bc

Как я уже рассказывал, bc под «Линуксом» очень старый, — на всех машинах, куда у меня есть доступ, установлена версия 1.07.1 2017-го года. Непонятно с чем связан такой консерватизм, но чем богаты. В этой версии отсутствует до печального много удобных вещей, например, функция для получения случайного числа.

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

Сегодня, пока ехал в такси, придумывал ещё более так себе способы это сделать.

Мысль моя крутилась вокруг запуска через утилиту env. В мире командной строки так частенько делают, так что этот способ как будто бы чуть более честный, так шелл тут не используется:

#!/usr/bin/env -S -i seed_="0${XDG_SESSION_ID};while(seed_--).=random()#" bc /proc/self/environ
print random()
quit()

Здорово, правда?

Вся чёрная магия сосредоточена в первой строке. Файл /proc/self/environ формируется в «Линуксе» для каждого запущенного процесса и содержит унаследованные переменные окружения. Так как там много ненужного нам мусора, очищаем его целиком при помощи ключа -i утилиты env.

Далее мы создаём переменную окружения seed_, а внутри её формируем небольшую программу, которая запустится до нашего кода. Для bc результат будет выглядеть так:

seed_=0123456
while(seed_--).=random()
#^@
print random()
quit()

Я развернул односрочную программу в многострочную для удобства.

Вместо 123456, конечно, будет подставлено число из переменной окружения $XDG_SESSION_ID, которая содержит число. Ноль там впереди, чтобы не случилось ничего страшного, если эта переменная в вашем дистрибутиве «Линукс» отсутствует.

Мне кажется, это неплохой способ, жаль только что содержимое $XDG_SESSION_ID остаётся одинаковым на всём протяжении жизни сессии. То есть, если запустить программу несколько раз в одном и том же окне терминала, случайные числа будут генерироваться всегда в одной и той же последовательности.

В конце файла /proc/self/environ всегда есть символ с кодом ноль, который мог бы нам всё испортить, но мы спрятали его за символом комментария — #.

Как видно, функция random() вызывается seed_ раз, что позволяет остановиться на каком-то случайном значении. Точка (.), которой я присваиваю random(), — специальная переменная bc. У неё есть значение, но, фактически, её частенько используют, чтобы присвоить куда-нибудь ненужные возвращаемые значения; иначе они попадут на экран.

Несложно додуматься до похожего способа, который позволяет читать число из какого-нибудь файла в системе. Нужно только, чтобы оно было там одно. Надо создать файл с содержимым seed_=\ и подключить его до файла с числом. Файлы подключаются через перевод строки, действие которого отменяет слеш, так что число, опять же, попадёт в переменную seed_. Дальше всё как в предыдущем примере.

Использую ли я «Флиппер»

У меня тут спросили, использую ли «Флиппер Зеро», — давно ничего про него не рассказывал. Использую, конечно, и очень интенсивно! С тех пор как потерял магнитный ключ от подъезда, каждый день туда и обратно прохожу, прикладывая вместо него «Флиппер». Всё недосуг заняться этим вопросом.

Хорошо, что ещё в самом начале я записал на «Флиппер» данные всех магнитных ключей, которые у меня были — домашний, рабочий, родственников и так далее.

Дочкино печенье

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

Замешала тесто, нанесла всё на противень, подстелив бумагу для готовки, и поставила выпекаться в духовку.

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

Печенье оказались вкусными, мы их съели почти сразу, еле успел сфотографировать.

Англо-русский словарь на bc

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

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

Сделал так же, как в версии под «Линукс» — bc переводится на ввод 36-ричных чисел. В таком режиме слова у нас становятся числами.

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

Так что я поступил иначе — проверяю версию bc и, если она достаточной новая (как под «Маком»), запускаю bc через tr, который заменяет буквы в нижнем регистре на буквы в верхнем. В этом случае, начало программы выглядит так:

#!/bin/sh
c=/*
tr -u a-z A-Z | bc -R "$0"
exit; */1

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

Сам словарь нашёлся в интернете. Чтобы не заливать в свой репозиторий чужую интеллектуальную собственность, я сделал make-файл, генерирующий мне программу на bc — словарь скачивается, распаковывается и обрабатывается специально написанной программой на Пайтоне. В итоге получается программа на пятьдесят тысяч с гаком строк.

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

Чтобы минимизировать программу по объёму, я сделал два цикла, а останов поиска делаю через break — он позволяет выйти из внутреннего цикла к началу внешнего:

while(c) while (c) {
ibase=36;c=read();ibase=A

if(c==19976){"Несколько";break}
/* тут очень много строк */
if(c==2813515210532){"Сухарь";break}
if(c==2174201762){"Зигота";break}
"Неизвестное слово";}
quit()

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

Результат, как обычно, можно увидеть в моём репозитории.

Игра «Виселица» на bc под «Линукс»

Я планировал заняться адаптацией «Виселицы» на bc под «Линукс» на следующий день, то есть сегодня, но не выдержал и вчера просидел над этим почти до полуночи. Линуксовый bc, конечно, гораздо скромнее по возножностям, было где поломать мозг, но больше всего времени я, кажется, потратил на рандомизацию.

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

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

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

Для этого я изменил способ запуска программы — сделал его шелл-скриптом, который передаёт в bc на инициализации цикл, генерирующий случайное количество вызовов random():

#!/bin/bash
x=/*
BC_LINE_LENGTH=0 bc -l -q <(/usr/bin/seq -f "x=random()+%g" $RANDOM) "$0"
exit; */1

Обвязка с комментарием сделана так, чтобы и шелл, и bc не увидели в коде ничего странно и не выдали ошибку синтаксиса, а вся мякотка происходит в строке /usr/bin/seq -f "x=random()+%g" $RANDOM. Команда seq генерирует последовательность x=random()+число столько раз, сколько указано в переменной $RANDOM. $RANDOM — это специальная переменная шелла, которая содержит случайное значение.

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

Ещё одной крупной проблемой стали строки — в этой версии bc не поддерживается присваивание их переменным. Из-за этого код пришлось сильно переделать.

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

define void print_letter(c) {
    if(!--c){"a"}
    if(!--c){"b"}
    if(!--c){"c"}
    /* …тут все 26 букв */
    if(!--c){"y"}
    if(!--c){"z"}
}

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

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

define read_letter() {
    auto z, b
    b = ibase
    ibase = 36

    z = read()
    ibase = b
    return z - 9
}

Переменная ibase отвечает за систему исчисления при вводе чисел.

Таким образом, численное исчисление получили не только все одиночные буквы, но и все слова. В теории, это можно использовать для ввода одиночных команд на английском языке. Я использую это свойство, чтобы распознать команду exit.

Остальные проблемы решались попроще. Ещё я немного поломал голову чем заменить ceil (округление вверх), потом догадался прибавить единицу и, выставив через специальную переменную scale нулевую точность для цифр после запятой, разделил получившееся значение на один, чтобы отбросить дробную часть:

define word_len(c) {
    auto r
    scale=10
    r = l(c) / l(256) + 1
    scale=0
    return r/1
}

Функцию логарифма log() тут пришлось заменить на натуральный логарифм l() — это одна из немногих математических функций, которые поддерживаются в этой версии bc.

Остальные замены довольно тривиальны, я писал о них ещё в прошлый раз. Результат положил отдельным файлом в моём репозитории.

Игра «Виселица» на bc

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

В силу специфики обработки ввода bc, писать нужно что-то пошаговое — фоновое выполнение не поддерживается, программа может работать только от ввода до ввода. Долго не размышляя, я как-то сразу решил написать игру «Виселица». Я её уже писал под «Флиппер», если помните.

Игровой процесс игры «Веселица», написанной на bc

На пути к успеху сразу начались трудности. Несмотря на то, что в bc есть многообещающая функция read(), оказалось, что с её помощью можно вводить только выражения языка и числа. В вышеупомянутом «пасьянсе» автор обошёлся числами, а мне нужны буквы, иначе играть будет невозможно.

К счастью, «выражения» — это ещё и переменные. Если задать значения всем однобуквенным переменным, мы сможем определить какую именно букву нажал пользователь.

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

a=1;b=2;c=3;d=4;e=5;f=6;g=7;h=8;i=9;j=10;k=11;l=12;m=13;n=14;o=15;p=16;q=17;r=18;s=19;t=20
u=21;v=22;w=23;x=24;y=25;z=26

co[a]="a";co[b]="b";co[c]="c";co[d]="d";co[e]="e";co[f]="f";co[g]="g";co[h]="h";co[i]="i";co[j]="j"
co[k]="k";co[l]="l";co[m]="m";co[n]="n";co[o]="o";co[p]="p";co[q]="q";co[r]="r";co[s]="s";co[t]="t"
co[u]="u";co[v]="v";co[w]="w";co[x]="x";co[y]="y";co[z]="z"

exit = -1

Заодно я задал значение переменной exit, это слово пользователь может ввести, чтобы выйти.

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

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

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

define get_word(c) {
    if(!--c) return 4328588043
    if(!--c) return 4328588820
    /* и так далее */
    if(!--c) return 437194509

    return -c
}

word = get_word(irand(get_word(0)) + 1)

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

Функция irand, используемая тут, является расширением bc, у меня на «Маке» она поддерживается, но под «Линуксом» её нет, так же как и вообще любой другой функции для работы со случайными числами.

С такими «строками» можно уже как-то работать, например, считать длину, чтобы вывести подходящее количество «окошек», в которых будут появляться буквы:

define word_len(c) {
    scale=10
    return ceil(log(c, 256), 0)
}

Или вывести на печать:

define void print_word(c) {
    auto word, i, mod

    scale=0
    for (i = 0; c; i++) {
        c = divmod(c, 256, mod[])
        word[i] = mod[0]
    }

    while (i--) {
        print co[word[i]]
    }
}

В общем, всё как с обычными строками, только чуть-чуть очень сильно неудобно.

Остальное, в общем-то, писать было просто — логика игры очень простая, пишется за несколько минут. На результат можно посмотреть в моём репозитории на «Гитхабе».

В теории, игру можно портировать и на «Линукс», надо только избавиться от хранения строк в переменных, заменить генерацию случайных чисел на внешний генератор, заменить log() на l(), а divmod() на деление и взятие модуля и избавиться от length() — массив в качестве аргумента в «Линуксе» не поддерживается.

Зелёная зима

Зима в этом году, конечно, удивительная. Во дворе уже всё меньше снега и всё больше травы, даже на кустах уже набухли почки. Немудрено — температура прыгает около нуля, чаще выше, чем ниже. Говорят весь склон под кремлём покрыт травой. У меня была мысль сходить туда, сфоткаться в футболке, когда я ещё в Казани в январе на зелёном газоне посижу? Но поленился, а сегодня, смотрю, уже снег выпал — температура упала до −1°C.

99 бутылок: калькулятор bc

Разбирал одну старенькую научную статью с некоторым количеством математики, а внутри увидел вычисления на bc.

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

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

82. bc — интерактивный интерпретатор Си-подобного языка, появившийся ещё в 1975 году как интерфейс для утилиты dc, на котором «песню о пиве» я уже писал. Утилита dc выполняла вычисления с произвольной точностью, используя обратную польскую запись, а bc предоставила более привычный Си-подобный синтаксис, транслируя его в команды dc. В 1991 году утилита bc была стандартизирована POSIX, и сегодня существует несколько её реализаций.

/* Beer song. Evgeny Stepanischev, Jan 2025 */

define void bottles(b) {
    if (b) print b else print "No"
    " bottle"
    if (b-1) print "s"
    " of beer"
}

for(beer = 99; beer;) {
    bottles(beer); " on the wall, "
    bottles(beer); print "!\n"

    print "Take one down, pass it around,\n"
    bottles(--beer); print " on the wall!\n\n"
}

print "No more bottles of beer on the wall,\n"
print "No more bottles of beer!\n"
print "Go to the store and buy some more,\n"
bottles(99); " on the wall!"

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

Никаких других сложностей с этой программой у меня не возникло, язык простой, хорошо продуманный, лёгок в освоении.

Лупа для пайки

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

Ну что я могу сказать? Зрение уже не то, мне нужна лупа. Запаял полтора резистора наощупь, начал паять четвёртую ножку, не припаивается нормально. У основания олова нет, это я разобрать могу, но толком ничего не вижу, тыкаю припоем почти наугад.

Интересно, есть ли обзоры луп для паяния, надо бы посмотреть. Хочется купить что-нибудь нормальное.

Девочка Кинсу

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

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

Получилась по-детски наивная, но довольно интересная история про девочку Кинсу.


Юная писательница с домашним питомцем

Всем привет! Это моя книга, и сегодня я расскажу о себе. Меня зовут Кинсу, мне 18 лет. Я ухожу из дома и ищу работу. Вы, наверное, спросите, какая работа у меня будет? Не знаю, наверное, скучная, как я в детстве себя представляла. Начинаем рассказ.

Кинсу ушла с работы и вдруг нашла странный предмет. Она посмотрела на него: он был жёлтый и какой-то очень странный. Он был похож на камень, но нет, у него были очень странные узоры. Она подумала: «Что это? Надо загуглить в интернете». И пошла домой. Пошла она домой, легла спать, а предмет начал светиться. Из него пошёл красный дым. Под утро этот предмет испарился, и Кинсу его не нашла. Она подумала: «Ну, не знаю, может это грабители». Но оказалось, что в доме никого не было. Она посмотрела на свою руку и вдруг заметила очень странный знак. Он напоминал созвездие Большой Медведицы. Она подумала: «Откуда это у меня? Может, я татушку нарисовала, но забыла?» И пошла дальше.

Квартира у неё была съёмная, она об этом ещё не рассказывала. Она не заметила, что у неё начал расти небольшой хвост, крылья и уши, как у лисы. Она как будто начала превращаться в какого-то зверя, но сама этого не поняла и пошла на работу. Пришла на работу, и все начали странно на неё смотреть. Вдруг она встретила двух симпатичных парней и подумала: «Может, мне с ними познакомиться?» Но они начали её обижать. Лиза была предводительницей этих парней, они её очень любили и исполняли всё, что она говорила. Они притащили Кинсу к Лизе, и один из парней ударил её. Кинсу сильно укусила его, пошла кровь, и они отпустили её. Она убежала.

На следующий день её уволили. Она очень расстроилась, но пошла в зоомагазин. Там она увидела красивую собаку. У неё осталось немного денег, и она решила её купить. Собака оказалась очень красивой и послушной овчаркой. Кинсу даже заплакала от счастья, когда её купила, и пошла домой со своей новой подругой.

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

В общем, Кинсу пришла с работы и сказала собаке: «Привет, Галя!» — так она её назвала. Вдруг неожиданно собака ответила: «Привет, Кинсу!» Кинсу подпрыгнула от страха. Собака сказала: «Спасибо, что не боишься меня. Мы с тобой друзья, не бойся». Кинсу ответила: «Я не испугалась, но почему ты говоришь?» Собака объяснила: «Я всегда умела говорить, только ты теперь научилась меня слышать». Кинсу удивилась: «Понятно, наверное, я сплю». Но собака ответила: «Нет, ты не спишь». Кинсу спросила: «Тогда почему ты говоришь? Ты же никогда раньше не говорила, и другие собаки не умеют говорить». Собака ответила: «Ты научилась нас слушать». Кинсу задумалась: «Ага, понятно. Значит, я каким-то образом научилась вас понимать. Объясни, моя чудесная собачка Галя, как это произошло?»

Галя спросила: «Помнишь, ты подобрала камешек на улице, когда шла на свою первую работу?» Кинсу ответила: «Да, помню. А что он сделал со мной?» Галя объяснила: «Он волшебный. Его создали, чтобы восстановить вселенную, которая погибла из-за страшной болезни. Тебе надо подружиться с духами стихий, чтобы спасти всё». Кинсу не совсем поняла, но согласилась: «Ага, спасибо, Галя». Собака добавила: «Тебе надо начать с Жизнь, с ним легче всех». Кинсу спросила: «А где его искать?» Галя ответила: «Ищи там, где живёшь. Это твоя жизнь».

Кинсу жила в однокомнатной квартире и никого там не видела. Галя объяснила: «Он приходит к тебе каждую ночь». Кинсу удивилась: «А почему именно ночью?» Собака ответила: «Он боится, что его увидят». Кинсу взяла Галю на поводок, и они пошли на прогулку. Гуляли долго, пока не наступил вечер. Галя сказала: «Пошли домой, уже поздно. Скоро будем встречать его». Они вернулись домой, Кинсу всё подготовила и стала ждать.

Вдруг она услышала голос: «Привет, все ли живы? Кому пора наверх?» Это был голос Жизни. Он звал своего брата, Смерть, и говорил, что они создают новые жизни. Кинсу спросила: «А мне можно тоже ребёночка?» Галя ответила: «Есть у меня один на примете». Кинсу заинтересовалась: «Кто это?» Галя сказала: «Энит». Кинсу спросила: «Где он живёт и как мне с ним познакомиться? У меня столько вопросов, но я стесняюсь и не хочу замуж». Галя успокоила её: «Тише, он пришёл».

Жизнь подошёл к столу и прочитал записку, написанную красивым аккуратным почерком: «Мы ждём тебя». Он сказал: «Выходите, кто меня ждал, но вы меня ещё не увидите, потому что я невидимка и не услышите». Вдруг из-за дивана вылезла Кинсу и сказала: «Я тебя вижу и слышу». Жизнь удивился: «Почему?» Кинсу ответила: «Не знаю, моя собака говорит, что я подобрала какой-то камешек, из-за него я научилась видеть духов и говорить с животными». Жизнь спросил: «Это жёлтый, немного прямоугольный камень?» Кинсу подтвердила: «Да». Жизнь объяснил: «Тебе надо подружиться со всеми духами. Я первый».

Вдруг из-за дивана вылезла Галя и сказала: «Здравствуйте, уважаемый Жизнь». Жизнь удивился: «А вы кто?» Галя ответила: «Я Галя, а вас зовут Жизнь, правильно?» Жизнь подтвердил: «Да, правильно. А тебя как зовут, девочка?» Кинсу ответила: «Меня зовут Кинсу». Жизнь сказал: «Понятно, а я — Жизнь. Вот и познакомились. А кто у вас следующий по списку или у вас нет списка?» «Нет» — ответили они. Жизнь сказала: «Следующий — Смерть» и предупредил: «С ним будет посложнее. Вы не боитесь кладбищ и ужастиков?» Кинсу и Галя ответили: «Нет». Жизнь сказал: «Тогда пошлите в его дом. У него там страшновато». «А что там такого, наверняка дом как дом» — спросили Кинсу и Галя. «Не просто дом, у него там страшно, как на кладбище, вы точно не боитесь идти к нему знакомиться?» — спросил Жизнь.

Они пошли к дому Смерти. По дороге Жизнь вёл себя странно. Кинсу спросила: «Ты что, испугался?» Жизнь ответил: «Нет». Кинсу удивилась: «Тогда почему ты дрожишь?» Жизнь ответил: «Я не дрожу, это кто-то другой». Кинсу и Галя засмеялись. Жизнь сказал: «Как по-моему, нет ничего смешного в том, что человек боится Смерти». «Ну ты же Жизнь, а не человек, разница в том, что люди умирают, а ты — нет» — сказали Кинсу с Галей. Вдруг из-за их спины появилась Смерть. Все закричали: «Ааа!» Смерть спросил: «Ладно, хорошо, зачем пришли?» Кинсу выступила вперёд и смело сказала: «Я случайно подобрала камешек, который говорит, что вы создали Жизнь. Я пришла, чтобы объединиться с вами и что-то спасти». «А что спасти?» — спросила она у Гали. «Спасти вселенную» — шепнула Галя на ухо подруге. «А, точно, вспомнила, чтобы спасти вселенную» — сказала Кинсу. Смерть ответил: «Понятно. Тогда действуйте быстрее, у нас времени нет, чтобы знакомиться. Тебе надо собрать всех духов и восстановить вселенную. У тебя уже есть две суперсилы».

Они пошли дальше. Жизнь шепнул Кинсу: «Я же говорил, что будет сложно». Кинсу отмахнулась: «Ты много чего говоришь». Они нашли Ночь, которая облетала землю, чтобы везде был покой. Кинсу крикнула: «Привет!» Ночь удивилась: «Кто ты и почему видишь меня и почему с тобой Жизнь и Смерть?» Кинсу объяснила: «Мы собираем все суперсилы, чтобы восстановить вселенную». Ночь согласилась помочь.

Они пошли по поиски ещё одной суперсилы и не заметили, что за ним следят агенты. Агенты следили, пытаясь понять, что делает Кинсу с собаками и суперсилами.

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

Жизнь, Смерть, День, Ночь и Галя пошли на поиски следующей суперсилы, а девочка осталась одна. Увидев это на неё накинулись агенты и пытались поймать её сетью. Они удивились, увидев, как Кинсу превратилась в лошадь и убежала. Агенты позвонили начальству по рации и сообщили: «Девушка сбежала из наших сетей и превратилась в лошадь». Кинсу и её друзья продолжали поиски. Они нашли все суперсилы: Жизнь, Смерть, Утро, День, Вечер, Ночь, Воздух, Землю, Огонь и Воду. Кинсу сказала: «Я очень устала, может мне использовать свою магию?» Смерть ответил: «Как хочешь». Кинсу использовала магию и создала палатку, спальники и даже костюмы всем.

Потом они сказали: «Может ты нам лучше дом сделаешь?», она убрала созданное и сделала большой красивый замок с лошадьми и остальными животными, которых она очень любила, и отдельные комнаты для каждой суперсилы.

Вдруг она нашла яйцо в тронном зале своего замка, она очень удивилась, потому что его не колдовала. Все сказали: «Это яйцо твоей души. Оно появилось, потому что всё, что ты загадываешь, ты загадываешь от души». Агенты, которые стояли в комплекте из брони недалеко и готовились напасть, испугались и убежали, увидев замок и передали по рации, все отстать от этой девушки. На следующий день из яйца вылупился красивый дракон. Он был синего, фиолетового и розового цветов, с длинными лапами, хвостом и красивыми могучими чёрными крыльями. Дракон подружился с Кинсу.

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

Почему Дуолинго

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

Мистер Сова ненавязчиво напоминает о занятиях английским

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

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

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

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

Полезный промпт

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

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

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

К счастью, есть полезный промпт, позволяющий и это переложить на нейросеть. Достаточно попросить её задать вам несколько вопросов по теме.

Например, нам надо поздравить с днём рождения друга Вадима. У нас туго с фантазией и мы хотим поручить эту задачу нейросети.

Можно написать «напиши мне поздравления с днём рождения моего друга Вадима» и получить более-менее стандартный текст. Что нейросеть может знать о Вадиме? Что за Вадим вообще? Например, что ему было бы приятно прочитать в поздравлении? Откуда нейросети это знать?

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

Дуодециллион

Прочитал с утра, что долг компании «Гугл» российским телеканалам достиг 1,81 дуодециллиона. Интересно стало когда долг достигнет числа гугол — единицы со ста нулями. Ведь название «Гугл» произошло именно от этого числа.

Сумма штрафа удваивается каждую неделю, то есть в один момент 2×2×…×2×2×1,81×10³⁹ должно стать больше или равно 10¹⁰⁰. Можно прикинуть на «Пайтоне»: math.log(1e61 / 1.81, 2) (нули у чисел я сократил).

Вышло чуть больше 201 недели — это почти четыре года.

Ранее Ctrl + ↓