99

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


99 бутылок: Small C, dbPager

14. Small C. Написав в предыдущей серии программу, выводящую песню о пиве, на Си—, я заинтересовался классом малоизвестных си-подобных языков. Благо Интернет и поисковые машины под рукой.

Первое, что мне попалось — это Small C. Впервые сведения о этом языке появились в октябре 1999 года в Dr. Dobb’s Journal. Язык простой и удобный, настолько отличен от Си, что перечислять эти отличия тут я не буду. Подробности можно найти в документации, доступной там же, на сайте.

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

Несколько матерных слов в адрес компилятора. Отвратительная диагностика, странная реакция на символы табуляции, лишние переводы строки и символы «^», неработоспособность конструкции «a?b:c» и так далее. Компиляция моего небольшого примера заняла на Pentium-II 333 примерно 10 секунд. А теперь сам листинг.

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

/* 99 beer song. Written by Stepanischev E.V. Small C */
#include <console>

printbeer (b)
{
     if (b) printf ("%d",b); else printf ("No")
     printf (" bottle")
     if (b!=1) printf ("s")
     printf (" of beer")
}

main ()
{
     for (new i = 99; i > 0;)
     {
           printbeer (i)
           printf (" on the wall, ")
           printbeer (i)
           printf (".^nTake one and pass it around,^n")
           i--
           printbeer (i)
           printf (" on the wall.^n^n")
     }

     printf ("No more bottles of beer...^n");
     printf ("Go to the store and buy some more...^n");
     printf ("99 bottles of beer.");
}

15. Язык dbPager. Предназначен для динамической генерации страничек под MS IIS. Инструкцию по настройке прекомпилятора под IIS5 я не нашел, так что тестировал под версией для командной строки. Язык несколько, на мой взгляд, необычен своей концепцией блочников и некоторыми конструкциями, но, в целом, очень хорошо читается и воспринимается.

Скрипт, выводящий песню о пиве (beer.dbp).

// Beer song. Written by Stepanischev E.V. (dbPager)
var "beer=99"
    var "LoopLimit=99" :: while 1
        var ""
            @beer:printbeer
        %Space%on the wall,
        var ""
            @beer:printbeer
        .%CrLf%
        Take one and pass it around,%CrLf%
        set "beer=[%beer%-1]"
        var ""
            @beer:printbeer
        %Space%on the wall.%CrLf%%CrLf%

No more bottles of beer...%CrLf%
Go to the store and buy some more...%CrLf%
99 bottles of beer.

:printbeer
    switch %beer%
        #0 :: No
        #else :: %beer%
    %Space%bottle
    switch %beer%
        #1 :: 
        #else :: s
    %Space%of beer


Оставить комментарий

99 бутылок: C-​-, WSH

12. Sphinx C-​-. Есть язык Си, есть Си++, а есть, оказывается, Си-​-. Язык, занимающий промежуточное положение между Си и ассемблером. Его автором является Peter Cellik (Канада), в данный момент поддержкой и расширением синтаксиса языка занимается Михаил Шекер (Россия).

Язык мне показался обычным ассемблером, с внедрёнными элементами синтаксиса Си. Этакий навороченный макроассемблер. Попался бы мне такой лет так пять назад — оторвал бы с руками, а сейчас… Но, хотя на ассемблере теперь я пишу только мелочь, а мелочь лучше писать без применения всяческих прилад, стирать все же не буду — вдруг пригодится.

P.S. Кстати, на страничке языка можно скачать архиватор HA, переписанный на Си-​-. Работать он после такой модификации стал в полтора раза быстрее. Заслуга языка и компилятора или автора модификации?

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

?use80486
?include "WRITE.h--"

void PRINTBEER ()
{
    $PUSH AX;
    IF (AX) WRITEWORD (AX); ELSE WRITESTR ("No");
    WRITESTR (" bottle");
    $POP AX;
    IF (AX<>1) WRITE ('s');
    WRITESTR (" of beer");
}

void main()
byte bott;
byte beer = 99;
{
    WHILE (beer)
    {
        PRINTBEER (beer);
        WRITESTR  (" on the wall, ");
        PRINTBEER (beer);
        WRITESTR  (".\nTake one and pass it around,\n");
        beer--;
        PRINTBEER (beer);
        WRITESTR  (" on the wall.\n\n");
    };

    WRITESTR ("No more bottles of beer...\n");
    WRITESTR ("Go to the store and buy some more...\n");
    WRITESTR ("99 bottles of beer.");

    AX = 0x4C;
    $INT 0x21;
}

