То, чего вы не ждали от калькулятора. Пасьянс на bc

  • Tutorial
Невинные развлечения с bash больше не кажутся мне чем-то особенным. В качестве своей следующей цели для экспериментов я выбрала GNU bc — консольный калькулятор и скриптовый математический язык программирования в одной коробке. Эта статья наверняка будет полезна всем линуксоидам и юниксоидам, не очень тесно знакомым с bc.



Итак, короткое введение в программирование на bc, кавай и нэки пасьянс на чистом bc и поэтессы.

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

Девятый кю (белый пояс)


Запустить калькулятор можно очевидной командой bc. После этого можно вводить выражения для вычисления. Нажатие на Enter сразу выдаст результат.

c
carrot@ubuntu:~$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
>2*2
4
>3*(6+1)
21
>5||(1&&0)
1
>5/2
2


В выражениях можно использовать скобки, знаки сложения, вычитания, деления и умножения, а так же && (логическое «и»), || (логическое «или») и! (логическое «не»).

Шестой кю (зеленый пояс)


В калькуляторе bc можно и нужно использовать переменные. Чтобы определить переменную, нужно записать её имя, поставить знак «равно» и затем записать значение переменной. Всё как везде.
>raw=3116
>raw+1
3117


Самые внимательные успели обнаружить, что калькулятор округляет все числа до целых. Причина в следующем: специальная переменная scale, определяющая точность вычислений, по умолчанию равна нулю. Если вы хотите получить результат с точностью до десяти знаков, то присвойте переменной число 10.
>5/2
2
>scale=10
>5/2
2.5000000000
>7/191
.0366492146


В bc есть ещё три специальных переменных. Last хранит в себе прошлый результат вычислений, obase и ibase используются для работы с различными системами счисления.
>1
1
>last+10
11
>obase=16
>last
B
>255+1
100
>ibase=16
>FE+1
FF


Пятый кю (голубой пояс)


Пришло время научиться работать со стандартной библиотекой и подключать сторонние функции. Чтобы использовать стандартную библиотеку языка bc, нужно запускать его с параметром -l:
carrot@ubuntu:~$ bc -l
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
>s(3)
.14112000805986722210

В стандартной библиотеке определены следующие функции:
  • s (x) — синус x
  • c (x) — косинус x
  • a (x) — арктангенс x
  • l (x) — натуральный логарифм x
  • e (x) — экспонента от x
  • j (n,x) — функция Бесселя n-го порядка от x


Чтобы использовать сторонние библиотеки, стоит скачать их, например, с сайтов phodd.net/gnu-bc и http://marcmmw.freeshell.org/esp/programacion/bc.html. Вы найдете процедуры для работы с массивами, интегралами, производными, логикой, генераторы случайных чисел и многое другое. Моя любимая библиотека — для работы с изображениями в формате ppm. Это на bash можно что хочешь генерировать — хоть bmp, хоть jpeg, а здесь всё суровее. Не EГГОГология, конечно, но всё равно.
Запускать bc со сторонними библиотеками следует так:

carrot@ubuntu:~$ bc rand.bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
>rand(96)
21



Фрактал Мандельброта, рассчитанный в bc и сохраненный в ppm.

Четвертый кю (синий пояс)


Синтаксис bc очень похож на синтаксис Си. Поэтому можно смело использовать команды if, for, while, break, continue, return и расставлять фигурные скобки где ни попадя. Только после команд не нужно ставить точек с запятой, для вывода на экран использовать команду print, а для ввода — read. Функции определять командой define. Смотрите:
>define func () {
>for (i=0;i<10;i++) {
>a=a+i
>print a, «\n»
>}
>return 1}
>t=func ()
0
1
3
6
10
15
21
28
36
45
>print t
1

Третий кю (коричневый пояс)


В bc, к сожалению, нельзя работать с файловым вводом-выводом. Весь ввод через read, весь вывод через print. Еще в bc нельзя работать со строковыми переменными. Хотя, постойте! Можно использовать 36-ричную систему счисления, или же работать с массивами чисел как со строками.

Кроме того, в bc команда print не поддерживает полный набор escape-последовательностей.
The special characters recognized by bc are "a" (alert or bell), "b" (backspace), "f" (form feed), "n" (newline), "r" (carriage return), "q" (double quote), "t" (tab), and "\e" (backslash). Any other character following the backslash will be ignored. 


Когда я узнала об этом печальном ограничении, я подумала, что меня ждет розовая птица обломинго, ведь для любой серьезной игрушки нужно точное позиционирование курсора, и желательно использование различных цветов. Однако, я взяла hex-редактор в руки и обошла ограничение следующим образом: вставила символ с кодом 1Bh (escape) в качестве аргумента команды print, и затем пользовалась всеми радостями Escape-последовательностей.

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

