38 заметок с тегом

99

У американцев есть такая считалочка — «песня о пиве», наверняка её многие слышали в американских фильмах. У меня есть хобби — делать вывод этой считалочки на разных языках программирования. Со временем набралась приличная коллекция.

Позднее Ctrl + ↑

99 бутылок: Scratch и HQ9+

54. HQ9+ — язык, у которого только четыре оператора. «H» выводит «Hello world», «Q» печатает исходный код программы, 9 выводит «песню о пиве», а «плюс» «увеличивает аккумулятор». Язык, понятное дело, придуман в шутку и у неё есть продолжения — «объектный» «HQ9++», Тюринг-полный «HQ9+B» и так далее.

Так что данная программа на этом языке выглядит вот так:

9


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

Я, для интереса, написал на «Скретче» свои «99 бутылок». Программа на скриншоте. В среде редактирования мы управляем лисёнком и всё программирование крутится вокруг него, куча блоков позволяют что-то с ним делать — двигать, вращать, заставляют его что-то говорить и так далее. «Думать» выводит свой аргумент в  «облачке» его мыслей.

Скретч (84.30КиБ)

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

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

Есть ещё какие-то «Другие блоки», но с ними я не разбирался. Кажется, через них можно как-то расширять язык.

99 бутылок: AppleScript, Applesoft BASIC

У меня тут мой ноут поперхнулся чаем, так что я неделю был на стареньком компике под Виндой, почувствовал себя себя как без рук. По этой же причине почти не писал ничего в блог, лишь одним вечером на ноуте жены написал очередные две «Песни про пиво» на языках AppleScript и Applesoft BASIC. Первый — современный язык для автоматизации мелочи на «Маках», второй — древний (1977 год) бейсик, когда-то так же использовавшийся на «Маках».

52. AppleScript — встроенный в операционную систему «МакОС» язык программирования, используемый для мелкой автоматизации. По программе этой не очень очевидно, но язык максимально приближен к английскому, причём многие вещи можно формировать разнообразными способами — так же, как бы это сделал носитель английского языка.

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

(* Песня про пиво. Автор — Евгений Степанищев *)
repeat with beer from 99 to 1 by -1
     set b to bottles(beer)
     log b & " on the wall, " & b & "."
     log "Take one down and pass it around, " & bottles(beer - 1) & " of beer on the wall."
     log
end repeat

log "No more bottles of beer on the wall, no more bottles of beer."
log "Go to the store and buy some more, 99 bottles of beer on the wall."

on bottles(beer)
     if beer = 0 then
 	        return "no bottles"
     else if beer > 1 then
 	        return (beer as string) & " bottles"
     else
 	        return "1 bottle"
     end if
end bottle


51. Applesoft BASIC — Бейсик разработанный компанией Майкрософт, использовавшийся в компьютерах фирмы Эпл, начиная с 1977 года. Ничего особо примечательного, вполне полнофункциональный язык, хоть и не без недостатков тех ранних «бейсиков» — вызов функций по номеру строки, параметров нет, локальных переменных нет, в общем, все прелести.

Я специально использовал конструкцию «ON…GOTO», хоть в ней и не было необходимости — хотел показать аналог конструкции switch. SGN тут — встроенная функция нахождения знака выражения.

000 REM Песня про пиво, автор — Евгений Степанищев
001 HOME: TEXT
010 FOR beer = 99 TO 1 STEP -1
020 b = beer: GOSUB 100
030 ? bottles$; " on the wall, "; bottles$; "."
035 b = beer - 1: GOSUB 100
040 ? "Take one down and pass it around, "; bottles$; " of beer on the wall."
050 ?
060 NEXT
070 ? "No more bottles of beer on the wall, no more bottles of beer."
080 ? "Go to the store and buy some more, 99 bottles of beer on the wall."
090 END
099 REM
100 ON SGN(b-1)+2 GOTO 120, 130, 110
110 LET bottles$ = STR$(b) + " bottles": RETURN
120 LET bottles$ = "no bottles": RETURN
130 LET bottles$ = "1 bottle": RETURN

