Category: напитки

Category was added automatically. Read all entries about "напитки".

кукяй

«99 бутылок» на баше без цикла

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

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

#!/bin/bash
echo -e "99 bottles of beer on the wall, 99 bottles of beer.
Take one down and pass it around, 98 bottles of beer on the wall.\n"
: ${i:=99}; ((--i)) && (grep -B5 -m1 ^G "$0" |
sed "s/9[8]/$(($i-1))/g;s/9[9]/$i/g;s/ [0] / no /;s/\([1] b[^s]*\)s/\\1/g" >> "$0") ||
(echo 'No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.';truncate -s 437 "$0")
:;

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

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

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



Ссылка на оригинал.
кукяй

99 бутылок: Psql (переработанная версия)

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

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

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

Таблицу замен я реализовал через девять переменных с числовыми именами, значением которых является число на единицу меньше имени. Например: \set 9 8 — тут переменная с именем 9 получает значение 8.

Чтобы реализовать вычитание единицы, пришлось разделить счётчик цикла на две переменные — beer_h (старший разряд) и beer_l (младший разряд), вычитание производится для каждой цифры отдельно. На диск записывается код, в который помещается имя переменной и её новое значение, используя текущее значение, как имя переменной, из которой надо взять следующее. Понимаю, что запутанно, надеюсь на примере понять будет проще.

Вот этот кусок: \qecho '\\set beer_h :':beer_h. Если текущее значение переменной beer_h равно 9, то на диск будет помещен скрипт с содержимым \set beer_h :9, после его подключения код выполнится, а так как значение переменной 9 — 8, то beer_h получит значение 8.

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

С кодогенерацией, кстати, работать веселее — сгенерированный код потом можно использовать как некий аналог подпрограмм, экономя размер кода.

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

\if 0
    99.psql
    Psql beer song v.2
    Written by Evgeny Stepanischev https://bolknote.ru
\endif

\if :{?beer_l} \else
    \set 9 8 \set 8 7 \set 7 6 \set 6 5 \set 5 4 \set 4 3 \set 3 2 \set 2 1 \set 1 0
    \set print /tmp/beer_print.sql
    \set minus /tmp/beer_minus.psql

    \out :print
    \qecho '\\if :{?beer_h_value_0} \\echo -n :beer_l'
    \qecho '\\else \\echo -n :beer_h:beer_l \\endif'

    \set beer_h 9
    \set beer_l 9
    \set s s
\endif

\include :print
\echo -n ' bottle':s' of beer on the wall, '
\include :print
\echo ' bottle':s' of beer.'

\if :{?beer_l_value_0}
    \unset beer_l_value_0
    \set beer_l 9
    \out :minus
    \qecho '\\set beer_h :':beer_h '\\set beer_h_value_:':beer_h 1
    \include :minus
\else
    \out :minus
    \qecho '\\set beer_l :':beer_l '\\set beer_l_value_:':beer_l 1
    \include :minus
\endif

\if :{?beer_h_value_0}
    \if :{?beer_l_value_1}
        \set s
    \endif
    \if :{?beer_l_value_0}
        \echo Take one down and pass it around, no bottles of beer.'\n'
        \echo No more bottles of beer on the wall, no more bottles of beer.
        \echo Go to the store and buy some more, 99 bottles of beer on the wall.
        \q
    \endif
\else
    \unset beer_l_value_1
\endif

\echo -n 'Take one down and pass it around, '
\include :print
\echo ' bottle':s' of beer.\n'

\include_relative 99.psql


Ссылка на оригинал.
кукяй

99 бутылок: Psql

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

75. Psql — не язык программирования, а клиентская программа, распространяемая вместе с СУБД «Постгрес». У неё есть довольно скромный встроенный язык, в который относительно недавно добавили условный блок.

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

\if 0
    99.psql
    Psql beer song
    Written by Evgeny Stepanischev https://bolknote.ru