И, наконец, самый унылый факт: в bc есть только один способ отлавливать нажатия клавиш — read. И он совершенно не подходит для интерактивных игр. А жаль, потому что на моём компьютере алгоритм рейкастинга, запущенный в bc, работает раз в десять быстрее, чем тот же алгоритм в bash, и выдает около 30-40 кадров в секунду.

Второй кю (всё еще коричневый пояс)


Теперь можно написать простой пасьянс на bc. Я выбрала пасьянс «Турецкий платок». Скачиваем архив с исходными кодами, распаковываем, запускаем так:
bc rand.bc printcard.bc

После запуска нужно ввести seed — начальное значение генератора случайных чисел. После этого вы увидите перетасованную колоду карт, разложенную в десять столбцов. Вводите номера столбцов, и если последние карты столбцов имеют одинаковую картинку (например, двойка треф и двойка бубен), то они будут убраны. Как только все карты удастся разобрать, программа поздравит вас с победой и завершит bc. Если вы решили, что стоит прекратить распутывать платок, нажмите Ctrl+C дважды, и затем Enter.

Первый дан (черный пояс)


А не будет информации про него. Почему? Потому что я еще не чувствую себя мастером...

P.S. Ссылка на пасьянс ещё раз, специально для тех, кто всегда сначала скачивает все файлы, а потом читает статью: narod.ru/disk/31656937001/platok.tar.html
Share post

Similar posts

Comments 27

    +9
    Аж икнулось от неожиданности. bash, cmd и прочее еще удивляют, но дают эффекта WOW.
    Но BC — это что-то. Респект и уважуха!

    PS. Ушел читать маны по bc. Могу больше не вернуться…
      0
      *но не дают эффекта…
        0
        Для меня, к примеру, такой распространенный и полезный инструмент как sed пока что тёмный лес. А на нем даже тетрис есть. В общем, нет предела для совершенства. А bc несложный, manpage к нему куда короче, чем к bash.
          +3
          В общем, нет предела для совершенства ивзращенства.
          На ум приходит банальнейшая фраза — эффектно, но не эффективно. Но в любом случае признаю, получилось так же эффектно, как это умеют делать Месси или Роналду.
            0
            Если вы про bc, то я бы не говорил, что это неэффективный инструмент. На однопроцессорных системах он может утереть нос всяким там маткадам по скорости работы, при этом есть почти на любой linux-системе. Можно попробовать перекомпилировать bc с помощью icc для увеличения скорости работы на многопроцессорных/многоядерных системах, кстати.
              0
              У нас для такого обычно используется «изврат, но прикольно»:)
                +1
                Картинку с троллейбусом забыли.
                +1
                Не расстраивайтесь. sed для многих тёмный лес. Да и документация к нему, мягко выражаясь, оставляет желать лучше. При копании вглубь, по крайней мере у меня, вопросов возникает гораздо больше, нежели ответов.
                  +2
                  По седу лучше читать не маны а учебники, написанные людьми для людей.

                  Я начинал с этого: www.grymoire.com/Unix/Sed.html
                  С юморком иногда даже. :)
              0
              Гм… Вау…
                +5
                Ненормальное программирование?
                  0
                  Немножко.
                  +4
                  Писать морской бой на Bash это ещё куда не шло. Но пасьянс на калькуляторе… Мир сошёл с ума.
                    +3
                    А когда-то игры на калькуляторах ограничивались чем-то вроде «посадки на луну» :-D
                      0
                      Ну нет, были даже РПГшки. Например, «Страна монстров». Калькулятор (железка) — это такая микроЭВМ, так что всё нормально.
                        +3
                        Мне кажется вся проблема была в семисегментном индикаторе калькулятора…
                          +1
                          Некоторые ограничения семисегментники накладывают. Но это не проблема для людей с хорошим воображением. Уж не помню, какой именно был алгоритм у программы, которую я писал, но я точно помню, что я играл в шахматы со своей же программой для программируемого калькулятора.
                        +5
                        слово ЕГГОГология напомнило о тех временах :)
                        +2
                        Статья отличная.
                        Подача материала шикарна, спасибо. Напомнило тетрис на awk/sed :)
                        Автор молодец.
                          +2
                          Спасибо. Наверное, нужно было побольше рассказать про команды специально для тех, кто не в курсе… Как думаете?
                            +1
                            imho всё супер. Кому надо — тот заинтересуется.
                            Ну разве что нюансы, на которые затратили много времени, и которые неявно описаны в манах.
                              0
                              Самые подлые подлянки в двух словах описал уже. Значит, переживать не о чем?
                          +1
                          Как же он без тангенса-то?
                            +1
                            Наверное, ожидается, что каждый, способный пользоваться bc способен сделать
                            define t(x) { return s(x) / c(x) }
                            +1
                            я думал после тетриса на sed+bash меня будет сложно удивить подобным, ан нет)
                              +1
                              В качестве 10ки можно использовать букву «T». Широко распространенно в обозначение карт. Аккуратней выглядит.
                                0
                                Спасибо, хорошая мысль.

                              Only users with full accounts can post comments. Log in, please.