Quels conseils généraux avez-vous pour jouer au golf en DC ?
dc est un utilitaire de calculatrice pour UNIX / Linux qui est antérieur au langage C. Je souhaite savoir comment raccourcir mes programmes DC (calculs?). Je cherche des idées qui peuvent être appliquées au code-golf général qui sont au moins un peu spécifiques au DC (par exemple, supprimer des commentaires n'est pas une réponse utile)
Veuillez poster un pourboire par réponse.
Réponses:
Instructions if-then-else
Supposons que nous voulons vérifier la condition
Éditer:a==b
(laissera
etb
être stockés dans leurs registres respectivement nommés).Soit
(foo)
un espace réservé, dans le but de condenser:Je suis sûr que c'est la déclaration la plus compacte possible (également présentée ici ).
la source
[[thenaction]P][[elseaction]P][r]sI 2 4 =I x sI f
- être un début? Les actions pour tehn et autres sont sur la pile, laI
macro " f" les échange et est appelée conditionnellement. alors le haut de la pile sera exécuté et la macro inutilisée sera déposée dans I pour nettoyer la pile.2 4
ne sont que des exemples de données à comparer. En variante , la[x]sI
partie peut être déplacée à la comparaison, si cela est jugé plus lisible:[[thenaction]P][[elseaction]P] 4 4 [r]sI =I x sI f
. Lef
dans les exemples montrera juste que la pile est propre après ...dc
et c'était la 1ère page où j'ai vudc
laif-then-else
construction d' OpenBSD . Je pense que nous avons besoin d'undc
ensemble de fans avec les 3 versions pour tous les principaux systèmes d'exploitation ... o :-) ... et maif-then-else
proposition ci-dessus ne fonctionne pas sur l'originaldc
car il manque lar
commande ... :-([[(if)2Q]si(condition)i(else)]x
- envelopper le tout dans une macro, et la partie if à l'intérieur d'une autre macro à l'intérieur, afin que vous puissiez vous2Q
éloigner du tout avant d'atteindre la partie else. Donc, si vous voulez faire si 1 == 1 puis imprimer 1 sinon imprimer 2 , ce serait1[[1P2Q]si1=i2P]x
(non testé car je n'ai pas accès à dc ici et maintenant. J'étais également sûr d'avoir fait cette astuce dans une réponse ici avant mais je[/*else*/]sE[[/*then*/]sE]sIlalb=IlEx
vs[[/*then*/2Q]sIlalb=I/*else*/]x
- 6 octets. Tho encore non testé: PVous pouvez enregistrer une entrée avec
d
En utilisant
d
, qui duplique le ToS (haut de la pile), vous pouvez déplacer l'entrée pour une utilisation ultérieure, tout en étant capable de l'utiliser.la source
Tableaux
Bien qu'ils soient un casse-tête pour les débutants,
dc
propose des tableaux. Ils fonctionnent comme ceci:Comme d'habitude, le premier élément a l'index 0. Les tableaux peuvent être utiles lorsque vous travaillez avec des séquences, comme dans la séquence SUDSI , en particulier en combinaison avec des compteurs. Les tableaux peuvent réduire la quantité de mélange de nombres que vous devez faire (et le nombre de compteurs et de comparaisons) si vous souhaitez sélectionner un élément particulier sans détruire votre environnement. Par exemple, si vous souhaitez déplacer une pile de nombres dans un tableau, vous pouvez écrire une fonction récursive qui utilise
z
(profondeur de pile) ouz 1-
comme index, stocke l'élément et vérifie s'ilz == 0
doit se terminer lui-même.Soyez conscient des points suivants:
dc
va planter.la source
dc
peut avoir été mis à jour récemment et le comportement du tableau peut avoir légèrement changé en ce qui concerne le plantage. Je ne peux pas confirmer non plus pour le moment, mais je pense que quelque chose était différent la dernière fois que je l'ai utilisé sur Linux.0 à la nième puissance au lieu des conditions / macros
Parfois, vous pourriez avoir besoin de quelque chose comme conditionnel c ternaire:
Une bonne façon de gérer cela est décrite dans la réponse de @ Joe . Mais nous pouvons faire mieux:
où E est D - C.
Cela teste l'égalité en élevant 0 à la puissance de la différence des deux valeurs. Il en résulte 1 si égal et 0 sinon. Le reste met simplement le 1 ou 0 à l'échelle des valeurs C ou D. Cela fonctionne car
dc
donne 0 0 = 1 et 0 n = 0 pour n! = 1.la source
Parfois, il est nécessaire de jeter un numéro de la pile. Une façon de le faire est de simplement l'insérer dans une variable inutilisée, c'est-à-dire
st
. Cependant, dans certaines situations, vous pouvez l'afficher à quelques autres endroits, par exemple la base d'entrée lorsque vous n'avez plus d'entrée numérique ou le spécificateur de précision si vous n'avez plus d'opérations à faire là où la précision ferait une différence. Dans le premier cas, utilisezi
. Dans ce dernier cas, utilisezk
.la source
o
peut également être utilisée. Et si certaines de ces choses sont sans importance, elles peuvent être utilisées comme stockage ainsi que comme simple suppression -I
/K
/O
rappelez-les respectivement, et enregistrez des octets sursa
/la
etc. Valeurs valides AFAIK:i
2-16;k
tout entier non négatif;o
tout entier supérieur à 1.Calcul de la longueur:
Z
,X
etz
Z
ouvre le ToS et pousse le nombre de chiffres (décimal) s'il s'agit d'un nombre ou le nombre de caractères s'il s'agit d'une chaîne. Cela peut être utile pour détecter la longueur d'un résultat (pour la mise en mémoire tampon de la sortie) ou calculer la longueur d'une chaîne. Notez que pour les nombres,Z
pousse la longueur combinée de la partie entière et de la partie fraction.X
ouvre le ToS et pousse le nombre de chiffres dans la partie fraction du nombre. Si le ToS était une chaîne,0
est poussé.Pour trouver le nombre de chiffres dans la partie entière du nombre, on peut utiliser
dZrX-
. Si vous n'avez pas changé la précision de la valeur par défautk==0
, l'utilisation1/Z
est plus courte, mais supposez que vous devez conserver une précision non nulle particulière après l'opération:Kr0k1/Zrk
c'est plutôt une horreur.z
pousse le nombre d'éléments sur la pile. Une de mes commandes préférées, elle ne fait apparaître aucune valeur! Il pourrait être utilisé pour générer une séquence de nombres ou incrémenter un compteur. L'utilisationzd
répétée (par exemple, au début d'une macro) pourrait permettre de tester un calcul sur chaque nombre naturel ou entier dans l'ordre croissant.la source
z
pour ceci et cela auparavant, mais je n'ai jamaisLes chiffres
A
àF
peuvent être utilisés en remplacement des numéros 10 à 15. Cependant, ils doivent toujours être traités efficacement comme des chiffres de base 10 (en supposant que la base d'entrée est 10) lorsqu'ils sont à des endroits différents. En d'autres termes, avec une base d'entrée 10FF
ne représenterait pas 255, cela représenterait(15 * 10) + 15
ou 165.En fait cela fonctionne pour tous les chiffres
0
àF
dans une base d'entrée2
à16
. Donc, si la base d'entrée est 5, ce26E
serait soit(2 * 5^2) + (6 * 5) + 14
94.Notez que ce comportement est en vigueur pour les sources GNU non modifiées. Cependant, comme le souligne @SophiaLechner, les distributions basées sur RedHat semblent utiliser bc-1.06-dc_ibase.patch qui modifie ce comportement afin que les chiffres> = ibase soient traités comme
ibase - 1
, quelle que soit leur valeur réelle. Notez que le TIOdc
ne semble pas avoir bc-1.06-dc_ibase.patch (même si son Fedora 28 ¯_ (ツ) _ / ¯).la source
FF
représente99
, dans la base d'entrée 526E
est le même que244
, c'est-à-dire la base 1074
.dc
version utilisez-vous? J'utilise GNU dc 1.4.1 sur ubuntu et GNU dc 1.3 sur MacOSFFp
sorties99
en 1.3.95. Pourriez-vous vérifier cela dans votre version MacOS, alors?Lors de l'initialisation d'une macro de
fonction(que nous utiliseronsF
) que vous souhaitez exécuter immédiatement, utilisez quelque chose commedsFx
plutôt quesFlFx
. La même chose fonctionne pour les variables:dsa
plutôt quesala
.Si vous devez faire d'autres choses entre le stockage et le chargement (par exemple,
sa[other stuff]la
), considérez toujours si ce qui précède est viable: si vous laissez une valeur sur la pile avant les autres opérations, sera-t-elle de retour en haut à la fin de ces opérations?la source
Je viens de découvrir cela par accident. Une autre façon de générer un zéro:
_
._
est un signal à cc que les chiffres suivants sont un nombre négatif. Exemple:Mais que se passe-t-il si nous ne le suivons pas avec un numéro?
Cela fonctionne lorsque le caractère non vide suivant le trait de soulignement n'est pas un chiffre. Si un chiffre le suit, même après une nouvelle ligne, il est interprété comme un signe négatif.
la source
Si le contenu de la pile entière doit être imprimé à la fin d'un programme, une boucle macro récursive peut être utilisée pour y parvenir. Cependant, il est beaucoup plus court d'utiliser simplement la
f
commande.la source
dc
lit l'entrée une ligne à la fois. Si vous avez besoin de lire plusieurs éléments, le faire une ligne par ligne nécessite soit une?
lecture pour chaque ligne, soit une boucle de macro encombrante. Au lieu de cela, si tous les éléments d'entrée peuvent être placés sur une ligne séparée par des espaces, un seul?
lira tous les éléments d'entrée, les poussant chacun sur la pile.Par exemple, dans
seq 10 | dc -e'?f'
,seq
génère des nombres entiers de 1 à 10, un par ligne. le?
lira juste le premier1
qui sera sorti lors duf
vidage de la pile entière. Cependant, dansseq 10 | tr '\n' ' ' | dc -e'?f'
, lestr
entiers d'entrée sont séparés par un espace. Dans ce cas, le?
lira tous les entiers de la ligne en une seule fois etf
les affichera tous.la source
Si un opérateur est restreint depuis la source, créez-en un nouveau avec
a
Quelque chose qui m'a été utile à quelques reprises maintenant est d'éviter d'utiliser un opérateur spécifique en poussant la valeur ASCII de l'opérateur, en la
a
convertissant en chaîne et en las
stockant dans un registre à exécuter plus tard en tant que macro sur. Par exemple, je dois faire la division, mais je suis soit interdit, soit j'essaie d'éviter d'utiliser le personnage/
. Je peux, au lieu de cela47asd
, puis à l'avenir, lorsque je devrai diviser 16 par 416 4 ldx
,.s
celle-ci qui doivent être postfixées par quelque chose.la source
Éviter les espaces blancs
Éviter les espaces blancs pose de nombreux défis et est généralement facile à utiliser
dc
. En plus de chaînes, une fois très précis que les espaces devient nécessaire est en poussant plusieurs numéros dans une rangée:1 2 3
. Si cela doit être évité:1[]x2[]x3[]x
.35asn
et exécuter ce entre:1lnx2lnx3lnx
.la source
dc: ',' (054) unimplemented
avertissements.