\endif 

\if :{?beer} \else \set beer 99 \endif
\echo :beer bottles of beer on the wall, :beer bottles of beer.

select :beer-1 beer, :beer > 2 notend \g /dev/null
\gset

\if :notend \set s s \else \set s \endif

\echo Take one down and pass it around, :beer bottle:s of beer.'\n'

\if :notend
    \include_relative 99.psql
\else
    \echo 1 bottle of beer on the wall, 1 bottle of beer.
    \echo Take one down and pass it around, no bottle:s of beer.'\n'
    \echo No more bottles of beer on the wall, no more bottles of beer.
    \echo Go to the store and buy some more, 99 bottles of beer on the wall.
\endif

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

:{?beer} — синтаксис проверки существования переменной, это нужно чтобы понять запускаем ли мы программу в первый раз или включили её в себя же, чтобы имитировать цикл.

select :beer-1 beer, :beer > 2 notend — эскуэль-запрос, которым делается математика и сравнение — вычитается единица из переменной и проверяется не пора ли выходить из цикла.

\g /dev/null — запуск запроса в выводом результата в /dev/null (то есть в никуда), поскольку его результат на экране нам не нужен.

\gset — записываем результат запроса в переменные, имена которых равны именам столбцов запроса.

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



Ссылка на оригинал.
кукяй

«Я тебя по IP вычислю»

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

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

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

Посмотрел его айпи-адрес (в те времена очень у многих они были «белыми»), оказалось — это адрес диалап-пула одного из казанских провайдеров. Поскольку айтишная Казань в те годы была маленькая и все друг друга знали, написал знакомому админу, который там работал, он мне за пиво выдал имя и фамилию абонента, этого хватило, чтобы навсегда отвадить его от чата, — получив в личку своё ФИО, хам моментально пропал с горизонта.



Ссылка на оригинал.
кукяй

99 бутылок: Старсет

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

74. Старсет — язык программирования высокого уровня, разработанный в Институте программных систем РАН в 1991 году. К сожалению, мне удалось обнаружить компиляторов или интерпретаторов этого языка, и даже упоминания, что они вообще когда-либо были реализованы.

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

Книга «Язык программирования Старсет», М. М. Гилула, А. П. Столбоушкин, М., «Наука», 1991

Язык, кстати говоря, небезынтересный — в наличие имеется развитая работа с множествами и свой язык регулярных выражений («образцов»), который может применяться не только на скалярах, но и на множествах! Кроме того имеются операторы, позволяющие распараллеливать вычисления!

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

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

Каноническим числовым представлением нуля будем считать слово 0. В частности, каноническим числовым значением слова 1 является оно само, каноническим представлением слова 2 является слово −6, каноническим представлением слова 3 — слово 67000000000000000.

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

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

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

/* Считалочка про пиво на языке «Старсет». Написал Евгений Степанищев */
/* https://bolknote.ru */

Func Бутылки(колво)
    Word: Бутылки, колво;

    Choice
        Case колво = 1 Do Бутылки := '1 bottle' End
        Case колво = 0 Do Бутылки := 'no bottles' End
        Otherwise Do Бутылки := колво^' bottles' End
Endfunc

Proc Песня()
    Word: колво, бутылок;

    колво := 99;
    бутылок := Бутылки(колво);

    While колво > 0 Do
        Write бутылок^' of beer on the wall, '^бутылок^' of beer.';
        колво := колво - 1;
        бутылок := Бутылки(колво);
        Write 'Take one down and pass it around, '^бутылок^' of beer on the wall.';
        Write ''
    End

    Write 'No more bottles of beer on the wall, no more bottles of beer.';
    Write 'Go to the store and buy some more, 99 bottles of beer on the wall.'
Endproc

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

Ещё необычно выглядит операция конкатенации — ^ и повторения строки — ^^. Из-за того, что в языке есть неявные преобразования, можно делать вот такое:

