99
У американцев есть такая считалочка — «песня о пиве», наверняка её многие слышали в американских фильмах. У меня есть хобби — делать вывод этой считалочки на разных языках программирования. Со временем набралась приличная коллекция.
99 бутылок: Small C, dbPager
14. Small C. Написав в предыдущей серии программу, выводящую песню о пиве, на Си—, я заинтересовался классом малоизвестных
Первое, что мне попалось — это Small C. Впервые сведения о этом языке появились в октябре 1999 года в Dr. Dobb’s Journal. Язык простой и удобный, настолько отличен от Си, что перечислять эти отличия тут я не буду. Подробности можно найти в документации, доступной там же, на сайте.
Интересно, что исполнение программ происходит, как и в Java, в два этапа. На первом программа прекомпилируется
Несколько матерных слов в адрес компилятора. Отвратительная диагностика, странная реакция на символы табуляции, лишние переводы строки и символы «^», неработоспособность конструкции «a?b:c» и так далее. Компиляция моего небольшого примера заняла на
Программа, выводящая песню о пиве (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
Язык мне показался обычным ассемблером, с внедрёнными элементами синтаксиса Си. Этакий навороченный макроассемблер. Попался бы мне такой лет так пять назад — оторвал бы с руками, а сейчас… Но, хотя на ассемблере теперь я пишу только мелочь, а мелочь лучше писать без применения всяческих прилад, стирать все же не буду — вдруг пригодится.
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
endproc99 бутылок: ASP (JScript и JavaScript), Parser
Жаждались? Судя по кислым лицам — нет. Итак, представляю очередную серию из мыльного сериала «99 бутылок пива на стене». На этот раз, на стене амбициозный Парсер с хорошей родословной, но плохой внешностью
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
END99 бутылок: 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();
-- END2. 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»
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