Какие общие советы у вас есть для игры в гольф в DC ?
dc - это утилита калькулятора для UNIX / Linux, предшествующая языку C. Меня интересует, как сделать мои программы постоянного тока (вычисления?) Короче. Я ищу идеи, которые могут быть применены к общему коду-гольфу , которые, по крайней мере, немного специфичны для постоянного тока (например, удаление комментариев не является полезным ответом)
Пожалуйста, оставьте один совет за ответ.
Ответы:
Заявления if-then-else
Предположим, мы хотим проверить условие
редактировать:a==b
(пустьa
иb
хранятся в их соответственно именованных регистрах).Позвольте
(foo)
быть заполнителем, с целью уплотнения:Уверен, что это наиболее компактный оператор из возможных (также показанный здесь ).
источник
[[thenaction]P][[elseaction]P][r]sI 2 4 =I x sI f
, это начало? Действия для tehn и прочего находятся в стеке,I
макрос « f» меняет их и вызывается условно. тогда вершина стека будет выполнена, и неиспользуемый макрос будет сброшен в I для очистки стека.2 4
это просто пример данных для сравнения. В качестве альтернативы[x]sI
часть может быть перемещен в сравнении, если рассматривать более читаемым:[[thenaction]P][[elseaction]P] 4 4 [r]sI =I x sI f
. Вf
примерах просто будет показано, что стек чист после ...dc
и это было первая страница , где я видел OpenBSDdc
«sif-then-else
конструкции. Я думаю, что нам нуженdc
комплект вентиляторов со всеми 3 вариантами для всех основных операционных систем ... o :-) ... и моеif-then-else
предложение выше не работает на оригинале,dc
потому что в нем отсутствуетr
команда ... :-([[(if)2Q]si(condition)i(else)]x
- обернуть все это в макрос и часть if внутри другого макроса внутри него, чтобы вы могли2Q
выйти из всего этого, прежде чем достигнуть else-части. Так что, если вы хотите сделать, если 1 == 1, то выведите 1, иначе выведите 2 , это было бы1[[1P2Q]si1=i2P]x
(не проверено, поскольку у меня нет доступа к dc прямо здесь и сейчас. Также я был уверен, что делал этот трюк в ответе здесь раньше но не смог его найти)[/*else*/]sE[[/*then*/]sE]sIlalb=IlEx
против[[/*then*/2Q]sIlalb=I/*else*/]x
разницы в 6 байтов.Вы можете сохранить ввод с
d
Используя
d
, который дублирует ToS (верхнюю часть стека), вы можете убрать ввод с пути для дальнейшего использования, при этом все еще имея возможность использовать его.источник
Массивы
Хотя они являются головной болью для начинающих,
dc
предлагает массивы. Они работают так:Как обычно, первый элемент имеет индекс 0. Массивы могут быть полезны при работе с последовательностями, как в последовательности SUDSI , особенно в сочетании со счетчиками. Массивы могут уменьшить количество перестановок чисел, которое вам нужно сделать (и количество счетчиков и сравнений), если вы хотите выбрать определенный элемент, не разрушая вашу среду. Например, если вы хотите переместить стопку чисел в массив, вы можете написать рекурсивную функцию, которая использует
z
(глубину стека) илиz 1-
в качестве индекса, хранит элемент и проверяет,z == 0
завершить ли себя.Помните о следующем:
dc
потерпит крахисточник
dc
возможно, был недавно обновлен, и поведение массива могло немного измениться в связи с падением. Пока не могу подтвердить, но я думаю, что в прошлый раз, когда я использовал это в Linux, что-то было не так0-й степени вместо условных / макросов
Иногда вам может понадобиться что - то вроде с троичной условно:
Хороший способ справиться с этим описан в ответе @ Joe . Однако мы можем сделать лучше:
где E - D - C.
Это проверяет равенство, возводя 0 в степень разности двух значений. Это приводит к 1, если равно и 0 в противном случае. Остальные просто масштабируют 1 или 0 до значений C или D. Это работает, потому что
dc
дает 0 0 = 1 и 0 n = 0 для n! = 1.источник
Иногда необходимо сбросить число из стека. Один из способов сделать это просто вытолкнуть его в неиспользуемый переменную, то есть
st
. Однако в некоторых ситуациях вы можете вставить его в несколько других мест, например, во входную базу, когда у вас больше нет числового ввода, или в спецификатор точности, если у вас нет больше операций, которые могут помочь, если точность будет иметь значение. В первом случае используйтеi
. В последнем случае используйтеk
.источник
o
его тоже можно использовать. И если какие-либо из этих вещей не важны, они могут использоваться в качестве хранилища, а также просто отбрасывать ихI
/K
/O
вызывать их соответственно и сохранять байты сверхsa
/la
и т.д. Допустимые значения AFAIK:i
2-16;k
любое неотрицательное целое число;o
любое целое число больше 1.Длина расчета:
Z
,X
, иz
Z
выскакивает ToS и выталкивает количество цифр (десятичное), если это число, или количество символов, если это строка. Это может быть полезно для определения длины результата (для буферизации вывода) или вычисления длины строки. Обратите внимание, что для чиселZ
толкает объединенную длину целочисленной части и дробной части.X
выскакивает ToS и толкает количество цифр в дробной части числа. Если ToS был строкой,0
он выдвигается.Чтобы найти количество цифр в целой части числа, можно использовать
dZrX-
. Если вы не изменили точность по умолчаниюk==0
, используется1/Z
короче, но предположим, что вам нужно поддерживать определенную ненулевую точность после операции:Kr0k1/Zrk
это скорее бельмо на глазу.z
толкает количество предметов в стеке. Одна из моих любимых команд, она не выдает никаких значений! Это может быть использовано для генерации последовательности чисел или увеличения счетчика.zd
Повторное использование (скажем, в начале макроса) может позволить протестировать вычисления для каждого натурального или целого числа в порядке возрастания.источник
z
для этого и того раньше, но мне никогда не приходило в голову использовать это как хак для счетчика ... Отлично ...Digits
A
наF
может быть использованы в качестве замены для чисел от 10 до 15. Однако они еще должны быть обработаны эффективно , как основание 10 цифр (предполагается , что входная база 10) , когда в разных местах. Другими словами, при вводе база 10FF
не будет представлять 255, она будет представлять(15 * 10) + 15
или 165.На самом деле это работает для всех цифр ,
0
чтобыF
в любом входной базы2
в16
. Так что, если база ввода 5, то26E
будет(2 * 5^2) + (6 * 5) + 14
или 94.Обратите внимание, что это поведение действует для неизмененных источников GNU. Однако, как указывает @SophiaLechner, в дистрибутивах RedHat, по-видимому, используется bc-1.06-dc_ibase.patch, который меняет это поведение, поэтому цифры> = ibase обрабатываются как
ibase - 1
, независимо от их фактического значения. Обратите внимание, что TIO,dc
похоже, не имеет bc-1.06-dc_ibase.patch (хотя его Fedora 28 ¯_ (ツ) _ / ¯).источник
FF
представляет собой99
, на входе базу 526E
такая же, как244
, например, база 1074
.dc
версию вы используете? Я использую GNU DC 1.4.1 на Ubuntu и GNU DC 1,3 на MacOSFFp
выходы99
в 1.3.95. Не могли бы вы проверить это в своей версии MacOS?При инициализации в
функциимакро (мы будем использоватьF
) , который вы хотите запустить сразу же, использовать что - то вроде ,dsFx
а неsFlFx
. То же самое работает для переменных:dsa
вместоsala
.Если вам нужно сделать что-то другое между хранением и загрузкой (например,
sa[other stuff]la
), все равно подумайте, действительно ли вышеприведенное является жизнеспособным: если вы оставите значение в стеке перед другими операциями, оно вернется к началу к концу из этих операций?источник
Просто обнаружил это случайно. Еще один способ сгенерировать ноль:
_
._
является сигналом для постоянного тока о том, что следующие цифры являются отрицательным числом. Пример:Но что, если мы не будем следовать за ним с номером?
Это работает, когда следующий непустой символ, следующий за подчеркиванием, не является цифрой. Если за ним следует цифра, даже после новой строки, она интерпретируется как отрицательный знак.
источник
Если содержимое всего стека необходимо распечатать в конце программы, для этого можно использовать рекурсивный макрос-цикл. Однако гораздо проще просто использовать
f
команду.источник
dc
читает ввод строки за раз. Если вам нужно прочитать несколько элементов, то для этого нужно выполнить по одной на строку, либо?
для каждой строки нужно прочитать, либо громоздкий макрос-цикл. Вместо этого, если все элементы ввода могут быть помещены в одну строку, разделенную пробелом, то?
будет считывать все входные элементы, помещая каждый из них в стек.К примеру , в
seq 10 | dc -e'?f'
,seq
выводит целые числа 1-10, по одному в строке.?
будет только читать первый ,1
который будет выводиться , когдаf
сбрасывает весь стек. Однако вseq 10 | tr '\n' ' ' | dc -e'?f'
,tr
делает входные целые все разделенные пробелом. В этом случае он за один раз?
прочитает все целые числа из строки иf
выведет их все.источник
Если оператор ограничен от источника, создайте новый с
a
Что-то, что пригодилось мне пару раз, теперь состоит в том, чтобы избегать использования определенного оператора, выдвигая значение ASCII оператора, используя его
a
для преобразования его в строку, иs
записывая его в регистр для последующего выполнения в качестве макроса на. Например, мне нужно сделать разделение, но я либо запрещен, либо стараюсь избегать использования персонажа/
. Я могу вместо этого сделать,47asd
а затем в будущем, когда мне нужно разделить 16 на 416 4 ldx
,.s
которым нужно что-то постфиксировать.источник
Как избежать пробелов
Как избежать пробелов, возникает немало проблем, и, как правило, это легко
dc
. Помимо строк, один очень специфический момент, когда пробел становится необходимым, - это нажатие нескольких чисел в строке:1 2 3
. Если этого следует избегать:1[]x2[]x3[]x
.35asn
и выполнить его между ними:1lnx2lnx3lnx
.источник
dc: ',' (054) unimplemented
предупреждениями.