Write 'МА' ^^ '2 раза' /* Будет выведено «МАМА», так  как «2 раза» преобразуется к двойке */

С удовольствием познакомился с языком, благо он не выглядит, как что-то, сделанное «в стол», для «галочки» или исключительно для обучения школьников или студентов.



Ссылка на оригинал.
кукяй

99 бутылок: Lua

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

73. Lua — скриптовый язык, который чаще всего применяют для встраивания, например — нередко используют для описания сценариев в играх. Объектная модель прототипная, этим напоминает ДжаваСкрипт, но в Луа она мощнее.

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

А вот стандартная библиотека подкачала, простой пример — в ней нет функции задержки, когда она мне понадобилась, пришлось её импортировать из Си. Или есть модуль, который хоть как-то позволяет работать с ЮТФ-8, но в нём даже нет простого способа получить символ по его номеру или поменять регистр строки.

function beer(b)
    if b == 1 then
        return '1 bottle'
    else
        return (b == 0 and 'no' or b) .. ' bottles'
    end
end

b = beer(99)

for i = 99, 1, -1 do
    print(b .. ' of beer on the wall, ' .. b .. ' of beer.')
    b = beer(i - 1)
    print('Take one down and pass it around, ' .. b .. ' of beer on the wall.\n')
end

print([[No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.]])


Ссылка на оригинал.
кукяй

99 бутылок: CFAQ

72. CFAQ (читается «СИФАК»). Очень люблю самодельные языки программирования, есть в них какое-то милое очарование, крафтовость с нотками олдскула. Услада сердцу после вездесущего Кровавого Энтерпрайза.

Когда узнал, что у известного писателя-фантаста Леонига Каганова есть собственный фреймворк для чипа ESP8266 со встроенным самописным скриптовым языком программирования «СИФАК», не мог пройти мимо. Леонид хоть и зарабатывает на жизнь литературными трудом, но когда-то работал программистом, разрабатывая на ассемблере модули устройств для геофизики и дозиметрии.

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

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

# 99.TXT. Написано Степанищевым Евгением, апрель 2020
B = 99
repeat -1 {
    Bt = {B}

    repeat 2 {
        if {Bt} = 0 {
            set S = no bottles
        } else {
            if {Bt} = 1 {
                set S = 1 bottle
            } else {
                set S = {Bt} bottles
            }
        }

        if {Bt} = {B} {
            echo {S} of beer on the wall, {S} of beer.<br>
        } else {
            echo Take one down and pass it around, {S} of beer on the wall.<br>
        }

        Bt -= 1
    }

    B -= 1

    if {B} = 0 {
        echo No more bottles of beer on the wall, no more bottles of beer.<br>
        echo Go to the store and buy some more, 99 bottles of beer on the wall.

        exit
    }
}

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

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

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



Ссылка на оригинал.
кукяй

99 бутылок: V

71. V — один из языков, за развитием которых я пристально наблюдаю. Искренне желаю ему развития и процветания — под влиянием «Раста», «Гоу» и чего-то вроде Пе́рла, у авторов получается довольно интересный язык, который пока, правда, находится в стадии альфы.

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

Сильнее всего язык, кажется, похож на Гоу — есть даже синтаксически такой же оператор go, позволяющий запускать что-нибудь в отдельном потоке (позднее обещают сделать корутины), но и уши «Раста» торчат даже в моей небольшой программе: совпадение с образцом, условные операторы-конструкции, константные переменные (если не указан mut).

Есть обобщённое программирование (которого так не хватает в Гоу), интерполяция переменных в строках (привычная ребятам, программирующим на ПХП, Перле и шеллах) и ограниченная перегрузка операторов (как в Си++).

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

// 99.v by Evgeny Stepanischev Feb 2020

fn bottles(beer byte) string {
    return match beer {
        0 {
            'no bottles'
        }
        1 {
            '1 bottle'
        }
        else {
            '$beer bottles'
        }
    }
}

