CJam es un lenguaje de golf basado en pila inspirado en GolfScript, creado por el aditsu de usuario PPCG .
Entonces, en la línea de otras preguntas de consejos específicos del idioma:
¿Qué consejos generales tienes para jugar al golf en CJam? Por favor, publique un consejo por respuesta.
Respuestas:
Módulo correcto para números negativos
A menudo es molesto que el resultado de la operación de módulo dé el mismo signo que el primer operando. Por ejemplo,
-5 3%
da en-2
lugar de1
. La mayoría de las veces quieres lo último. La solución ingenua es aplicar el módulo, agregar el divisor una vez y aplicar el módulo nuevamente:Pero eso es largo y feo. En lugar de ello, podemos utilizar el hecho de que la indexación de matrices siempre es modular y hace el trabajo correctamente con índices negativos. Así que simplemente convertimos el divisor en un rango y accedemos a eso:
Aplicado a
-5
, esto da1
como se esperaba. ¡Y es solo un byte más largo que el incorporado%
!Si el módulo es una potencia de 2, puede guardar otro byte usando arihmética bit a bit (que también es mucho más rápido). Comparar:
Para el caso especial de
65536 == 2^16
otro byte se puede guardar haciendo uso del comportamiento de ajuste del tipo de carácter:fuente
Empujar rangos de caracteres concatenados
La cadena que contiene todos los dígitos
"0123456789"
se puede escribir comoLas letras mayúsculas ASCII (
A-Z
) se pueden empujar comoque genera la cadena de todos los caracteres hasta Z , luego descarta los primeros 65 (hasta @ ).
Todas las letras ASCII (
A-Za-z
) se pueden insertar comoque funciona como arriba, luego crea una copia, se convierte en minúsculas y se agrega.
¡Pero hay una forma más corta de hacerlo!
Luego, el
^
operador que a menudo se pasa por alto (diferencias simétricas para listas) permite crear los mismos rangos mientras se guardan tres bytes:'[,
crea el rango de todos los caracteres ASCII hasta Z ,_el
crea una copia en minúscula y^
mantiene solo los caracteres de ambas cadenas que aparecen en una pero no en ambas.Como todas las letras en la primera cadena son mayúsculas, todas en la segunda son minúsculas y todos los caracteres que no son letras están en ambas cadenas, el resultado en la cadena de letras.
El alfabeto RFC 1642 Base64 (
A-Za-z0-9+/
) se puede insertar utilizando la técnica anterior y agregando las no letras:Una forma igualmente corta de empujar esta cadena hace uso únicamente de diferencias simétricas:
¿Cómo podemos encontrar la cuerda al principio?
Todos los rangos de caracteres utilizados (
A-Z
,a-z
,0-9
,+
,/
) pueden ser empujados como la diferencia simétrica de a la gama que comienzan en el byte nulo, es decir'A,'[,^
,'a,'{,^
,'0,':,^
,'+,',,^
y'/,'0,^
.Por lo tanto, ejecutar
:,:^
on"A[a{):+,/0"
empujará los caracteres deseados, pero no en el orden correcto.¿Cómo encontramos el orden correcto? Fuerza bruta al rescate! El programa
itera sobre todas las permutaciones posibles de la cadena, aplica
:,:^
y compara el resultado con la salida deseada ( enlace permanente ).El alfabeto radix-64 utilizado, por ejemplo, por crypt (
.-9A-Za-z
) se puede generar utilizando el método anterior:Este es el método más corto que conozco.
Dado que todos los caracteres en la salida deseada están en orden ASCII, no es necesario iterar sobre permutaciones.
No todos los rangos de caracteres concatenados se pueden empujar en el orden deseado usando
:,:^
.Por ejemplo, el rango
0-9A-Za-z;-?
no se puede impulsar ejecutando:,:^
cualquier permutación de"0:A[a{;@"
.Sin embargo, podemos encontrar una variación rotada de la cadena deseada que puede, utilizando el código
que imprimirá ( enlace permanente ) lo siguiente:
Esto significa que
tiene el mismo efecto que
que solo se puede usar con una pila vacía sin anteponer a
[
.fuente
¿Evitar {...} {...}?
Suponga que tiene un número entero en la pila. Si es impar, desea multiplicarlo por 3 y agregar 1; de lo contrario, desea dividirlo por 2.
Una declaración if / else "normal" se vería así:
Sin embargo, el uso de bloques generalmente no es el camino a seguir, ya que
{}{}
ya agrega cuatro bytes.?
también se puede usar para seleccionar uno de los dos elementos en la pila:Este es un byte más corto.
Bloquear-? con una declaración if vacía siempre es un no-go. Por ejemplo,
es dos bytes más largo que
Si en cambio tienes
y lo que estás comprobando es un entero no negativo, puedes hacer
Los nuevos
{}&
y{}|
prácticos, pero a veces problemáticos si no puedes abarrotar la pila.Aún así, en el caso de
puedes usar una variable temporal en su lugar:
fuente
!)/
yg)/
son más cortos en los ejemplos.Cambiar declaraciones
CJam no tiene declaraciones de cambio. Anidadas si las declaraciones funcionan igual de bien, pero
{{}{}?}{}?
ya tiene 12 bytes de longitud ...Si podemos transformar la condición en un entero pequeño, no negativo, podemos transformar todas las declaraciones de caso en una cadena delimitada y evaluar el resultado correspondiente.
Por ejemplo, si queremos ejecutar
code0
si el número entero de la pila es 0 ,code1
si es 1 ycode2
si es 2 , podemos usaro
o
S/
divide la cadena en["code0" "code1" "code2"]
,=
extrae el fragmento correspondiente y~
evalúa el código.Haga clic aquí para ver las declaraciones de cambio en acción.
Finalmente, como lo sugieren @ jimmy23013 y @RetoKoradi, podemos acortar aún más el cambio en algunos casos. Say
code0
,code1
ycode2
tienen longitudes L 0 , L 1 y L 2 , respectivamente.Si L 0 = L 1 ≥ L 2
se puede usar en su lugar, donde
L
es L 0 . En lugar de dividirse en un delimitador,/
divide la cadena en trozos de igual longitud aquí.Si L 0 ≥ L 1 ≥ L 2 ≥ L 0 - 1 ,
se puede usar en su lugar.
>
elimina 0, 1 o 2 elementos del comienzo de la cadena y3%
extrae cada tercer elemento (comenzando por el primero).fuente
"code0code1code2"5/=~
? Me parece mucho más sencillo, y tiene la misma longitud.Golf común array y valores de cadena
Hay ciertas series o cadenas cortas que surgen de vez en cuando, por ejemplo, para inicializar las cuadrículas. Ingenuamente, estos pueden costar 4 o más bytes, por lo que vale la pena buscar operaciones con valores integrados que den el mismo resultado. Especialmente la conversión de bases suele ser útil.
[0 1]
se puede escribir como2,
.[1 0]
puede escribirse comoYYb
(es decir, 2 en binario).[1 1]
se puede escribir comoZYb
(es decir, 3 en binario).[[0 1] [1 0]]
se puede escribir como2e!
.[LL]
se puede escribir comoSS/
(dividiendo un solo espacio por espacios)."\"\""
se puede escribir comoL`
."{}"
se puede escribir como{}s
.Este último se puede extender a los casos en que desea que todos los tipos de paréntesis guarden otro byte:
"[{<()>}]"
se puede escribir como{<()>}a`
."()<>[]{}"
se puede escribir como{<()>}a`$
.Especialmente el truco de conversión de base puede ser útil para tener en cuenta para algunos casos oscuros que aparecen de vez en cuando. Por ejemplo
[3 2]
, seríaE4b
(14 en la base 4).En casos aún más raros, incluso puede encontrar
mf
útil el operador de factorización . Por ejemplo,[2 7]
esEmf
.Siéntase libre de ampliar esta lista si encuentra otros ejemplos.
fuente
Despejando la pila
Si solo desea borrar toda la pila, envuélvala en una matriz y revísela:
Lo que es un poco más complicado es, si has hecho muchos cálculos, pero solo quieres mantener el elemento de la pila superior y descartar todo lo que está debajo. El enfoque ingenuo sería almacenar el elemento superior en una variable, borrar la pila, empujar la variable. Pero hay una alternativa mucho más corta: envolver la pila en una matriz y extraer el último elemento:
(Gracias a Optimizer que me mostró esto el otro día).
Por supuesto, si solo hay dos elementos en la pila,
\;
es más corto.fuente
\;
solo aparecería el elemento debajo de los TOS. Quiso decir;;
?e
y poderes de diezComo en otros tantos idiomas, puedes escribir en
1e3
lugar de1000
en CJam.Esto funciona para bases no enteras e incluso para exponentes no enteros también. Por ejemplo,
1.23e2
empuja 123.0 y1e.5
empuja 3.1622776601683795 (raíz cuadrada de 10 ).Lo que no es obvio de inmediato es que en
1e3
realidad son dos tokens:1
empuja el entero 1 en la pila.e3
lo multiplica por 1000 .¿Por qué es eso importante?
Puedes invocar
e<numeric literal>
algo que ya está en la pila.Puede mapear
e<numeric literal>
sobre una matriz.fuente
Normas euclidianas
La forma directa de calcular la norma euclidiana de un vector, es decir, la raíz cuadrada de la suma de los cuadrados de sus elementos, es
Sin embargo, hay un camino mucho más corto.
mh
, el operador de hipotenusa, saca dos enteros a y b de la pila y empuja sqrt (a 2 + b 2 ) .Si tenemos un vector x: = [x 1 … x n ], n> 1 en la pila,
:mh
(reducir por hipotenusa) lograremos lo siguiente:Primero se empujan x 1 y x 2 y
mh
se ejecuta, dejando sqrt (x 1 2 + x 2 2 ) , en la pila.Luego, x 3 se empuja y
mh
se ejecuta nuevamente, dejandosqrt (sqrt (x 1 2 + x 2 2 ) 2 + x 3 2 ) = sqrt (x 1 2 + x 2 2 + x 3 2 ) en la pila.
Después de que x n ha sido procesado, nos queda sqrt (x 1 2 +… x n 2 ) , la norma euclidiana de x .
Si n = 1 y x 1 <0 , el código anterior producirá un resultado incorrecto.
:mhz
trabaja incondicionalmente (Gracias a @ MartinBüttner por señalar eso).He usado este truco por primera vez en esta respuesta .
fuente
Convierte desde base n con una lista de números mayor que n
CJam convierte una lista en un número con esta fórmula: A 0 * n l + A 1 * n l-1 + A 2 * n l-2 + A l * n 0 (con no negativo
n
).n
es la base yl
es la longitud de la lista. Esto significa que A i puede ser cualquier número entero, que no tiene que estar en el rango de[0,n)
.Algunos ejemplos:
0b
extrae el último elemento y lo convierte en entero. Funciona comoW=i
y guarda un byte si no fuera entero. Pero todo lo demás en la lista también debe poder convertirse en entero.1b
devuelve la suma Funciona como:i:+
y guarda dos bytes si no fueran enteros. También funciona con listas vacías mientras:+
que no.[i{_1&9 32?_@\m2/}16*;]W%:c
convierte un carácter en una cadena de finales de línea y pestañas, que se pueden volver a convertir con2bc
. Sin embargo, la función de codificación no es fácil de jugar en un programa de código de golf. Pero generalmente no necesitas eso.Puede usar el siguiente código para convertir una cadena a caracteres Unicode que no estén en 16 bits, que se pueden volver a convertir
2A#b128b:c
. (Las explicaciones se agregarán más tarde. O tal vez escriba una nueva versión más adelante).El método similar funciona con cualquier conjunto de
n
enteros que tengan diferentes valores de modn
, si puede encontrar alguna forma de deshacerse del dígito más significativo.fuente
Utilizando
$
como ternario siCuando no le importa perder memoria, es decir, dejar elementos no utilizados en la pila con los que luego borrará
];
, el operador de copia$
puede ser un sustituto útil del operador ternario?
.?
funciona bien si logra calcular la condición antes de presionar los dos elementos para elegir, pero la mayoría de las veces, la condición realmente depende de esos elementos, y tenerla encima de ellos resulta mucho más natural.Si tienes
A B C
en la pila, puedes ejecutaren lugar de
copiar
B
siC
es verdad y deA
otra manera.Si
C
es un booleano real (0
o1
), puede ejecutaren lugar de
copiar
A
siC
es verdad y deB
otra manera.fuente
Mapa de listas anidadas
Digamos que tienes una lista anidada, como una matriz:
O una serie de cadenas:
Y desea asignar un bloque al nivel anidado (es decir, aplicarlo a cada número o cada carácter). La solución ingenua es anidada
%
:Sin embargo, en realidad puede empujar el bloque interno sobre la pila y luego usarlo
f%
.f
es "mapear con parámetro adicional", por lo que se mapeará%
en la lista externa, usando el bloque como segundo parámetro:Guarda dos bytes.
Otro buen truco para hacer algo como
for (i=0; i<5; ++i) for (j=0; j<5; ++j) {...}
esEl exterior se
f
asignará al primer rango, proporcionando el segundo rango como un parámetro adicional. Pero ahora, si lo usa def
nuevo, solo el elemento de la pila superior es una matriz, por lo quef
asigna el bloque interno a ese, proporcionando la "variable de iteración" externa como un parámetro adicional. Esto significa que el bloque interno se ejecuta coni
yj
en la pila.Tiene la misma cantidad de caracteres que simplemente mapear un bloque en un producto cartesiano (aunque este último se acorta si necesita los pares como matrices):
La diferencia es que esta versión produce una única matriz de resultados para todos los pares, mientras que el doble
f
produce una lista anidada, que puede ser útil si desea almacenar los resultados en una cuadrícula, siendo las coordenadas las variables iteradoras.Gracias a Dennis por mostrarme este truco.
0.6.4 Actualizar
f
y:
ahora han sido inmensamente mejorados al tomar cualquier otro operador, incluidos ellos mismos. Esto significa que ahora puede guardar aún más bytes. La asignación de un operador a una lista anidada se hizo aún más corta ahora:Sin embargo, esto realmente no ayuda con la asignación de bloques en listas anidadas.
En cuanto a la aplicación de bloques u operadores al producto cartesiano, esto también se acortó ahora, tanto para los bloques como para los operadores:
Lo bueno es que ahora puedes anidarlos. Por lo tanto, puede aplicar un operador con la misma facilidad al tercer nivel en una lista:
O un bloque con algunos trucos:
fuente
f~
...f
espera un operador binario,~
es unario; quizás quisiste:~
? Además, podemos discutir esto en el chatUnhandled char after ':': :
( enlace )Operadores vectorizados para arte ASCII
Para muchos desafíos artísticos ASCII, es útil generar dos patrones diferentes para superponerlos más tarde. Los operadores vectorizados pueden ser muy útiles para lograr diferentes tipos de superposiciones.
Una propiedad útil de la vectorización del operador es que el operador solo se ejecuta una vez para cada elemento de la cadena / matriz más corta, mientras que los elementos de la más grande que no tienen contrapartes permanecen intactos.
.e<
El operador mínimo
e<
trabaja para pares de cadenas, caracteres, matrices y enteros; saca dos elementos de la pila y empuja la parte inferior hacia atrás.Dado que un espacio tiene un punto de código más bajo que todos los demás caracteres ASCII imprimibles,
.e<
se puede usar para "borrar" partes de un patrón generado:Para un ejemplo completo, vea mi respuesta a Me Want Honeycomb .
.e>
El operador máximo
e>
funciona como el operador mínimo, con el resultado opuesto.Nuevamente, debido al bajo punto de código del espacio,
.e>
puede usarse para insertar un patrón de caracteres imprimibles en un bloque de espacios:Para un ejemplo completo, vea mi respuesta a Seven Slash Display .
.e&
El operador lógico AND
e&
empuja su argumento izquierdo si es falso y su argumento derecho de lo contrario.Si ninguno de los patrones contiene elementos falsos, esto puede usarse para imponer incondicionalmente un patrón sobre otro:
Para ver un ejemplo completo, vea mi respuesta para Imprimir la bandera estadounidense. .
.e|
El operador lógico OR
e|
se puede usar como se indicó anteriormente, con el orden inverso de los argumentos:fuente
Use
&
para verificar si un artículo está en una listapor
Puedes usar
en cambio, que devuelve 0/1 y truthy / falsey respectivamente.
fuente
z
y matrices no rectangularesEl operador zip
z
transpone las filas y columnas de una matriz A bidimensional 1 , cuyos elementos también pueden ser iterables.Para matrices no rectangulares, a diferencia de las
zip
funciones integradas en, por ejemplo, Python (trunca las filas a la misma longitud) o Ruby (nil
rellena las filas con ), CJam simplemente convierte las columnas de la matriz en filas, ignorando sus longitudes y brechas.Por ejemplo, comprimir la matriz
es equivalente a comprimir la matriz
o la matriz
mientras las tres acciones empujan
en la pila
Si bien esto significa que
z
no es una involución (que sería útil en ocasiones), tiene algunas aplicaciones.Por ejemplo:
Podemos alinear las columnas de una matriz a la parte superior (es decir, convertir la primera matriz en la segunda) comprimiendo dos veces:
Se pueden usar modificaciones menores del método anterior para problemas similares.
Por ejemplo, para alinear las columnas de una matriz con la parte inferior (es decir, para convertir la segunda matriz en la primera), podemos comprimir dos veces con el orden de fila invertido:
Dada una serie de cadenas, podemos calcular la longitud de la cadena más larga de esta manera:
Sin embargo, al comprimir y calcular el número de filas del resultado, podemos guardar tres bytes:
1 Si alguna de las "filas" de A no es iterable, las
z
trata como singletons, por lo que la compresión funciona para matrices arbitrarias.fuente
z
convertir columnas en filas, mientras se omiten los valores vacíos. En el ejemplo, la primera columna en la entrada es 1, 2, 3, la segunda columna es 4, 5 (se omite la posición vacía), y la tercera columna es 6. Estas son las filas del resultado.Excepciones
Todas las excepciones son fatales en CJam. Como la salida a STDERR se ignora por defecto , podemos usar esto para nuestra ventaja.
Todos los operadores en CJam trabajan sacando cero o más elementos de la pila, realizan alguna tarea y empujan cero o más elementos en la pila. Se producen excepciones mientras se realiza la tarea, por lo que aún aparecen los elementos, pero no se empuja nada a cambio.
Aquí hay algunos casos de uso:
Despejando una pequeña pila
Para borrar una pila que contiene dos elementos,
@
se puede usar.@
intenta reventar tres elementos de la pila, pero falla después de reventar el segundo.Cualquier otro operador que muestre tres elementos serviría para el mismo propósito.
Véalo en acción aquí .
Eliminar dos o tres elementos de la pila
Cualquier operador que no esté implementado para estos elementos en particular puede usarse para extraer dos o tres elementos de la pila justo antes de salir.
Para reventar dos elementos,
b
funciona si uno de ellos es un personaje o ninguno de ellos es un número entero.Para reventar tres elementos,
t
funciona si ninguno de los dos más inferiores es iterable, el más inferior está vacío o ninguno de ellos es un entero.Saliendo de un bucle
En ocasiones, necesitamos salir de un bucle cuando un entero se convierte en cero o una cadena se vuelve demasiado corta. En lugar de probar estas condiciones, si las operaciones involucradas fallan por cero, la cadena vacía o los singletons, simplemente podemos dejar que el programa siga su curso natural.
Para ver un ejemplo de aritmética, consulte aquí .
Para ver un ejemplo de cadenas, vea aquí .
Ejecución condicional
Si el código fuente no se debe ejecutar para ciertos tipos de entrada, a veces podemos usar un operador que falla ese tipo de entrada.
Por ejemplo,
i
fallará para cadenas que no se evalúan como un número entero yew
fallará para cadenas de longitud 0 o 1.Véalo en acción aquí .
fuente
Max / Min de una matriz
¡Aquí hay uno para empezar!
Cuando necesita encontrar el número máximo o mínimo de una matriz, la forma más fácil y más pequeña es ordenar la matriz y luego extraer el primer o el último elemento.
Entonces, si la matriz está en variable
A
es el máximo y
Es el mínimo.
Obtener ambos al mismo tiempo también es posible
Esto puede parecer obvio después de leer, pero el primer intento de cualquiera tiende a ir hacia el uso
e<
oe>
mediante la iteración a través de la matriz, que es comoque es 2 bytes más, e incluso más si quieres max y min.
fuente
(
y en)
lugar de0=
yW=
.:e<
y:e>
Use una marca de tiempo para números grandes
Si necesita un número muy grande pero arbitrario, generalmente usará la notación científica como
9e9
o elevará una de las grandes variables incorporadas a una potencia similar, comoKK#
. Sin embargo, si no le importa cuál es el número real, y no necesita ser siempre el mismo (por ejemplo, como el límite superior para un número aleatorio), puede hacerlo en dos bytes usandoen lugar. Esto proporciona la marca de tiempo actual en milisegundos y es del orden de 10 12
fuente
e9
.Comprobando que dos cadenas / matrices no son iguales
A veces, desea un valor verdadero cuando dos cadenas o matrices no son iguales, y un valor falso si lo son. La solución obvia son dos bytes:
Verifique la igualdad e invierta el resultado. Sin embargo, bajo ciertas condiciones puedes usar
Cuando
#
se aplica a dos matrices, en realidad busca la segunda matriz como una submatriz de la primera (y le da el índice donde comienza la submatriz). Entonces, si las dos matrices son iguales, la submatriz se encontrará justo al comienzo y dará0
, lo cual es falso. Pero si no se puede encontrar la segunda matriz, dará-1
cuál es la verdad.La razón por la que necesitamos alguna condición adicional en las dos matrices es que esto también produce un valor falso si la segunda matriz es un prefijo no trivial de la primera, por ejemplo:
da
0
aunque las cuerdas no sean las mismas. La condición más simple que descarta este caso es si sabe que ambas matrices tendrán la misma longitud; en ese caso, si una es un prefijo de la otra, sabrá que son iguales. Pero en circunstancias específicas puede haber condiciones más débiles que también son suficientes. Por ejemplo, si sabe que las cadenas están ordenadas, un prefijo siempre será la primera cadena, no la segunda.fuente
c
y enteros de 16 bitsPara agregar (o restar) enteros de 16 bits sin signo con el ajuste adecuado, puede usar
+65536%
o+2G#%
.Sin embargo,
Es mucho más corto. Los personajes se envuelven alrededor de 65536 , por lo que lanzar a Character (
c
) luego a Long (i
) tiene un efecto similar a65536%
, con el beneficio adicional de que el resultado no será negativo.El mismo truco se puede usar para empujar 65535 :
fuente
Conjuntos de potencia
Digamos que tiene una matriz y desea una matriz con todos los subconjuntos posibles de esa matriz. El truco es comenzar con una matriz vacía y luego, para cada elemento, duplicar los subconjuntos que ya tienes y agregarles el nuevo elemento (manteniendo el resultado anterior donde no se agregó el elemento ). Tenga en cuenta que necesita inicializar la pila con el caso base, es decir, una matriz que contiene solo una matriz vacía: Esto podría verse así:
Lo bueno de esto es que puede ejecutar inmediatamente algunos cálculos en el subconjunto, potencialmente sin caracteres agregados. Digamos que quiere los productos de todos los subconjuntos. En ese caso, el caso base es una matriz que contiene
1
, y en cada paso, toma la lista anterior de posibles productos, la duplica y multiplica todo en el duplicado por el nuevo elemento:fuente
Compruebe si los elementos de una lista son todos iguales
Creo que esto también vale la pena mencionar. Utilizar:
Devuelve verdadero si no es todo lo mismo, o una lista vacía si es lo mismo. Errores si la lista está vacía.
En caso de que el elemento extraído pueda ser una matriz (o cadena) en sí:
Use
!
o!!
para obtener valores booleanos. En caso de que el elemento extraído pueda ser una matriz, y haya a lo sumo dos tipos de elementos diferentes, y desee que sea 1, si no todos iguales, esto es más corto:fuente
0=
para cuerdasPara recuperar el primer elemento de una matriz, debe usar
0=
(o(
, si no le importa, dejar el resto de la matriz en la pila).Sin embargo, si esa matriz es una cadena, la conversión al carácter es suficiente.
Ejemplo
fuente
c
extraer el primer elemento de cualquier matriz, lo que sería más útil y consistente.Rotación de una matriz (o la pila) una unidad hacia la izquierda
CJam tiene el operador rotar a la izquierda
m<
, que normalmente es lo que debe usar para rotar una matriz un número arbitrario de unidades a la izquierda.En algunos casos, también puede usar
(+
para cambiar y agregar:El segundo ejemplo no funcionó porque el primer elemento de la matriz también es iterable, por lo que se
+
concatena en lugar de agregarse.Además, si desea volcar la matriz girada en la pila, puede usar
:\
(reducir mediante intercambio) incondicionalmente:Mientras no tengas una apertura
[
, este truco también se puede usar para rotar toda la pila, es decir, para llevar el elemento de la pila más inferior a la parte superior:fuente
Imprimir una lista y limpiar la pila
Digamos que su pila tiene una lista de cadenas / números / etc. en la parte superior y algunos otros elementos adicionales debajo. es decir
Ahora solo le interesa imprimir la última lista, así que
que salidas
Lo que parece realmente inteligente, ya que usamos el truco de limpieza de la pila y solo imprimimos la lista unida con espacios (que a veces puede no ser la forma deseada de imprimir una lista).
¡Esto se puede jugar más al golf!
¡Eso es 2 bytes más corto !
y si solo tienes 1 elemento en la pila además de la lista, ¡es aún más corto!
Lo
p
bueno de esto es que elimina el elemento más superior de la pila, lo enrosca (también agrega una nueva línea al final) e imprime en STDOUT al instante, sin esperar a que se complete el código.Entonces el código anterior saldrá
¡cuál es la representación exacta de una lista cuando estaba en la pila!
fuente
Productos cartesianos o todas las combinaciones posibles de dos o más conjuntos
CJam tiene una calculadora de producto cartesiano incorporada
m*
que toma las dos primeras listas / cadenas en la pila y crea todos los pares posibles a partir de ella. Por ejemplohojas
como la pila
Pero, ¿qué sucede si desea todas las combinaciones posibles de más de 2 listas / cadenas? Usas
m*
eso muchas veces? Por ejemplodejará lo siguiente en la pila
Tenga en cuenta que los productos siguen siendo pares, donde uno de los elementos es un par en sí. Esto no se espera y queremos combinaciones planas.
Hay una manera fácil de hacer eso. Simplemente ajuste todas las listas que desee para su producto cartesiano en una matriz, cree productos cartesianos por pares y aplánelo cada vez:
Esto deja
en la pila
¿Quieres mantener el orden? , simplemente cambie antes de volver a agregar el elemento emergente a la matriz. es decir
¿Quieres solo permutaciones?
¿Quieres solo elementos únicos en las combinaciones?
Eso es todo amigos. por ahora .
fuente
]:m*:e_
, con cualquier número de matricesOperando en cuerdas
A veces, si está trabajando con una estructura de datos compleja, mientras que los elementos que contiene son simples, la conversión a cadenas puede ayudar.
Por ejemplo, si desea obtener el primer o el último elemento en una matriz 2D de bits, y no le importa el tipo devuelto,
sA<
guarda un byte de0=A<
o:+A<
.O si desea modificar algunos bits en la entrada, puede modificar la cadena antes de evaluarla.
O si tiene esta estructura y desea convertirla en una lista simple:
Puedes hacerlo con muchos personajes de otras maneras:
Pero puede ser mucho más corto con cadenas:
Es más corto incluso si puede tener números con más de un dígito:
O:
Si no necesita otra matriz que contenga muchas de esas matrices.
fuente
e_
ahoras
todavía funciona mejor.Usando en
N
lugar deLa
En muchos casos, necesita algo inicializado en una matriz que contenga una matriz vacía como su único elemento, que es
La
, aparentemente, innecesariamente 1 byte más.En muchos casos, también debe agregar una nueva línea después de cada elemento antes de imprimir, que sería algo así como
No
oN*
.Pero si ambas son ciertas, a veces puede descubrir que puede inicializar la matriz con
N
, que tiene el carácter de nueva línea como su único elemento. Asegúrese de anteponer solo cosas a los elementos en el resto de su código, y lo primero a anteponer es siempre un carácter o una matriz. O solo agregue, si una nueva línea principal es aceptable y eso la hace más corta.A veces
S
también funciona si necesita separar la salida con espacios.En casos más raros, el elemento inicial tiene que ser una cadena. Pero aún puede usar lo
Na
que podría ser más corto que agregar la nueva línea después.fuente
División en uno o más casos
Digamos que tiene una cadena
"abbcdbbfghbdbb"
y desea dividirlab
Esto deja en la pila:
¿Notas las cadenas vacías? Esos están allí porque dos
b
estaban juntos y no había nada entre ellos. A veces, quieres evitar esto. Puedes hacer esto poro filtrar cadenas vacías
pero eso es 3 bytes adicionales.
Un operador poco menos conocido para este caso de uso particular es
%
. Además de hacer mod y mapa y dividir en función del número ("abcd"2%
="ac"
),%
también se puede dividir en cadenas / matrices. Entonces, para el caso de uso anterior:se ira
en la pila
Gracias por @ user23013 por señalar esto en una de mis respuestas hoy.
fuente
Use doblar / reducir como infijo foreach
Tenemos
:x
como una abreviatura de{x}%
y o{x}*
(dependiendo de six
es unario o binario). Desafortunadamente, no hay un operador infijo equivalente para acortar{x}/
. Sin embargo, muy a menudo cuando lo hacemos{x}/
, enx
realidad es un operador binario que modifica repetidamente el elemento que se encuentra debajo de la pila. Si ese es el caso, y dicho elemento no es una matriz, podemos guardar un byte abusando de fold / reduce como foreach:Esto funciona porque doblar siempre deja el primer elemento intacto. Desafortunadamente, no guarda un byte, cuando el elemento modificado es una matriz, porque agregarlo lo desenvolvería. Sin embargo, a veces tiene la suerte de que su matriz ya contiene ese elemento en la parte delantera, en cuyo caso se debe tener en cuenta la reducción (en lugar de eliminar manualmente el elemento antes de usarlo
{}/
en el resto).fuente
imprimir e imprimir
Cjam tiene
print
operador:o
. Funciona, pero la pila se imprime inmediatamente después de que se haya ejecutado todo el código. Puede detenerlo si borra la pila al final del programa. Simplemente ponga esto al final:Para imprimir puedes usar
oNo
op
(funciona como`oNo
)fuente
o
yp
.p
comienza convirtiendo el elemento a imprimir en una representación de cadena inequívoca.p
es equivalente a ejecutar`oNo
.