13. Windows Script Host — технология, заботливо упрятанная в недра вашей Windows заботливой компанией Microsoft. Скрипт написан с применением второй версии технологии, которая распространяется вместе с Windows 2000. Впрочем, ничего не мешает поставить его на любую другую ОС этого семейства. Базируется она на JScript или VBScript и позиционируется как замена пакетному (batch) языку DOS.

Способ запуска: wscript.exe beer.js. Во время выполнения настоятельно не рекомендуется переключать окна.

Скрипт, выводящий песню о пиве (beer.js).

function PrintBeer(i)
{
    return (i?i:"No")+" bottle"+(i-1?'s':'')+" of beer"
}

WshShell = WScript.CreateObject("WScript.Shell")
with (WshShell)
{
    Run("notepad.exe")
    WScript.Sleep(100)
    AppActivate("Untitled - Notepad")

    for (i = 99; i>0;)
    {
        SendKeys (PrintBeer (i)+" of beer on the wall, ")
        SendKeys (PrintBeer (i)+".~")
        SendKeys ("Take one and pass it around,~")
        i--
        SendKeys (PrintBeer (i)+" on the wall.~~")
    }

    SendKeys ("No more bottles of beer...~")
    SendKeys ("Go to the store and buy some more...~")
    SendKeys ("99 bottles of beer.")
}


Оставить комментарий

99 бутылок: Microsoft Dialer

11. Microsoft Dialer. Можно только удивляться, сколько языков программирования можно найти у себя на компьютере. Эта песнь о пиве написана на языке программирования SCP-файлов, файлов, руководящих соединением через модем. Насколько я понял в этом языке есть примитивная арифметика, вывод, циклы и ветвление (правда без else), но нет преобразования типов. Так что переменная цикла nB используется только для упрощения. Но как бы то ни было, написать программу у меня получилось. :)

Скрипт, выводящий песню о пиве.

; "99 beer" song by Evgeny V. Stepanischev
proc main
    string szA = "9"
    string szB = "9"
    string szS = " bottles"
    string szX = ""
    string szY = ""

    integer nB = 99

    set screen keyboard on
    delay 2

    ; Эту строчку ждет мой провайдер
    ; У вас она может быть другой
    transmit "@D^M^M"

    while Nb>0 do

    if szA!="0" then
    transmit szA
    endif

    transmit szB

    szS = " bottles"
    if nB==1 then
    szS = " bottle"
    endif

    transmit szS
    transmit " of beer on the wall, "

    if szA!="0" then
    transmit szA
    endif

    transmit szB
    transmit szS
    transmit " of beer.^M"
    transmit "Take one and pass it around,^M"

    szX = szA

    if szB=="0" then
        if szA=="1" then
        szX = "0"
        endif

        if szA=="2" then
        szX = "1"
        endif

        if szA=="3" then
        szX = "2"
        endif

        if szA=="4" then
        szX = "3"
        endif

        if szA=="5" then
        szX = "4"
        endif

        if szA=="6" then
        szX = "5"
        endif

        if szA=="7" then
        szX = "6"
        endif

        if szA=="8" then
        szX = "7"
        endif

        if szA=="9" then
        szX = "8"
        endif

    szY = "9"

    endif

    if szB=="1" then
    szY = "0"
    endif

    if szB=="2" then
    szY = "1"
    endif

    if szB=="3" then
    szY = "2"
    endif

    if szB=="4" then
    szY = "3"
    endif

    if szB=="5" then
    szY = "4"
    endif

    if szB=="6" then
    szY = "5"
    endif

    if szB=="7" then
    szY = "6"
    endif

    if szB=="8" then
    szY = "7"
    endif

    if szB=="9" then
    szY = "8"
    endif

    szA = szX
    szB = szY

    nB = nB - 1

    if nB==0 then
    transmit "No more bottles of beer on the wall.^M"
    endif

    if nB!=0 then
    if szA!="0" then
    transmit szA
    endif

    transmit szB

    szS = " bottles"
    if nB==1 then
    szS = " bottle"
    endif

    transmit szS
    transmit " of beer on the wall.^M^M"
    endif

    endwhile


    transmit "No more bottles of beer...^M"
    transmit "Go to the store and buy some more...^M"
    transmit "99 bottles of beer.^M"

    delay 99
endproc

Оставить комментарий

99 бутылок: ASP (JScript и JavaScript), Parser

Жаждались? Судя по кислым лицам — нет. Итак, представляю очередную серию из мыльного сериала «99 бутылок пива на стене». На этот раз, на стене амбициозный Парсер с хорошей родословной, но плохой внешностью и братья-почти-что-близнецы JavaScript и ASP.