fn main() {
    mut b := bottles(99)

    for i := 98; i >= 0;  {
        println('$b of beer on the wall, $b of beer.')
        b = bottles(i--)
        println('Take one down and pass it around, $b of beer on the wall.\n')
    }

    println('No more bottles of beer on the wall, no more bottles of beer.')
    println('Go to the store and buy some more, 99 bottles of beer on the wall.')
}


Ссылка на оригинал.
кукяй

Шутки с бородой

Продолжаю выкладывать вырезки из газет царских времён — из тех обрывков, что иногда попадались мне на чердаках. На фотографии кусочек всё того же номера 244 газеты «Камско-волжская рѣчь». Это в последний раз, больше ничего сто́ящего в ней не нашлось.

Спешите ознакомиться, «1001 совѣтъ даромъ» от мизогиниста, скрывающегося за именем весёлого скрипача К’аламбура:

Мякотка из газеты «Камско-волжская рѣчь», вторникъ 5 ноября 1913 г., №244-й

Как становится очевидным в самом конце, это — столетней давности продакт-плейсмент коньяка Шустова. Шустовы начинали производить алкогольную продукция в 1863 году, начали с качественной водки — производили марки «Зубровка», «Спотыкач», «Запеканка», «Нектарин» и «Рябину на коньяке», позже занялись коньяком.

Для продвижения своей продукции Ш. заспамили своими баннерами в газетах всю Россию — многие годы на обложке самого читаемого в России журнала «Нива», прямо под названием журнала располагалась реклама их коньяка. Кроме прессы, она была на вагонах трамваев и поездов, на бортах пароходов, и даже в спектаклях персонажи просили подавать только шустовский коньяк.

В итоге продукция стала знаменитой не только в России, но и за границей, неоднократно получала награды на международных выставках. В 1912 году фирма «Н. Шустов и сыновья» стала поставщиком двора Его Императорского Величества.

Большей популярности в России не имел ни один производитель алкогольных напитков.



Ссылка на оригинал.
кукяй

99 бутылок: Zephir

69. Zephir — язык программирования, созданный для написания модулей расширения PHP и являющийся его сателлитом. Текущая версия (0.12.2) содержит несколько багов, с которыми пришлось столкнуться при написании программы. К счастью, перед компиляцией «Зефир» транслируется в Си, поэтому разобраться в происходящем труда не стоило.

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

По синтаксису «Зефир» явный наследник ПХП, но выглядит почище — без «долларов» в именах переменных (которые многих раздражают) и скобок в управляющих конструкциях (из-за чего напоминает мне Гоу). Процедурное прошлое здесь почти не видно — многие функции на типами имеют объектные эквиваленты.

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

«Песня о пиве» на «Зефире» выглядит следующим образом:

// Beer song by Evgeny Stepanischev
// song.zep
namespace Beer;

class Song
{
	private static function format(int bottles) -> string
	{
		string result = "";

		switch bottles {
			case 0:
				let result = "No bottles";
				break;
			case 1:
				let result = "1 bottle";
				break;
			default:
				let result = "%d bottles"->format(bottles);
		}

		return result . " of beer";
	}


    public static function sing() -> void
    {
    	int bottles = 99;
    	var botStr = self::format(bottles);

        while bottles > 1 {
        	echo "%s of beer on the wall, %1$s of beer.\n"->format(botStr);

        	let bottles--;
        	let botStr = self::format(bottles);

        	echo "Take one down and pass it around, %s on the wall.\n\n"->format(botStr);
        }

        echo "No more bottles of beer on the wall, no more bottles of beer.\n",
        	"Go to the store and buy some more, 99 bottles of beer on the wall.\n";
    }

}

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

zephir build
php -d extension=beer.so -r 'Beer\Song::sing();'


Ссылка на оригинал.