99
У американцев есть такая считалочка — «песня о пиве», наверняка её многие слышали в американских фильмах. У меня есть хобби — делать вывод этой считалочки на разных языках программирования. Со временем набралась приличная коллекция.
99 бутылок: Lua
Пока ещё помню язык Луа, который я использовал для написания «Морского боя» в азбуке Морзе, надо бы продолжить им сериал о «99 бутылках пива на стене».
73. Lua — скриптовый язык, который чаще всего применяют для встраивания, например — нередко используют для описания сценариев в играх. Объектная модель прототипная, напоминает ДжаваСкрипт, но в Луа она мощнее.
Язык очень простой, учится элементарно, но при этом довольно мощный.
А вот стандартная библиотека подкачала, простой пример — в ней нет функции задержки, когда она мне понадобилась, пришлось её импортировать из Си. Или есть модуль, который хоть
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 (читается «СИФАК»). Очень люблю самодельные языки программирования, есть в них
Когда узнал, что у известного
Язык, конечно, довольно простой, без поддержки подпрограмм или функций (их можно эмулировать отдельными файлами, передавая параметры через глобальные переменные), но с циклами, ветвлениями и переменными.
# 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, позволяющий запускать
Есть обобщённое программирование (которого так не хватает в Гоу), интерполяция переменных в строках (привычная ребятам, программирующим на ПХП, Перле и шеллах) и ограниченная перегрузка операторов (как в Си++).
Насколько я понял из сайта и блога, язык нацелен на безопасное программирование, скорость, как выполнения (проигрывает Си всего на три процента), так и выполнения и простоту кода. Повторюсь, выглядит очень интересно.
// 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.')
}99 бутылок: ElanTele ★
70. ElanTele («змеиный язык», видимо намёк на Пайтон) — язык программирования, интерпретатор которого позволяет писать как на английском, так и на татарском. Насколько я понял, это
Обычные конструкции на месте — ветвление, два цикла, определение функции, простенький
// beer.et by Evgeny Stepanischev
вар бөтеннәрюлы := функция(ә) бу
вар саннар := ["0","1","2","3","4","5","6","7","8","9"]
вар олыара := ә/10
вар нәтиҗә := саннар[ә - олыара*10 + 1]
әгәр ә > 9 буочракта
нәтиҗә := саннар[олыара + 1] + нәтиҗә
бетте
кайтар нәтиҗә
бетте
вар форматлау := функция(шешәләр) бу
вар нәтиҗә
әгәр шешәләр = 0 буочракта
нәтиҗә := "no bottles"
башкаочракта
әгәр шешәләр = 1 буочракта
нәтиҗә := "1 bottle"
башкаочракта
нәтиҗә := бөтеннәрюлы(шешәләр) + " bottles"
бетте
бетте
кайтар нәтиҗә + " of beer"
бетте
вар ә,
дәвамында ә эчендә 1..99 элмәк
:= форматлау(100-ә)
яз
+ " of beer on the wall, " +
+ " of beer."
яз "Take one down and pass it around, " + форматлау(99-ә) + " on the wall.\n"
бетте
яз "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 бутылок: 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();'99 бутылок: dc
68. DC — программа для арифметических вычислений с произвольной точностью
Поддерживаются 256 стековых регистров и основной стек программы. На стеках могут размещаться числа и строки, последние могут исполняться, как подпрограммы. Команды однобуквенные, некоторые имеют операнд; числа записываются как есть, строки — между квадратными скобками.
Компактно «песню о пиве» можно записать таким кодом:
[n10P]su[[s]P]ss[[No bottles]Plon2+Q]sn
[d0=ndn[ bottle]n1!=slon]sb[ of beer]so
[ddlbx[ on the wall, ]nlbx[.]lux
[Take one down and pass it around,]lux
1-dlbx[ on the wall.]lux[]luxd0!=B]sB
99lBx
[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.
] nА вот вариант с комментариями (которые, правда, не делают программу уж сильно понятнее):
# beer.dc
# Степанищев Е. В. bolknote.ru
# Печать с переводом строки, мне не нравится помещать
# его в строку символом — ломаются отступы
[
n 10 P
] su
# Печатаем «s»
[
[s] P
] ss
# Печатаем «No bottles of beer», убираем (сложением) ноль со стека,
# прерываем выполнение родителя (выходим из двух уровней)
[
[No bottles] P lon
2+Q
] sn
# Вывод кол-ва бутылок с «bottle(s) of beer»
[
d 0 =n
d n [ bottle] n 1 !=s lon
] sb
# « of beer» — в регистр «о», будем использовать
# для вывода части фразы
[ of beer] so
# основной цикл программы (вызывается рекурсивно)
[
d
d lbx [ on the wall, ] n lbx [.] lux
[Take one down and pass it around,] lux
1-
d lbx [ on the wall.] lux [] lux
d 0 !=B
] sB
99 lBx
[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.
] n99 бутылок: Юᓂ곧⎔
67. Юᓂ곧⎔ — эзотерический язык программирования, кратко описанный в пятничном посте в блоге кандидата математических наук Дэвида Мадора. Основная идея — придумать язык, обфусцированный ресурсами Юникода.
Недавно появился транслятор из «Юᓂ곧⎔» в Си, благодаря чему можно писать и запускать программы на этом необычном языке.
Согласно спецификации языка, все имена функций должны записываться кириллицей, десятичные цифры — быть монгольскими, в именах аргументов должна использоваться хирагана и тому подобное.
Несмотря на это, писать не особо сложно — можно быстренько накидать требуемое в Си, а потом перевести программу в «Юᓂ곧⎔», подсмотрев правила в трансляторе.
Интересно как смотрится программа под разными операционными системами. «МакОС», насколько я могу судить, отображает всё корректно.
❝99.⎔❞
ℤбутылок «ℤぶ»
☹
¿«ぶ ⇔ ☰» писать «“⁌☱☵☶⁍⁌☱☵☷⁍⁌☴☰⁍”»।
¬писать «“﹪ℤ⁌☴☰⁍” ¦ ぶ»।
писать «“⁌☱☴☲⁍⁌☱☵☷⁍⁌☱☶☴⁍⁌☱☶☴⁍⁌☱☵☴⁍⁌☱☴☵⁍”»।
¿«ぶ ⇔ ☱»।¬писать «“⁌☱☶☳⁍”»।
☺
⌂ «»
☹
∀«ቁምፊ 工 ← ᠙᠙। 工 ≩ ☰। ∇工»
☹
бутылок «工»।
писать «“⁌☴☰⁍⁌☱☵☷⁍⁌☱☴☶⁍⁌☴☰⁍⁌☱☴☲⁍⁌☱☴☵⁍⁌☱☴☵⁍⁌☱☶☲⁍⁌☴☰⁍\
⁌☱☵☷⁍⁌☱☵☶⁍⁌☴☰⁍⁌☱☶☴⁍⁌☱☵☰⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☶☷⁍⁌☱☴☱⁍⁌☱☵☴⁍⁌☱☵☴⁍⁌☵☴⁍⁌☴☰⁍”»।
бутылок «工»।
писать «“⁌☴☰⁍⁌☱☵☷⁍⁌☱☴☶⁍⁌☴☰⁍⁌☱☴☲⁍⁌☱☴☵⁍⁌☱☴☵⁍⁌☱☶☲⁍⁌☵☶⁍␊”»।
писать «“⁌☱☲☴⁍⁌☱☴☱⁍⁌☱☵☳⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☵☷⁍⁌☱☵☶⁍⁌☱☴☵⁍⁌☴☰⁍\
⁌☱☴☴⁍⁌☱☵☷⁍⁌☱☶☷⁍⁌☱☵☶⁍⁌☴☰⁍⁌☱☴☱⁍⁌☱☵☶⁍⁌☱☴☴⁍⁌☴☰⁍⁌☱☶☰⁍⁌☱☴☱⁍⁌☱☶☳⁍\
⁌☱☶☳⁍⁌☴☰⁍⁌☱☵☱⁍⁌☱☶☴⁍⁌☴☰⁍⁌☱☴☱⁍⁌☱☶☲⁍⁌☱☵☷⁍⁌☱☶☵⁍⁌☱☵☶⁍⁌☱☴☴⁍⁌☵☴⁍⁌☴☰⁍”»।
бутылок «工−᠑»।
писать «“⁌☴☰⁍⁌☱☵☷⁍⁌☱☴☶⁍⁌☴☰⁍⁌☱☴☲⁍⁌☱☴☵⁍⁌☱☴☵⁍⁌☱☶☲⁍⁌☴☰⁍\
⁌☱☵☷⁍⁌☱☵☶⁍⁌☴☰⁍⁌☱☶☴⁍⁌☱☵☰⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☶☷⁍⁌☱☴☱⁍⁌☱☵☴⁍⁌☱☵☴⁍⁌☵☶⁍␊␊”»।
☺
писать «“⁌☱☱☶⁍⁌☱☵☷⁍⁌☴☰⁍⁌☱☵☵⁍⁌☱☵☷⁍⁌☱☶☲⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☴☲⁍⁌☱☵☷⁍\
⁌☱☶☴⁍⁌☱☶☴⁍⁌☱☵☴⁍⁌☱☴☵⁍⁌☱☶☳⁍⁌☴☰⁍⁌☱☵☷⁍⁌☱☴☶⁍⁌☴☰⁍⁌☱☴☲⁍⁌☱☴☵⁍⁌☱☴☵⁍\
⁌☱☶☲⁍⁌☴☰⁍⁌☱☵☷⁍⁌☱☵☶⁍⁌☴☰⁍⁌☱☶☴⁍⁌☱☵☰⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☶☷⁍⁌☱☴☱⁍⁌☱☵☴⁍⁌☱☵☴⁍\
⁌☵☴⁍⁌☴☰⁍⁌☱☵☶⁍⁌☱☵☷⁍⁌☴☰⁍⁌☱☵☵⁍⁌☱☵☷⁍⁌☱☶☲⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☴☲⁍⁌☱☵☷⁍⁌☱☶☴⁍\
⁌☱☶☴⁍⁌☱☵☴⁍⁌☱☴☵⁍⁌☱☶☳⁍⁌☴☰⁍⁌☱☵☷⁍⁌☱☴☶⁍⁌☴☰⁍⁌☱☴☲⁍⁌☱☴☵⁍⁌☱☴☵⁍⁌☱☶☲⁍⁌☵☶⁍␊”»।
писать «“⁌☱☰☷⁍⁌☱☵☷⁍⁌☴☰⁍⁌☱☶☴⁍⁌☱☵☷⁍⁌☴☰⁍⁌☱☶☴⁍⁌☱☵☰⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☶☳⁍\
⁌☱☶☴⁍⁌☱☵☷⁍⁌☱☶☲⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☴☱⁍⁌☱☵☶⁍⁌☱☴☴⁍⁌☴☰⁍⁌☱☴☲⁍⁌☱☶☵⁍⁌☱☷☱⁍⁌☴☰⁍\
⁌☱☶☳⁍⁌☱☵☷⁍⁌☱☵☵⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☵☵⁍⁌☱☵☷⁍⁌☱☶☲⁍⁌☱☴☵⁍⁌☵☴⁍⁌☴☰⁍⁌☷☱⁍⁌☷☱⁍⁌☴☰⁍\
⁌☱☴☲⁍⁌☱☵☷⁍⁌☱☶☴⁍⁌☱☶☴⁍⁌☱☵☴⁍⁌☱☴☵⁍⁌☱☶☳⁍⁌☴☰⁍⁌☱☵☷⁍⁌☱☴☶⁍⁌☴☰⁍⁌☱☴☲⁍⁌☱☴☵⁍\
⁌☱☴☵⁍⁌☱☶☲⁍⁌☴☰⁍⁌☱☵☷⁍⁌☱☵☶⁍⁌☴☰⁍⁌☱☶☴⁍⁌☱☵☰⁍⁌☱☴☵⁍⁌☴☰⁍⁌☱☶☷⁍⁌☱☴☱⁍⁌☱☵☴⁍⁌☱☵☴⁍⁌☵☶⁍”»।
☺99 бутылок: Ассемблер 6502 для Apple I
66. Ассемблер 6502 для «Эпл I». 6502 — восьмибитный микропроцессор, выпускавшийся в 1975 году компанией «МОС Текноложи».
У процессора всего 56 команд (не считая недокументированные), доступны три регистра — A, X и Y. Очень необычно устроена адресация — первые 256 байт памяти доступны через восьмибитную адресацию, всё остальное пространство — через шестнадцатибитную.
Мнемоники трёхбуквенные, в основном — смысловые сокращения или акронимы, запоминаются легко. Например, LDY — LoaD Y, ASL — Arithmetic Shift Left, JSR — Jump to SubRoutine и так далее.
Процессор использовался в первом персональном компьютере «Эпл», для него я и написал «песню про пиво», использовав для печати на экран куцее встроенное АПИ.
Очень помогло, что в наборе команд есть десятичный режим — в этом режиме после прибавления единицы к «09h» получается «10h», а не «0Ah» (надо только помнить, что в этом режиме работают всего две команды — ADC и SBC). «Бутылки» в этом режиме считать значительно легче.
.ORG 00280h
.CPU 6502
ECHO = $FFEF
PRBYTE = $FFDC
PRHEX = $FFE5
MONITOR = $FF1F
SED
LDA #$99
LOOP_:
PHA
JSR BOTTLES
JSR B_OF_T_WALL
LDX #(ENDPASSSTR - STRS - 2) ; ", "
LDY #2
JSR PRINT
PLA
PHA
JSR BOTTLES
JSR OF_BEER
JSR DOT_CR
JSR TAKE_ONE_DOWN
PLA
SEC
SBC #1
PHA
JSR BOTTLES
JSR B_OF_T_WALL
JSR DOT_CR
PLA
CMP #0
BNE LOOP_
JSR NO_MORE
JMP MONITOR
PRINTNUMBER: ; in A (number), use A
CMP #$F
BCS $+5
JMP PRHEX
JMP PRBYTE
PRINT_PSTR: ; in X (offset), use A, Y
LDY (STRS),X
INX
PRINT: ; in X (offset), Y (len), use A
LDA (STRS),X
JSR ECHO
INX
DEY
BNE PRINT
RTS
BOTTLES: ; in A (quantity), use X, Y
CMP #0
BEQ NO_
PHA
JSR PRINTNUMBER
LDX #3 ; skips len+"NO"
LDY #8 ; length of " BOTTLES"
PLA
CMP #1
BNE NO_ONE_
DEY ; 7 - length of " BOTTLE"
NO_ONE_:
JMP PRINT
NO_:
LDX #0
JMP PRINT_PSTR
B_OF_T_WALL: ; use X, Y, A
LDX #(BEERONTHEWALLSTR - STRS)
JMP PRINT_PSTR
OF_BEER: ; use X, Y, A
LDX #(BEERONTHEWALLSTR - STRS + 1) ; skips len
LDY #8 ; length of " OF BEER"
JMP PRINT
DOT_CR: ; use X, Y, A
LDX #(END - STRS - 2) ; "." + CR
LDY #2
JMP PRINT
TAKE_ONE_DOWN: ; use X, Y, A
LDX #(PASSSTR - STRS)
JMP PRINT_PSTR
NO_MORE: ; use X, Y, A
LDX #(ENDSTR - STRS)
JMP PRINT_PSTR
STRS:
.PSTR "NO BOTTLES"
BEERONTHEWALLSTR:
.PSTR " OF BEER ON THE WALL"
PASSSTR:
.PSTR "TAKE ONE DOWN AND PASS IT AROUND, "
ENDPASSSTR:
ENDSTR:
DB 128,"NO MORE BOTTLES OF BEER ON THE WALL, NO MORE BOTTLES OF BEER.",$8D
DB "GO TO THE STORE AND BUY SOME MORE, 99 BOTTLES OF BEER ON THE WALL.",$8D
END:Для отладки, написания программы и перевода в машинные коды использовался довольно удобный «
Сначала программу я вводил в эмулятор вручную, но потом обленился и написал программу для ввода шестнадцатеричного дампа внутрь эмулятора. Выложил на «Гитхаб», если
Надеюсь
99 бутылок: Эль-76
65.
Язык процедурный, как и следовало ожидать, но с обработкой исключений, который тут называются «ситуациями». Довольно необычно.
% Песня о пиве 99.l76
программа
процедура пиво = проц(ф32 бутылок)
начало
если бутылок = 0 то
печатьмс(стр8 "no bottles")
инес бутылок = 1 то
печатьмс(стр8 "1 bottle")
иначе
печать(бутылок);
печатьмс(стр8 " bottles")
все
конец;
ф32 бутылок;
для бутылок от 99 вниздо 1 цикл
пиво(бутылок);
печатьмс(стр8 " of beer on the wall, ");
пиво(бутылок);
печатьмс(стр8 " of beer.");
печатькс();
печатьмс(стр8 "Take one down and pass it around, ");
пиво(бутылок - 1);
печатьмс(стр8 " of beer on the wall.");
печатькс();
печатькс()
повторить;
печатьмс(стр8 "No more bottles of beer on the wall, no more bottles of beer.");
печатькс();
печатьмс(стр8 "Go to the store and buy some more, 99 bottles of beer on the wall.")
конецТем не менее, программа запускается и выводит задуманное, хотя могла бы выглядеть менее уродливо, будь у меня компилятор, реализующий
99 бутылок: Rust
64. Rust — довольно известный язык, на слуху, очень интересный своими концепциями. Пока писал «песню о пиве», даже захотелось познакомиться с ним поближе.
Язык является «близким к железу», нацелен на безопасность и многопоточность — немало ошибок, которые приводят к уязвимостям в программах на Си, тут выявляются ещё на этапе компиляции. Правда за это приходится платить, порог входа в язык очень высокий.
Ниже программа на этом языке, но выбранный формат позволяет показать лишь маленькую толику фишек языка.
Наверное опытные программисты уже выделили знакомые по другим языкам части программы, но некоторые вещи возможно требуют пояснений.
Тип u8 — это тип «байт», match — конструкция проверяющая совпадение с образцом, мощная вещь, умеет сопоставлять что угодно — значения, типы, реализованные методы и так далее, mut — ключевое слово, указывающая, что переменную можно модифицировать,
// Beer song. Evgeny Stepanischev, 2018
fn bottles(beer: u8) -> String {
match beer {
0 => "no bottles".to_string(),
1 => "1 bottle".to_string(),
_ => format!("{} bottles", beer)
}
}
fn main() {
let mut beer = 99;
while beer > 0 {
println!("{} of beer on the wall, {0} of beer.", bottles(beer));
beer -= 1;
println!("Take one down and pass it around, {} of beer on the wall.\n", bottles(beer));
}
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.");
}99 бутылок: SCSS
63. SCSS — язык шаблонизации для файлов CSS. Я написал реализацию «99 бутылок» на нём ещё в 2012 году, но по неизвестной причине так никуда и не выложил. Возможно к лучшему — посмотрел свежим взглядом и исправил несколько неточностей.
Язык полностью процедурный, с примитивными типами (есть массивы, включая ассоциативные и собственный тип — «цвет»), поддержкой интерполяции в строках и с массой своих особенностей, диктуемых областью применения.
Шаблонизатор не имеет обособляющих элементов (типа двойных фигурных скобок), его конструкции «живут» прямо в коде, который генерируется, поэтому иногда нужно ставить немного уродливые подпорочки — например, символ деления используется и в математической операции, и в синтаксисе таблиц стилей, так что иногда приходится указывать что имеется ввиду.
Переводы строк пришлось оставить в строках как есть, поскольку, по всей видимости, нет никаких специализированных управляющих последовательностей для этого — в практике такой задачи не встречается.
@function bottles($beer) {
@if $beer == 0 { @return "no bottles" }
@if $beer == 1 { @return "1 bottle" }
@return $beer + " bottles"
}
@function beer($beer) {
$b: bottles($beer);
@return "#{ $b } on the wall, #{ $b }.
Take one down and pass it around, " + bottles($beer - 1) + " of beer on the wall.
"
}
$result: "
";
@for $i from 99 through 1 {
$result: $result + beer($i)
}
@debug $result +
"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 бутылок: Postscript
62. Postscript — интерпретируемый стековый язык программирования. Предназначен для стандартизации вывода документов на различные устройства.
Люди на нём программы пишут крайне редко, в основном это делают другие программы — например, при печати на принтер. Этот же язык программирования используется внутри формата PDF.
Язык строго типизирован, система типов включает: целые числа, числа с плавающей запятой, логический тип, строку, массив, процедуру, словарь и имя. Для всех операций используется стек и обратная польская запись.
%!
%%Title: (Beer song)
%%Creator: Evgeny Stepanischev
%%EndComments
/beer % (int) -> (int)
{
dup 0 eq {
(no bottles) print
} {
dup 1 eq {
(1 bottle) print
} {
dup //=string cvs print ( bottles) print
} ifelse
} ifelse
} bind def
99 -1 1 {
beer ( of beer on the wall, ) print beer (\n) print
(Take one down and pass it around, ) print
dup 1 sub beer pop
( of beer on the wall.\n\n) print
} for
(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.) print
quit
99 бутылок: Cmm, интернет-археология
61. Cmm. Язык «Cmm» был разработан в 1992 году компанией «Nombas». Основной идеей языка было упрощение языка «Си», отсюда и название — C minus minus. Официальное руководство говорит, что это «Си, минус объявление типов, минус указатели». Позже язык был переименован в ScriptEase, так как упоминание «Си» отпугивало людей. Язык существовал для ДОСа, Виндоуз, ОС/2 и операционной системы компании «Новелл».
В конце 1995 года компания создала версию скриптового языка
Язык действительно простой — типы выводятся из использования, массивы без указания размера, нет явного выделения и освобождения памяти, указателей не видно.
Массивы и строки, хоть и являются указателями (есть даже арифметика с ними), но этого не замечаешь — выглядят, как обычные переменные. Все lvalue передаются по указателю, для передачи по значению есть специальный синтаксис. Забавно, кстати, что точка с запятой не обязательна, прямо как в ДжаваСкрипте.
Остальные отличия от «Си» не столь заметны. Языки почти что близнецы, есть даже ограниченный предпроцессор, да и встроенные функции, в основном, сишные. Язык, видимо, претендовал сразу на несколько ниш, на нишу коммандных оболочек в том числе — в составе предпроцессора есть команда, позволяющая импортировать куски программ, указывая с какой по какую строку производить импорт. Насколько я смог заметить, это широко используется, чтобы внедрять «СиЭмЭм» внутрь
// Written by Evgeny Stepanischev, 2017
BottlesPlural(Beer)
{
switch ( Beer )
{
case 0:
return `no bottles`
case 1:
return `1 bottle`
default:
sprintf(Bottles, `%d bottles`, Beer)
return Bottles
}
}
i = 99
Bottles = BottlesPlural(i)
while ( i > 0 ) {
printf("%s of beer on the wall, %s of beer.\n", Bottles, Bottles)
Bottles = BottlesPlural(--i)
printf("Take one down and pass it around, %s of beer on the wall.\n\n", Bottles)
}
printf("No more bottles of beer on the wall, no more bottles of beer.\n")
printf("Go to the store and buy some more, 99 bottles of beer on the wall.\n")Если
99 бутылок: R
60. R. Как многие наверное помнят, в качестве хобби я время от времени пишу на разных языках программирования американскую «Песню о пиве»
Это довольно известное развлечение — реализовывать на куче языков
Я выбрал именно «Песню о пиве», так как не всем языкам из моего списка, под силу
# Written by Evgeny Stepanischev, 2017
bottles <- function(beer) {
ifelse(beer == 0, "no bottles",
ifelse(beer > 1, paste(beer, "bottles"), "1 bottle")
)
}
for (i in 99:1) {
paste(bottles(i), "of beer") -> b
cat(b, " on the wall, ", b, ".\n", sep = "")
cat("Take one down and pass it around,", bottles(i - 1), "of beer on the wall.\n\n")
}
cat("No more bottles of beer on the wall, no more bottles of beer.\n")
cat("Go to the store and buy some more, 99 bottles of beer on the wall.\n")
«99 бутылок» на языке «Электроники МК-61»
59. Язык калькулятора Электроника
В детстве такие калькуляторы я видел только на картинках в журнале «Наука и жизнь», а программы для них были
Вчера мне в руки попал настоящая «Электроника
Так выглядят мои «99 бутылок…» на этом калькуляторе:
8112000 Х→П c 8 + ИНВ Х→П b Вх 10 ÷ [X] Х→П d 8 + ИНВ Х→П e В/О ПРГ
П→Х 0 1 0 ÷ [x] Х→П 1 Вх {x} 1 0 × Х→П 2
1 1 Х→П 8 1 2 Х→П 7 П→Х 2 ПП 34 Х→П a
1 4 Х→П 8 1 3 Х→П 7 П→Х 1 ПП 34 П→Х a
^ С/П
6 - /-/ x<0 45 9 + К П→Х 7 + ИНВ В/О
1 + К П→Х 7 + ИНВ К П→Х 8 ^ В/ОПоскольку у меня в блоге скорее всего отсутствуют любители работать каждый день с калькуляторами советских времён, то я не буду придерживаться принятой нотации с номерами — не думаю, что
Вкратце о языке. Больше всего это похоже на крайне примитивный ассемблер с гипертрофированным математическим сопроцессором. Всё то же — переходы на адрес, одно- и двухбайтные инструкции с операндами, регистры с определёнными назначениями, сильно ограниченная память (105 команд), наличествует косвенная адресация и подпрограммы (стек вызовов размером в пять вхождений).
До запуска программы нужно в регистр «0» поместить стартовое значение (например, «99», «Х→П», «0») и запустить программу «В/О», «С/П».
Это я сделал
Поэтому на вход подаётся нужное число, например, «42», а на выходе мы можем полюбоваться фразой «BEEr 42». Не весть что, но что вы хотели от калькулятора? Кстати, выводимая фраза — не строка (спойлер: а число), о том как мне пришлось помучаться я ещё расскажу.
99 бутылок: Эллочка
58. Эллочка. Мне написал автор языка программирования «Эллочка» с предложением написать на нём «99 бутылок…», как вы знаете, у меня есть хобби — писать такие программы на разных языках.
Для этого языка есть единственный, авторский интерпретатор под ДОС (и очень важно использовать в файле программы символы перевода ДОС/Виндоуз, иначе ничего не будет работать), а сам язык напоминает странноватый Бейсик, без поддержки функций и процедур. Их можно эмулировать, используя трюк со специальной переменной «@», которая содержит номер текущей строки.
В языке есть ряд интересных возможностей, но их затмевают недостатки разного калибра, что характерно для языков без сообщества. Даже в таком простом примере мне пришлось побороться за работоспособность программы. Например, перед числами
!99 beer song by Evgeny Stepanischev
!Used variables: B, R, $1
B=99
@cycl
R=@+2
goto @beer
list ' of beer on the wall, '
R=@+2
goto @beer
list '.'\
list 'Take one down and pass around'\
decr B
R=@+2
goto @beer
list ' of beer on the wall.'\
list ''\
wait
clsc
esli B >> 0; @cycl
list 'No more bottles of beer on the wall, no more bottles of beer.'\
list 'Go to the store and buy some more, 99 bottles of beer on the wall.'
exit
@beer
esli B >> 0; +3\
list 'No bottles'
goto R
esli B == 1; +5\
$1=B
$1=%MID($1,2,10)
list $1+' bottles'
goto R
list '1 bottle'
goto R99 бутылок: CMake
57. CMake. Писать «Песни про пиво» на различных языках программирования — давнее моё увлечение, ему столько же лет, сколько этому блогу. В этот раз «поёт»
CMake — автоматизированная система сборки пакетов, имеющая развитый, хотя и несколько уродливый макроязык. Инструкции, большей частью, знакомые, разве что способ возврата значений несколько из макросов и функций несколько странный — через параметры и глобальные переменные.
Никакого ООП, само собой, и всё весьма примитивно по меркам развитых языков.
# 99.cmake
# to run: cmake -P 99.cmake
# Written by Evgeny Stepanischev, 2015
cmake_minimum_required(VERSION 3.0)
macro(bottles beer ret)
if(${beer} EQUAL 0)
set(${ret} "No bottles")
elseif(${beer} EQUAL 1)
set(${ret} "1 bottle")
else()
set(${ret} "${${beer}} bottles")
endif()
endmacro()
foreach(beer RANGE 99 1 -1)
bottles(beer bottles)
math(EXPR beer "${beer}-1")
bottles(beer bottless)
message("${bottles} of beer on the wall, ${bottles}.")
message("Take one down and pass it around, ")
message("${bottless} of beer on the wall.")
message("")
endforeach()
message("No more bottles of beer on the wall, no more bottles of beer.")
message("Go to the store and buy some more, 99 bottles of beer on the wall.")Строка для запуска во второй строке файла.
99 бутылок пива на «Электронике МК85»