99 бутылок: Batsh, VIM script

Потихоньку возобновил наполнение раздела «99 бутылок пива на стене» — тут я пишу американскую считалочку про пиво на различных языках программирования. Добавились языки VIM script и Batsh. Первый используется в консольном редакторе vim для написания внутренних скриптов, второй — для кроссплатформенного написания шелл-скриптов.

Batsh мне вообще понравился своей идеей — простой Си-подобный язык, который умеет транслироваться и в баш (Линукс, МакОС и так далее) и в бат-файлы (Виндоуз). Не уверен нужно ли это в жизни, но абстрактно идея хороша.

50. Batsh — чрезвычайно лёгкий в освоении язык с Си-подобным синтаксисом, который умеет транслироваться в баш- и бат-скрипты, т. е. скрипты, которые будут без проблем работать и в мире Линукса, и в мире Виндоуз. Язык без особых затей, работает, похоже, железобетонно, но бедноват — даже обычного цикла for в нём нет. В общем набор минимальный (хотя рекурсия есть), но программировать можно.

// Песня о пиве на языке Batsh Степанищева Евгения

function bottles(bottle){
    if (bottle == 0) {
        return "no bottles";
    }
    
    if (bottle == 1) {
        return "1 bottle";
    }
    
    return bottle ++ " bottles";
}

