¿Qué consejos generales tienes para jugar al golf en DC ?
dc es una utilidad de calculadora para UNIX / Linux que es anterior al lenguaje C. Estoy interesado en cómo acortar mis programas de CC (¿cálculos?). Estoy buscando ideas que se puedan aplicar al código general de golf que sean al menos un poco específicas de DC (por ejemplo, eliminar comentarios no es una respuesta útil)
Por favor, publique un consejo por respuesta.

Respuestas:
Declaraciones If-then-else
Supongamos que queremos verificar la condición
editar:a==b(letaybse almacenará en sus registros nombrados respectivamente).Dejar
(foo)ser un marcador de posición, con el fin de condensar:Estoy bastante seguro de que esta es la declaración más compacta posible (también presentada aquí ).
fuente
[[thenaction]P][[elseaction]P][r]sI 2 4 =I x sI fes un comienzo? Las acciones para tehn y más están en la pila, laImacro " f" las intercambia y se llama condicionalmente. entonces se ejecutará la parte superior de la pila y la macro no utilizada se soltará en I para limpiar la pila.2 4son solo los datos de ejemplo para comparar. Como alternativa, la[x]sIparte se puede mover a la comparación, si se considera más fácil de leer:[[thenaction]P][[elseaction]P] 4 4 [r]sI =I x sI f. Enflos ejemplos solo se mostrará que la pila está limpia después ...dcy esa fue la primera página donde vidclaif-then-elseconstrucción de OpenBSD . Creo que necesitamos undcpaquete de ventiladores con los 3 sabores para todos los principales sistemas operativos ... o :-) ... y miif-then-elsepropuesta anterior no funciona en el originaldcporque carece delrcomando ... :-([[(if)2Q]si(condition)i(else)]x- envolver todo en una macro, y la porción if dentro de otra macro dentro de eso, para que pueda2Qsalir de todo antes de llegar a la porción else. Entonces, si desea hacer si 1 == 1, imprima 1 más imprima 2 , sería1[[1P2Q]si1=i2P]x(no probado ya que no tengo acceso a CC aquí y ahora. También estaba seguro de que había hecho este truco en una respuesta aquí antes pero no pudo encontrarlo)[/*else*/]sE[[/*then*/]sE]sIlalb=IlExvs[[/*then*/2Q]sIlalb=I/*else*/]x- 6 bytes de diferencia. Aún no probado: PPuede guardar la entrada con
dAl usar
d, que duplica el ToS (parte superior de la pila), puede mover la entrada fuera del camino para su uso posterior, sin dejar de poder usarlo.fuente
Matrices
Aunque son un dolor de cabeza para los principiantes,
dcofrece matrices. Funcionan así:Como de costumbre, el primer elemento tiene el índice 0. Las matrices pueden ser útiles cuando se trabaja con secuencias, como en la secuencia SUDSI , especialmente en combinación con contadores. Las matrices pueden reducir la cantidad de combinación de números que debe hacer (y la cantidad de contadores y comparaciones) si desea seleccionar un elemento en particular sin destruir su entorno. Por ejemplo, si desea mover una pila de números a una matriz, puede escribir una función recursiva que utilice
z(profundidad de la pila) oz 1-como índice, almacene el elemento y compruebe si sez == 0termina.Tenga en cuenta lo siguiente:
dcse estrellaráfuente
dcpuede haber sido actualizado recientemente, y el comportamiento de la matriz puede haber cambiado ligeramente con respecto al bloqueo. No puedo confirmar tampoco en este momento, pero creo que algo fue diferente la última vez que lo usé en Linux.0 a la enésima potencia en lugar de condicionales / macros
A veces puede que tenga algo como c ternaria condicional:
Una buena manera de manejar esto se describe en la respuesta de @ Joe . Sin embargo, podemos hacerlo mejor:
donde E es D - C.
Esto prueba la igualdad elevando 0 a la potencia de la diferencia de los dos valores. Esto da como resultado 1 si es igual y 0 en caso contrario. El resto simplemente escala el 1 o 0 a los valores C o D. Esto funciona porque
dcda 0 0 = 1 y 0 n = 0 para n! = 1.fuente
A veces es necesario descartar un número de la pila. Una forma de hacerlo es simplemente introducirlo en una variable no utilizada, es decir
st. Sin embargo, en algunas situaciones, puede abrirlo en un par de otros lugares, por ejemplo, la base de entrada cuando no tenga más entrada numérica o al especificador de precisión si no tiene más operaciones que hacer donde la precisión marcaría la diferencia. En el primer caso, usei. En el último caso, usek.fuente
ose puede usar. Y si alguna de estas cosas no es importante, se pueden usar como almacenamiento y como simple descarte -I/K/Orecuperarlos respectivamente, y guardar bytes sobresa/laetc. Valores válidos AFAIK:i2-16;kcualquier número entero no negativo;ocualquier número entero mayor que 1.Cálculo de longitud:
Z,XyzZabre el ToS y empuja el número de dígitos (decimal) si es un número o el número de caracteres si es una cadena. Esto puede ser útil para detectar la longitud de un resultado (para la memoria intermedia) o calcular la longitud de la cadena. Tenga en cuenta que para los números,Zempuja la longitud combinada de la parte entera y la parte fracción.Xabre el ToS y empuja el número de dígitos en la parte fraccionaria del número. Si el ToS era una cadena,0se empuja.Para encontrar el número de dígitos en la parte entera del número, uno podría usar
dZrX-. Si no ha cambiado la precisión por defectok==0, el uso1/Zes más corto, pero suponga que necesita mantener una precisión particular distinta de cero después de la operación:Kr0k1/Zrkes más bien una monstruosidad.zempuja el número de artículos en la pila. ¡Uno de mis comandos favoritos, en realidad no muestra ningún valor! Podría usarse para generar una secuencia de números o incrementar un contador. El usozdrepetido (digamos, al comienzo de una macro) podría permitir probar un cálculo en cada número natural o entero en orden ascendente.fuente
zesto y aquello antes, pero nunca se me ocurrió usarlo como un truco de un mostrador ... Excelente ...Los dígitos
AaFse pueden usar en sustitución de los números del 10 al 15. Sin embargo, aún deben tratarse eficazmente como dígitos de base 10 (suponiendo que la base de entrada sea 10) cuando se encuentran en diferentes lugares. En otras palabras, con la base de entrada 10FFno representaría 255, representaría(15 * 10) + 15o 165.De hecho esto funciona para todos los dígitos
0queFen cualquier base de entrada2a16. Entonces, si la base de entrada es 5, entonces26Esería(2 * 5^2) + (6 * 5) + 14, o 94.Tenga en cuenta que este comportamiento está vigente para las fuentes GNU no modificadas. Sin embargo, como señala @SophiaLechner, las distribuciones basadas en RedHat parecen usar bc-1.06-dc_ibase.patch que cambia este comportamiento para que los dígitos> = ibase se traten como
ibase - 1, independientemente de su valor real. Tenga en cuenta que el TIOdcparece no tener bc-1.06-dc_ibase.patch (a pesar de que es Fedora 28 ¯_ (ツ) _ / ¯).fuente
FFrepresenta99, en la base de entrada 526Ees lo mismo que244, es decir, la base 1074.dcversión está ejecutando? Estoy usando GNU dc 1.4.1 en ubuntu y GNU dc 1.3 en MacOSFFpsalidas99en 1.3.95. ¿Podrías comprobar esto en tu versión de MacOS, entonces?Al inicializar una macro de
función(usaremosF) que desea ejecutar de inmediato, use algo así como endsFxlugar desFlFx. Lo mismo funciona para las variables: endsalugar desala.Si necesita hacer otras cosas entre el almacenamiento y la carga (por ejemplo,
sa[other stuff]la), considere si lo anterior es viable: si deja un valor en la pila antes de las otras operaciones, ¿volverá a estar en la parte superior al final? de esas operaciones?fuente
Acabo de descubrir esto por accidente. Sin embargo, otra manera de generar un cero:
_._es una señal a dc de que los siguientes dígitos son un número negativo. Ejemplo:Pero, ¿y si no lo seguimos con un número?
Esto funciona cuando el siguiente carácter no en blanco después del guión bajo no es un dígito. Si un dígito lo sigue, incluso después de una nueva línea, se interpreta como un signo negativo.
fuente
Si el contenido de toda la pila necesita imprimirse al final de un programa, se podría utilizar un bucle macro recursivo para lograr esto. Sin embargo, es mucho más corto simplemente usar el
fcomando.fuente
dclee la entrada de una línea a la vez. Si necesita leer en varios elementos, hacerlo uno por línea requiere un?para cada línea para leer, o un engorroso macro loop. En cambio, si todos los elementos de entrada pueden colocarse en una línea separada por espacios, entonces un solo?leerá todos los elementos de entrada, empujando cada uno a la pila.Por ejemplo en
seq 10 | dc -e'?f',seqsalidas enteros 1-10, uno por línea. el?solo leerá el primero1que saldrá cuando sefdescargue toda la pila. Sin embargoseq 10 | tr '\n' ' ' | dc -e'?f', entrhace que la entrada integre todo el espacio separado. En este caso?, leerá todos los enteros de la línea de una vez y losfgenerará todos.fuente
Si un operador está restringido desde la fuente, cree uno nuevo con
aAlgo que me ha resultado útil un par de veces ahora es evitar usar un operador específico presionando el valor ASCII del operador, usarlo
apara convertirlo en una cadena ystorsionarlo en un registro para ejecutarlo como macro más adelante en. Por ejemplo, necesito hacer una división, pero no puedo o intento evitar usar el personaje/. Puedo, en cambio, hacerlo47asdy luego en el futuro cuando necesito dividir 16 por 416 4 ldx,.sese que deben ser fijados por algo.fuente
Evitar espacios en blanco
Evitar el espacio en blanco surge en bastantes desafíos, y generalmente es fácil
dc. Aparte de las cadenas, la única vez muy específico que hace necesario un espacio en blanco es al empujar varios números en una fila:1 2 3. Si esto debe evitarse:1[]x2[]x3[]x.35asny ejecutar que en el medio:1lnx2lnx3lnx.fuente
dc: ',' (054) unimplementedadvertencias.