56. БЭЙСИК «Электроники МК85». Как я уже сказал, Бейсик (в руководстве он называется «БЭЙСИК») на «МК85» отличается странностями. Например, там фиксированное количество переменных с определёнными (только однобуквенными именами), причём только одна строковая переменная может содержать не более 30 символов (её имя — символ доллара), остальные могут содержать не более семи символов.
Или запись массивов — все числовые переменные, по сути, являют собой один массив. Индекс «один» массива с именем «А» совпадает с переменной «B», а индекс «два» переменной «B» — это переменная «D» и так далее. Так что вы можете использовать
Другая неприятная особенность — небольшой максимальный размер строки и программы и весьма ограниченный её размер.
В общем, представляю вашему вниманию программу «99 бутылок пива на стене», написанную на БЭЙСИКе микрокомпьютера «Электроника
10FOR B=99 TO 1 STEP -1
20A=B:GOSUB90:PRINT" of beer on the wall, ";:GOSUB90:PRINT"."
30PRINT"Take one down and pass it around, ";:A=B-1:GOSUB90
40PRINT" of beer on the wall."
50NEXT B
60PRINT"No more bottles of beer on the wall, no more bottles of beer."
70PRINT"Go to the store and buy some more, 99 bottles of beer on the wall."
80END
90GOTO100*(SGN(A-1)+2)
100PRINT"no bottles";:RETURN
200PRINT"1 bottle";:RETURN
300PRINT A;" bottles";:RETURNМикрокомпьютер имеет интересную особенность — длинные строки, не помещающиеся на экране, он автоматически прокручивает, а чтобы человек успел прочитать, после каждой строки происходит остановка интерпретатора, для продолжения надо нажать клавишу «EXE». Точка с запятой после оператора «PRINT» говорит интерпретатору, что строка не кончилась, что позволяет печатать длинные строки несколькими операторами.
Ещё одна особенность — программируемый символ. Один символ, имеющий специальный код можно нарисовать попиксельно. Завтра попробую побаловаться.
99 бутылок: 𝄢 Cello
55. 𝄢 Cello. Попробовал попрограммировать с использованием библиотеки «libCello» — это набор макросов к Си, вводящих в язык кучу комплексных типов, простую работу с выделением и освобождением памяти под них,
В документации выглядело неплохо, но по факту оказалось, что библиотека недописана, а документация неполная и содержит ошибки. Шаг в сторону и программа вылетает. Например, она падает, если попытаться использовать возвращаемое лямбдой значение.
Пример ошибки в документации — функции в «стиле Си» не могут быть заданы внутри функции main, хотя на сайте указан пример, в котором утверждается обратное (и он не компилируется).
По идее, библиотека должна упрощать программирование, но в моём случае (я понимаю, «песня про пиво» не совсем та программа, в которой раскрывается эта библиотека) всё было ровно наоборот — на чистом Си я справился бы значительно быстрее.
Если бы её дописать и достойно задокументировать, вышло бы
#include "Cello.h"
int main() {
lambda(bottles, args) {
var beer = cast(at(args, 0), Int);
if_eq(beer, $(Int, 0)) {
print("no bottles");
} else {
if_gt(beer, $(Int, 1)) {
print("%d bottles", beer);
} else {
print("1 bottle");
};
}
return None;
};
for (var beer = $(Int, 99); gt(beer, $(Int, 0));) {
call(bottles, beer);
print(" on the wall, ");
call(bottles, beer);
println(".");
print("Take one down and pass it around, ");
sub(beer, $(Int, 1));
call(bottles, beer);
println(" 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.");
}Судя по репозиторию, автор интерес к своему детищу не потерял, будем надеяться, что
99 бутылок: Scratch и HQ9+
54. HQ9+ — язык, у которого только четыре оператора. «H» выводит «Hello world», «Q» печатает исходный код программы, 9 выводит «песню о пиве», а «плюс» «увеличивает аккумулятор». Язык, понятное дело, придуман в шутку и у неё есть продолжения — «объектный» «HQ9++»,
Данная программа на этом языке выглядит вот так:
953. Scratch. «Скретч» — язык программирования для школьников младших и средних классов. Интересный класс языков, я никогда им особо не интересовался, а тут возник совершенно профессиональный интерес — как можно дать возможность программировать
Я, для интереса, написал на «Скретче» свои «99 бутылок». Программа на скриншоте. В среде редактирования мы управляем лисёнком и всё программирование крутится вокруг него, куча блоков позволяют

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