LE Blog

Инженер с поэтической душой

12.02.2018 firtree_right Лось квайн

Давненько я не писал чисто программерского! Есть такая прекрасная маргинальная область: бесполезная дурня. Для меня — это совершенно точно искусство, как оно есть, только для очень узкого круга людей. Более ли менее известный пример — это Simone Giertz – Королева говёных роботов. Я сам бесконечно уважаю бесполезную дурню. О некоторых штуках я даже писал ранее. Например, про лося в терминале или про JSFuck. Сегодня хочу рассказать про моё свежее улечение — квайны. И похвастаться, конечно.

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

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

лось

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

eval a = <<-'a'
# Мой код
puts "eval a = <<-'a'\n#{a}a"
a

После пошёл читать код такого же любителя странного — Юсуке Эндо (Yusuke Endoh). Он, среди прочего, написал квайн-реле, которое выводит на каждом шагу код на другом языке. И если его запустить на 128 языках 128 раз, то оно выведет обратно исходный код на первом языке. Чувак тоже относится к программированию как к искусству. Странному, гиковскому, маргинальному, нердическому, но при этом Великому и Бессмысленному Искусству. Например, он написал книгу, которая называется «The World of Obfuscated, Esoteric, Artistic Programming». Конечно же, на японском. И врядли её переведут ( ≧Д≦) Или у него есть «Квайн, устойчивый к радиации», из которого можно удалить одну любую букву и он при запуске выведет восстановленный исходный код. Ещё и в аски-графике.

Вот вам видео последней версии квайна, вдохновленное товарищем Эндо. Отлично провёл время, в общем. А у вас как дела?

Материалы для самостоятельного изучения

  1. Исходный код квайна с лосём, история и анимированная версия
  2. Статья на английском, которая неплохо раскладывает по полочкам
  3. Слайды презентации Юсуке Эндо про его странные увлечения
  4. Монументальное квайн-реле на его гитхабе

02.03.2016 firtree_right Лось

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

Терминал

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

лось в терминале

При этом хотелось бы, чтобы у него было разное случайное выражение лица. Для этого нужно в ~/.bash_profile (или какой у вас файл для создания окружения) написать следующее:

eye=(o O @ . - \* \~ °)
let left=${RANDOM}%${#eye[*]}
let right=${RANDOM}%${#eye[*]}

cat << EOF

 _  _        _  _  _
| || | ____ | || || |
\    |/    \|      /
 \____ ${eye[$left]}  ${eye[$right]} ______/
      |    |________
      |             }=
      | __  ____  _ |
      ||  ||    || ||
      ||  ||    || ||
      ""  ""    "" ""

EOF

Базовая работа с массивами. Встроенная в баш функция случайного числа. Обязательно предварять косой чертой «*» и «~», чтобы они не стали списком файлов и домашней директорией. По-моему — красота!

Spec runner

И, конечно же, для любителей разработки через тестирование нужен правильный репортер:

![elk-spec](/images/leru/0039/elk-spec.gif)

Здесь нужно пользоваться эскейп кодами для управления положением каретки, то есть курсора. Мало кто помнит, но курсор можно двигать во все стороны на любое количество позиций. Данный пример я собрал для раннера тестов на жасмине. Да, да, я разрабатываю в том числе на node.js и тестирую с помощью jasmine. Ключевая функция для рисования лося вот:

function printElk() {
  if (specCount > 1) {
    print('\x1b[5A');
  }
  if (specCount % 2 === 0) {
    print(Array(specCount + 1).join(' ') + '     ^^' + eyes() + '^^\n');
    print(Array(specCount + 1).join(' ') + '  _____ U\n');
    print(specTrail + '~(  _  /\n');
    print(Array(specCount + 1).join(' ') + '  || ||\n');
    print(Array(specCount + 1).join(' ') + '  ^^ ^^\n');
  } else {
    print(Array(specCount + 1).join(' ') + '      ^^' + eyes() + '^^\n');
    print(Array(specCount + 1).join(' ') + '  _____ U\n');
    print(specTrail + '`(  _  /\n');
    print(Array(specCount + 1).join(' ') + '  // \\\\\n');
    print(Array(specCount + 1).join(' ') + ' ^^   ^^\n');
  }
}

Здесь specTrail и eyes следят за историей вопроса, а вся функция вместо того, чтобы как раньше, ставить точку или F, поднимается на пять строчек вверх и переписывает их полностью.

Бонус

Это не про лося, но тем не менее. Вообще, я считаю, что всегда лучше потратить немного времени, чтобы сделать всё удобно и интересно. Мелочи решают!

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

export PS1="\[\e]0;\u@\h: \W\a\`if [ \$? = 0 ];then echo \[\e[32m\]^_^\[\e[0m\];else echo \[\e[31m\]o_O\[\e[0m\];fi\`[\u@\h: \w][\$(rvm-prompt v)][\$(nvm_version)]\$(parse_git_branch)\$ "

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

\`if [ \$? = 0 ];then echo \[\e[32m\]^_^\[\e[0m\];else echo \[\e[31m\]o_O\[\e[0m\];fi\`

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

Материалы для самостоятельного изучения

  1. $RANDOM.
  2. elk_reporter.js.
  3. Управление курсором в баше.