9. Parser (втрой версии) студии Артемии Лебедева. Предпроцессор для генерации Веб-страниц «на лету».

^var[i;99]
^while[i>0;

^var[i] bottle^if[i!=1;s;] of beer on the wall, ^var[i]
bottle^if[i==1;s;] of beer.<BR>
Take one and pass it around,<BR>
^var[i;-;1]
^if[i;^var[i];No] bottle^if[i!=1;s;] 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.

10. ASP JScript и JavaScript. Одновременно. Первый — серверный язык, второй — клиентский. Испытано под IE 5.0, Opera 5.01, Netscape 4.75, Netscape 6.0 и IIS5.

<!-- <%@ LANGUAGE = JScript %>

<% //>
//</%> --> <SCRIPT LANGUAGE=JavaScript>
for (k = ' of beer on the wall',o='', i = 99; i>0; i--)
{
    a = i+' bottle'+(i-1?'s':'')
    o+= a+k+', '+a+' of beer...<BR>'+
    'Take one down, pass it around.<BR>'+
    (i-1?i-1:'No ')+' bottle'+(i-2?'s':'')+k+'.'+
    '<BR><BR>'
}

o+= 'No more bottles of beer...<br>'+
'Go to the store and buy some more...<br>'+
'99 bottles of beer.'

if (typeof(document)!='undefined') document.write (o); else
if (typeof(Response)!='undefined') Response.Write (o)
// </SCRIPT> <!-- // < %> -->


Оставить комментарий

99 бутылок: SHS SSI, Price Convertor Small Talk

Эпопея о бутылках с пивом продолжается. Сегодня вашему вниманию предлагается тексты программы, выводящие песню о бутылках на языках Small HTTP Server SSI и Price Convertor Short Talk 2.00rc2.

7. Small HTTP Server SSI. Вариант реализации SSI для SHS, написанного Максом Фиоктистовым. Файл должен называться index.shtm.

<!--#if expr="$b=No" -->
<BODY BGCOLOR=BLACK TEXT=WHITE>
No more bottles of beer...<BR>
Go to the store and buy some more...<BR>
99 bottles of beer.</BODY>
<!--#break -->
<!--#endif -->
<!--#set var="" value="" -->
<!--#set var="N" value="No" -->
<!--#set var="9" value="8" -->
<!--#set var="8" value="7" -->
<!--#set var="7" value="6" -->
<!--#set var="6" value="5" -->
<!--#set var="5" value="4" -->
<!--#set var="4" value="3" -->
<!--#set var="3" value="2" -->
<!--#set var="2" value="1" -->
<!--#set var="1" value="0" -->
<!--#set var="0" value="9" -->

<!--#if expr="!$a" -->
<!--#set var="a" value="9" -->
<!--#set var="b" value="9" -->
<!--#set var="s" value="bottles" -->
<!--#set var="m" value="$s" -->
<!--#endif -->
<!--#set var="t" value="$a" -->

<!--#if expr="$b=0" -->
<!--#set var="c" value="$a" -->
<!--#elif expr="$a>0" -->
<!--#set var="c" value="t" -->
<!--#endif -->
<!--#set var="d" value="$b" -->

<!--#if expr="$a=||$a=0||$c=1" -->
<!--#set var="c" value="" -->
<!--#endif -->

<!--#if expr="$d=1&&$c=" -->
<!--#set var="d" value="N" -->
<!--#elif expr="$d=2&&$c=" -->
<!--#set var="m" value="bottle" -->
<!--#endif -->

<HEAD>
<META HTTP-EQUIV="Refresh" Content="1;URL=index.shtm?a=<!--#echo var="$c" -->
&b=<!--#echo var="$d" -->&m=<!--#echo var="m" -->
&s=<!--#echo var="m" -->">
</HEAD>
<BODY BGCOLOR=BLACK TEXT=WHITE>
<!--#echo var="a" --><!--#echo var="b" -->
<!--#echo var="s" --> of beer on the wall,<BR>
Take one and pass it around,<BR>
<!--#echo var="$c" --><!--#echo var="$d" -->
<!--#echo var="m" --> of beer on the wall.
</BODY>

8. Price Contertor Small Talk 2.00rc2. Этот язык я придумал сам, реализован он был примерно в 1998 году, как внутреннее средство управления программой обработки прайсов, представленных виде файлов Excel.

BEGIN
    "99"
    mov a "bottle(s) of beer on the wall."
END
WORK    "*"
    eq "No"
    if
        echo "No more bottles of beer..."
        echo "Go to the store and buy some more..."
        echo "99 bottles of beer."
        break ""
    endif

    else
        delete
        mov Y a
        .
        echo
        echo "Take one and pass it around,"
        mov Y "1"
        -
        eq "0"
        if
            mov Y "No"
        endif

        delete
        mov Y a
        .
        echo
    endelse
    prev
END


Оставить комментарий

99 бутылок: PostgreSQL, MySQL, xSSI, CMD, PHP, JUnix Shell

Есть такой прелюбопытный сайт «99 Bottles of Beer on The Wall». Это сборник листингов программ, написанных на разных языках, но выводящих один и тот же текст — «песню про пиво». Как ни странно, но я обнаружил, что могу пополнить список из 227 языков, представленных на сайте, еще своими 6 экземплярами. Что я без промедления и сделал. Но, так как владелец сайта занят переездом на новый адрес и ему пока не до меня, я решил выложить эти образцы здесь, чтобы широкая общественность могла полюбоваться делом рук моих.

1. PostgreSQL (СУБД) https://www.postgresql.org/

YourTable — это ваша таблица с числом строк более 100.

-- Written by Evgeny.Stepanischev at ksu.ru
-- 
CREATE SEQUENCE temp_beer_seq INCREMENT -1 MINVALUE 0 MAXVALUE 99 START 99;
CREATE FUNCTION temp_b() RETURNS text
AS 'SELECT \' bottle\'||CASE WHEN last_value=1 THEN
\'\'::text ELSE \'s\'::text END||\' of beer\' FROM temp_beer_seq'
LANGUAGE 'sql';
        
CREATE FUNCTION temp_b_out() RETURNS text
AS 'SELECT s.last_value||temp_b()||\' on the wall, \'||
s.last_value||temp_b()||\'.\\n Take one and pass it around,\\n \'||
CASE WHEN NEXTVAL(\'temp_beer_seq\')=0 THEN \'No\'
 ELSE text(s.last_value-0) END||
temp_b()||\' on the wall.\\n\'
FROM temp_beer_seq s'
LANGUAGE 'sql';

SELECT CASE WHEN temp_beer_seq.last_value=0
THEN 'No more bottles of beer...\n Go to the store and buy some more...\n
 99 bottles of beer.' ELSE temp_b_out() END
FROM YourTable LIMIT 100,1;
                    -- 

DROP SEQUENCE temp_beer_seq;
DROP FUNCTION temp_b();
DROP FUNCTION temp_b_out();
-- END

2. MySQL (СУБД) https://www.mysql.com/
YourTable — это ваша таблица с числом строк более 100.

/* Program by Evgeny.Stepanischev at ksu.ru*/
SET @beer:=100;
SET @w:=' on the wall';
SELECT IF(@beer<2,'\nNo more bottles of beer...\n\
Go to the store and buy some more...\n99 bottles of \
beer.',CONCAT(CONCAT('\n',@str:=CONCAT(@beer:=@beer-1,\
@bot:=CONCAT(' bottle',IF (@beer>1,'s',''),' of beer')),\
@w,', ',@str,'.\nTake one and pass it around,\n'), IF \
(@beer-1=0,'No more ',@beer-1),@bot,@w,'.')) as beer
FROM YourTable LIMIT 100;


3. xSSI для Apache https://httpd.apache.org/
Знаком «█» обозначено место, где перевод строки не нужен,
просто строчки такие длинные, что пришлось их разбить.

<!-- Written by Evgeny.Stepanischev at ksu.ru -->
<!--#if expr="$D=A || $D=B" -->
        <!--#if expr="$K=/${D}8/" -->
        <!--#set var="D" value="8" -->
        <!--#set var="M" value="7" -->
        <!--#elif expr="$K=/${D}7/" -->
        <!--#set var="D" value="7" -->
        <!--#set var="M" value="6" -->
        <!--#elif expr="$K=/${D}6/" -->
        <!--#set var="D" value="6" -->
        <!--#set var="M" value="5" -->
        <!--#elif expr="$K=/${D}5/" -->
        <!--#set var="D" value="5" -->
        <!--#set var="M" value="4" -->
        <!--#elif expr="$K=/${D}4/" -->
        <!--#set var="D" value="4" -->
        <!--#set var="M" value="3" -->
        <!--#elif expr="$K=/${D}3/" -->
        <!--#set var="D" value="3" -->
        <!--#set var="M" value="2" -->
        <!--#elif expr="$K=/${D}2/" -->
        <!--#set var="D" value="2" -->
        <!--#set var="M" value="1" -->
        <!--#elif expr="$K=/${D}1/" -->
        <!--#set var="D" value="1" -->
        <!--#set var="M" value="0" -->
        <!--#elif expr="$K=/${D}0/" -->
        <!--#set var="D" value="0" -->
        <!--#else -->
        <!--#set var="D" value="9" -->
        <!--#set var="M" value="8" -->
        <!--#endif -->

<!--#else -->

        <!--#set var="D" value="A" -->
        <!--#set var="K" value="$QUERY_STRING" -->
        <!--#include virtual="$DOCUMENT_NAME" -->
        <!--#set var="A" value="$D" -->
        <!--#set var="Am" value="$M" -->

        <!--#set var="D" value="B" -->
        <!--#include virtual="$DOCUMENT_NAME" -->
        <!--#set var="B" value="$D" -->
        <!--#set var="Bm" value="$M" -->

        <!--#if expr="$A=0 && $B=0" -->
                <BODY BGCOLOR="BLACK" TEXT="WHITE"><B>
                No more bottles of beer...<br>
                Go to the store and buy some more...<br>
                99 bottles of beer.
                </BODY>
        <!--#else -->

                <HEAD>
                <!--#if expr="$B=0" -->
                        <!--#set var="A1" value="$Am" -->
                        <!--#set var="B1" value="9" -->
                <!--#else -->
                        <!--#set var="A1" value="$A" -->
                        <!--#set var="B1" value="$Bm" -->
                <!--#endif -->
                <META HTTP-EQUIV="Refresh" Content="1;█
URL=http://<!--#echo var="HTTP_HOST" --><!--#echo var="DOCUMENT_URI" -->?A█
<!--#echo var="A1" -->B<!--#echo var="B1" -->">
                </HEAD>

                <BODY BGCOLOR=BLACK TEXT=WHITE><B>
                <!--#if expr="$A>0" --><!--#echo var="A" --><!--#endif -->█
<!--#echo var="B" -->
                bottle<!--#if expr="$A$B>1" -->s<!--#endif -->
                of beer on the wall, <!--#if expr="$A>0" -->█
<!--#echo var="A" --><!--#endif --><!--#echo var="B" -->
                bottle<!--#if expr="$A$B>01" -->s<!--#endif --> of beer.<br>
                Take one and pass it around,<br>

                <!--#if expr="$A1$B1>00" -->
                        <!--#if expr="$A1>0" --><!--#echo var="A1" -->█
<!--#endif --><!--#echo var="B1" -->
                        bottle<!--#if expr="$A1$B1>01" -->s█
<!--#endif --> of beer on the wall.
                <!--#else -->
                        No more bottles of beer on the wall.
                <!--#endif -->
                <!--#set var="C" value="" -->
                <BR>
                </B></BODY>
        <!--#endif -->
<!--#endif -->


4. Win2000 batch file (CMD)

@ECHO OFF
REM Evgeny.Stepanischev at ksu.ru

FOR /L %%B IN (99,-1,1) DO CALL :PROG %%B
ECHO No more bottles of beer...
ECHO Go to the store and buy some more...
ECHO 99 bottles of beer. 
GOTO :EOF

:PROG
ECHO %1 bottle(s) of beer on the wall, %1 bottle(s) of beer.
ECHO Take one and pass it around,
SET /A S=%1-1
IF %S% EQU 0 SET S=No
ECHO %S% bottle(s) of beer on the wall.
ECHO.


5. PHP https://www.php.net/

<?
for ($s='s' and $beer=99;$beer;)
{
    echo "$beer bottle$s of beer on the wall, $beer bottle$s of beer.<br>",
    "\nTake one and pass it around,<br>";
    $beer--;
    $s = $beer==1?'':'s';
    if ($beer) echo "$beer bottle$s of beer on the wall.<br><br>";
};
?>
No more bottles of beer on the wall.<br><br>
No more bottles of beer...<br>Go to the story and buy some more...<br>
99 bottles of beer.


6. JUnix SHell junix.kzn.ru https://github.com/bolknote/junix
Предупреждаю: JUSH работает настолько медленно, что вы вряд ли дождетесь результата работы. Для испытания лучше уменьшить константу «beer» до 4-х.

set beer=99
set s=s
while ($beer gt 0)
echo $beer bottle$s of beer on the wall, $beer bottle$s of beer.
echo Take one and pass it around,
set beer--
if ($beer==1) set s=
if ($beer) echo $beer bottle$s of beer on the wall.\n
end
cat <<T
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.
T


Оставить комментарий

← 1 2 3 4 →