i = 99;
while (i > 0) {
    b = bottles(i) ++ " of beer";

    println(b, "on the wall,", b ++ ".");
    i = i - 1;
    println("Take one down and pass it around,", bottles(i), "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.");


49. VIM Script — встроенный скриптовый язык программирования консольного редактора VIM. Синтаксис довольно обычен, учится легко. Мощный для своего класса — обилие встроенных функций, довольно согласованный синтаксис, различные типы массивов. Есть интересные особенности, например, возможность явного переопределения функций, префиксы переменных для явного определения зоны видимости (например, префикс «a:» у меня в функции — это аргументы) или функции, которые могут принимать что-то вроде примитивного итератора.

" написал Евгений Степанищев bolknote.ru"

:function Bottles(bottle)
:    return get(["no bottles", "1 bottle"], a:bottle, a:bottle . " bottles")
:endfunction

:for beer in range(99, 1, -1)
:   let b =  Bottles(beer) . " of beer"
:   echo b "on the wall," b . "."
:   echo "Take one down and pass it around, " . Bottles(beer-1) . " of beer on the wall.\n"
:endfor

: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."

99 бутылок: Go

48. Go — язык программирования, придуманный в «Гугле». Я на нём программирую, время от времени, и довольно неплохо его уже знаю. Замечательный, на мой взгляд, язык. Этакий «Си с человеческим лицом». Особенно интересно добавлено туда ООП, да и параллельные вычисления сделаны хорошо. Единственно — не нравится реализация обработки ошибок через panic/defer.

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

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

package main
import "strconv"

func main() {
    for i := 99; i>0; i-- {
        b := bottles(i) + " of beer"

        println(b + " on the wall, " + b + ".")
        println("Take one down and pass it around, " + bottles(i-1) + " 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.")
}

func bottles(beer int) string {
    switch (beer) {
        case 0:
            return "no bottles"
        case 1:
            return "1 bottle"
    }

    return strconv.Itoa(beer) + " bottles"
}

99 бутылок: КуМир

47. КуМир — очередной неинтересный язык программирования «Комплект учебных Миров или Миры Кушниренко».

В 1995 году «КуМир» (о ужас!) был рекомендован Министерством образования РФ в качестве основного учебного материала по курсу «Основы информатики и вычислительной техники» на основе учебника А. Г. Кушниренко, Г. В. Лебедева и Р. А. Свореня.

Совершенно неинтересно про него рассказывать, если честно, хотя среда разработки очень неплоха в плане диагностики ошибок.

| написал Евгений Степанищев bolknote.ru

алг песня про пиво
нач
    цел пиво
    нц для пиво от 99 до 1 шаг -1
        вывод сколько пива(пиво), ' on the wall, ', нс
        вывод 'Take one and pass around,', нс
        вывод сколько пива(пиво-1), ' on the wall.', нс, нс
    кц
    вывод "No more bottles of beer...", нс
    вывод "Go to the store and buy some more...", нс
    вывод "99 bottles of beer."
кон

алг лит сколько пива(цел пиво)
нач
    если пиво = 0 то
        знач:="No"
    иначе
        знач:=цел_в_лит(пиво)
    все

    знач:=знач + ' bottle'

    если пиво <> 1 то
        знач:=знач+'s'
    все
кон

99 бутылок: gnuplot

46. gnuplot — программа для построение графиков, имеющая довольно развитый язык программирования. Основная особенность — отсутствие циклов, хотя доступна их эмуляция — через команду перезагрузки файла (reread).

Программа, выводящая песню о пиве (beer.gp)

# Написал Евгений Степанищев

bottles(beer) = beer == 1 ? '1 bottle' : beer ? sprintf('%d bottles', beer) : 'no bottles'

if (!exists("beer")) beer=99
print bottles(beer), " of beer on the wall, ", bottles(beer)," of beer\n",\
      "Take one and pass it around,"

beer=beer-1

print bottles(beer)," of beer on the wall.\n"

if (beer>0) reread

print "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."

99 бутылок: PowerShell

45. Windows Powershell. Наконец-то в Windows появился мощный, красивый язык командной строки. Язык построен на конвейерах, где по конвейеру передаётся не просто текст, а объекты. Особый интерес представляет интеграция с .NET Framework и WMI.

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

Программа, выводящая песню о пиве (beer.ps1)

# Написал Евгений Степанищев aka BOLK

function bottles([int]$beer) {
    switch ($beer) {
        0       { "no bottles" }
        1       { "1 bottle" }
        default { "$beer bottles" }
    }
}

99..1 | ForEach-Object {
    $bottles = (bottles $_) + ' of beer'

    $bottles + ' on the wall, ' + $bottles + '.'
    'Take one down and pass it around, ' + (bottles($_-1)) + " of beer 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 бутылок: РАЯ, MS HTML

44. РАЯ (русский алгоримический язык). Язык, придуманный академиком Ершовым для обучения детей программированию. Все названия на русском языке, что, впрочем, совершенно не отвлекает. Для написания программы я использовал падучую реализацию языка с сайта «Инфомир».

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

| Написал Евгений Степанищев aka BOLK
алг
нач
    цел сколько пива

    нц для сколько пива от 99 до 1 шаг -1
        выводим пиво(сколько пива, " on the wall, ") 
        выводим пиво(сколько пива, ".")

        вывод нс, "Take one and pass it around,", нс
        выводим пиво(сколько пива, " on the wall.")
        вывод нс, нс
    кц

    вывод "No more bottles of beer:", нс
    вывод "Go to the store and buy some more:", нс
    вывод "99 bottles of beer." 
кон

алг выводим пиво(цел пива, лит окончание)
нач
    вывод число пива(пива), " bottle"
    если пива > 1 или пива=0
        то вывод "s"
    все
    вывод окончание
кон

алг лит число пива(цел пива)
нач
    если пива=0
        то знач:="No"
        иначе знач:=цел_в_лит(пива)
    все
кон


43. MS HTML. Конечно, HTML не является языком программирования. Но и на этом языке разметки, применяя особенности Internet Explorer, можно написать песню про пиво. Лишнюю строку пришлось «спрятать» за экран. Работает, естественно, только в Internet Explorer.

<!-- Written by Evgeny "BOLK" Stepanischev -->
<style type="text/css">
    .outer { position: absolute; top: -20px }
    body { background: white; margin: 0; padding: 10px }
    body, table { font-size: 11px; font-family: Tahoma }
    table, td, tr { margin: 0; padding: 0; border-collapse: collapse }
</style>

<body>
<xml id="dataOuter">
<row>
    <d><o>9</o></d>
    <d><o>8</o></d>
    <d><o>7</o></d>
    <d><o>6</o></d>
    <d><o>5</o></d>
    <d><o>4</o></d>
    <d><o>3</o></d>
    <d><o>2</o></d>
    <d><o>1</o></d>
</row>
</xml>

<xml id="dataInner">
<row>
    <d><i>9</i></d>
    <d><i>8</i></d>
    <d><i>7</i></d>
    <d><i>6</i></d>
    <d><i>5</i></d>
    <d><i>4</i></d>
    <d><i>3</i></d>
    <d><i>2</i></d>
    <d><i>1</i></d>
    <d><i>0</i></d>
</row>
</xml>

<xml id="dataInnerSingle">
<row>
    <d><i>9</i><s>s</s></d>
    <d><i>8</i><s>s</s></d>
    <d><i>7</i><s>s</s></d>
    <d><i>6</i><s>s</s></d>
    <d><i>5</i><s>s</s></d>
    <d><i>4</i><s>s</s></d>
    <d><i>3</i><s>s</s></d>
    <d><i>2</i><s>s</s></d>
    <d><i>1</i></d>
</row>
</xml>

<div class="outer">
<table datasrc="#dataOuter">
<tr>
<td>

<table datasrc="#dataInner">
<tr>
<td>
<span datafld="o"></span><span datafld="i"></span>&nbsp;beer bottles
of beer on the wall.<br /><br />
<span datafld="o"></span><span datafld="i"></span>&nbsp;beer bottles
of beer on the wall,
<span datafld="o"></span><span datafld="i"></span>&nbsp;bottles of beer.<br />
Take one and pass it around,<br />
</td>
</tr>
</table>

</td>
</tr>
</table>

<table datasrc="#dataInnerSingle">
<tr>
<td>
<span datafld="i"></span>&nbsp;beer
bottle<span datafld="s"></span> of beer on the wall.<br /><br />
<span datafld="i"></span>&nbsp;beer
bottle<span datafld="s"></span> of beer on the wall,
<span datafld="i"></span>&nbsp;bottle<span datafld="s"></span>
of beer.<br />
Take one and pass it around,<br />
</td>
</tr>
</table>

No beer bottle of beer on the wall.<br />
<br />
No more bottles of beer...<br />
Go to the store and buy some more...<br />
99 bottles of beer.
</div>
</body>

99 бутылок: TheBAT!

42. TheBAT! На языке макросов почтового клиента TheBAT! 1.63b8. Ужасный язык. Плохо выглядит, трудно читается. Есть регулярные выражения, ветвление и вызов быстрых шаблонов (некий эквивалент процедур). Только в последней версии появились определяемые пользователем переменные (конструкция %_nnn или %SETnnn). Если будете испытывать, пустые строки в конце шаблонов нужно удалить.

* основной шаблон *
%REM="Beer song. Written by Evgeny Stepanischev"
%_BE1=9%_BE2=9%QINCLUDE="beer_loop"%-
No more bottles of beer:
Go to the store and buy some more:
99 bottles of beer.

* быстрый шаблон beer_loop *
%QINCLUDE="print_beer" on the wall, %QINCLUDE="print_beer".
Take one and pass around,
%IF:"%_BE2"="0":'%_BER=%_BE1%QINCLUDE="dec"%_BE1=%_BER%_BE2=9':'%_BER=%_BE2%QINCLUDE="dec"%_BE2=%_BER'%-
%QINCLUDE="print_beer" on the wall.

%IF:"%_BE1%_BE2"="00":"":'%QINCLUDE="beer_loop"'%-

* быстрый шаблон print_beer *
%IF:"%_BE1%_BE2"="00":'No':'%IF:"%_BE1">"0":"%_BE1%_BE2":"%_BE2"'%-
bottle%QINCLUDE="beers" of beer%-

* быстрый шаблон beers *
%IF:"%_BER"="1":"":"s"%-

* быстрый шаблон dec *
%IF:"%_BER"="1":"%_BER=0":""%-
%IF:"%_BER"="2":"%_BER=1":""%-
%IF:"%_BER"="3":"%_BER=2":""%-
%IF:"%_BER"="4":"%_BER=3":""%-
%IF:"%_BER"="5":"%_BER=4":""%-
%IF:"%_BER"="6":"%_BER=5":""%-
%IF:"%_BER"="7":"%_BER=6":""%-
%IF:"%_BER"="8":"%_BER=7":""%-
%IF:"%_BER"="9":"%_BER=8":""%-

99 бутылок: Refal-5, FOCAL

41. FOCAL. Название языка произошло от сокращения «Formula CALculator». В настоящее время язык, можно сказать, умер — в интернете мне с большим трудом удалось найти его описание. Ни одной действующей версии компилятора или интерпретатора языка мне найти не удалось.

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

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

Уже после выхода этой песни, со мной связался Алексей Томин и привёл описание функции FSBR. Вот, что он пишет: FSBR позволяет определить функцию с одним аргументом (с использованием & как параметра). Самое интересное — возможна рекурсия.

Пример, вычисление факториала:

11.1 I (&-1) 11.3,11.3,11.2
11.2 S &=&*FSBR(11,&-1)
11.3 R

Программа, выводящая песню о пиве (beer)

1.10 COMMENT Beer song. Written by Evgeny Stepanischev
1.20 FOR I=99, -1, 1; DO 2
1.30 TYPE "No more bottles of beer...", !
1.40 TYPE "Go to the store and buy some more...", !
1.50 TYPE "99 bottles of beer.", !
1.60 QUIT

2.10 SET B=1; DO 3; TYPE " on the wall, "; DO 3
2.20 TYPE !, "Take one and pass around,", !
2.30 SET B=2; DO 3; TYPE " on the wall.", !

3.10 DO 4.10; TYPE " of beer"; RETURN

4.10 IF (I-B) 4.20, 4.30, 4.40
4.20 TYPE "No bottles"; RETURN
4.30 TYPE "1 bottle"; RETURN
4.40 TYPE %4.00, I, "bottles"; RETURN


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

«Рефал» — язык манипулирования символьными объектам: текстами, формулами, программами и т. п. Программа на «Рефале» состоит из функций, которые могут определяться друг через друга, т. е. рекурсивно. Отсюда и название: «Алгоритмический язык Рекурсивных Функций». Язык «Рефал» был создан В. Турчиным в качестве метаязыка для описания семантики других языков. Язык определения функций «Рефала», основанный на понятиях образца и результатного выражения, чрезвычайно прост и компактен. Образцы — […] в сжатой и наглядной форме обеспечивают как запись условий на вид аргумента, так и разбиение аргумента на составные части.

Программа, выводящая песню о пиве (beer.ref):

** Beer song. Written by Evgeny Stepanischev

Pr   {
     e1 = <PRINTLN! *STDOUT e1>;
     };

S    {
     1  = ;
     e1 = 's';
     };

Beer {
     0 = 'No bottles of beer';
     e1, <S e1>: e2 = e1 ' bottle' e2 ' of beer';
     };

Beers
    {
    e1 (e2), <Beer e1>: e.beer =
        <Pr e.beer ' on the wall, ' e.beer '.'>
        <Pr 'Take one and pass around,'>
        <Pr <Beer e2> ' on the wall.'>
        <Pr>;
    };

Start
    {
    0  = <Pr 'No more bottles of beer...'>
         <Pr 'Go to the store and buy some more...'>
         <Pr '99 bottles of beer.'>;

    e1, <- e1 1>: e2  = <Beers e1 (e2)> <Start e2>;
    };

$EXEC Start 99;
Ранее Ctrl + ↓