¿Qué consejos generales tienes para jugar al golf en Mathematica? Estoy buscando ideas que puedan aplicarse a los problemas de código de golf en general que sean al menos algo específicos de Mathematica (por ejemplo, "eliminar comentarios" no es una respuesta).

(Norm[#-#2]&)en lugar deEuclideanDistance.Algunas funciones integradas con nombres largos se pueden reemplazar con expresiones más cortas.
Por ejemplo:
Total=>TrTranspose=>Threado\[Transpose]True=>1<2False=>1>2Times=>1##&Alternatives=>$|##&IntegerQ=>⌊#⌋==#&a[[1]]=>#&@@aa[[All,1]]=>#&@@@aConstantArray[a,n]=>Array[a&,n]oTable[a,{n}]Union@a=>{}⋃aoa⋃aToExpression@n=>FromDigits@nsines un númeroDivisible[n,m]=>m∣nFromDigits[n,2]=>Fold[#+##&,n]Sines una lista de0s y1sComplex@z=>{1,I}.zdondezhay una lista del formulario{x,y}fuente
Thread[{{a,b},{c,d}}]==Thread[List[{a,b},{c,d}]]=={List[a,c],List[b,d]}=={{a,c},{b,d}}==Transpose[{{a,b},{c,d}}]FoldtrucoFromDigitstambién funciona para cualquier otra base, excepto10. Por ejemploFromDigits[n,5]->Fold[4#+##&,n](con la ventaja de guardar un byte extra para bases100y1000).U+F3C7.Echosea una opción, porque imprime>>(y un espacio) en STDOUT antes de imprimir la cadena real.Complex[x,y] => {1,I}.{x,y}, creo quex+y*Ies mucho más corto con el mismo efecto?Listas con valores repetidos
Este es un vector bastante común para trabajar con:
Resulta que esto puede ser acortado por un byte:
Incluso se guardan más bytes si el vector es más largo que dos ceros. Esto también se puede utilizar para inicializar matrices cero, por ejemplo, lo siguiente proporciona una matriz de ceros 2x2:
Esto también se puede utilizar para valores distintos de cero si son lo suficientemente grandes, suficientes o negativos. Compare los siguientes pares:
Pero recuerde que a partir de 6 valores, es mejor
1~Table~6en este caso (potencialmente más temprano, dependiendo de los requisitos de precedencia).La razón por la que esto funciona es que
,introduce dos argumentos en la lista, pero los argumentos omitidos (en cualquier lugar de Mathematica) sonNulls implícitos . Además, la multiplicación esListabley0*xes0para casi cualquierx(excepto para cosas comoInfinityyIndeterminate), así que aquí está lo que está sucediendo:Para las listas de
1s, puede usar un truco similar haciendo uso de las reglas de exponenciación. Hay dos formas diferentes de guardar bytes si tiene al menos tres1s en la lista:fuente
1^{,,,}es un byte más pequeño que0{,,,}+1.{,,}^0. Editaré la publicación.Conoce tus argumentos de función pura
Al jugar al golf, a menudo empleará un enfoque funcional, en el que utiliza funciones anónimas (puras) con la
&sintaxis abreviada. Hay muchas maneras diferentes de acceder a los argumentos de una función de este tipo, y a menudo puede reducir un par de bytes al tener un buen conocimiento de las posibilidades.Acceso a argumentos únicos
Probablemente lo sepas si has usado funciones puras antes. El n º argumento se denomina
#n, y#actúa como un alias para#1. Entonces, si, por ejemplo, desea escribir una función que tome como parámetros otra función y su argumento (para pasar el argumento a esa función), useEsto no funciona con números negativos (como los que podría usar al acceder a las listas).
Acceso a argumentos con nombre (nuevo en V10)
Una de las principales características nuevas del lenguaje en Mathematica 10 es
Associations, que son básicamente mapas de valores clave con tipos de clave arbitrarios, escritos comoSi dicha asociación se pasa como primer argumento a una función pura, puede acceder a algunos de sus argumentos como parámetros con nombre:
Tenga en cuenta que
#todavía se refiere a toda la asociación como se esperaba. Para que los parámetros nombrados funcionen, las claves deben ser cadenas (no funcionará si utiliza variables indefinidas, por ejemplo), y esas cadenas deben comenzar con una letra y solo contener letras y dígitos.El argumento del "yo"
#0Una característica menos conocida es que
#0también existe y le proporciona el objeto de función en sí. Esto puede ser realmente útil en quines y quines generalizados. De hecho, la quine más corta de Mathematica (que conozco) esLo que es un poco molesto es que no te dará los caracteres exactos que ingresaste. Por ejemplo, si se usa
@para la aplicación de funciones, todavía se representará como[...]y se insertarán espacios en algunos lugares. Esto generalmente hará que la quine sea un poco más larga de lo que le gustaría, pero siempre funcionará, primero jugando al quine y luego simplemente copiando su salida, que ahora debería ser una quine real.Además de quines, esto también significa que puede escribir código recursivo sin tener que nombrar su función. Compare estas tres implementaciones de Fibonacci (ingenuas pero golfistas):
Secuencias de argumentos
Ahora aquí es donde comienza la verdadera magia. Las secuencias no se usan a menudo en el golf, porque
Sequencees un nombre demasiado largo para que valga la pena la mayor parte del tiempo. Pero en las funciones puras es donde brillan. Si no está familiarizado con las secuencias, básicamente son como símbolos en algunos otros idiomas, si usa una secuencia en unaListlista de argumentos de una función, sus elementos se expandirán automáticamente en ranuras separadas. Asi queAhora, en funciones puras
##o##1es una secuencia de todos los argumentos. Del mismo modo,##2es una secuencia de todos los argumentos que comienzan desde el segundo,##3todos los argumentos que comienzan desde el tercero, etc. Entonces, para empezar, podemos volver a implementarSequencecomo##&, ahorrando 5 bytes. Como ejemplo de uso, esto nos proporciona una alternativa aJoin@@list(vea este consejo ), que no guarda ningún byte, pero es bueno saber de todos modos:Esto efectivamente aplana el primer nivel de una lista anidada. ¿Qué más podemos hacer con esto? Aquí hay una alternativa más corta de 2 bytes para
RotateLeft:Solo por estas cosas vale la pena tener en cuenta esta característica. Sin embargo, podemos hacerlo mejor! Las secuencias se vuelven realmente interesantes cuando se considera que los operadores se implementan realmente como funciones ocultas. Por ejemplo, en
a+brealidad evalúa aPlus[a,b]. Entonces, si le damos una secuencia ...Este truco se ha utilizado en este consejo para guardar un byte
Times, porque técnicamente la yuxtaposición también es solo un operador:También puede usarlo para guardar un byte
Unequalsi tiene un valor o variable de un solo carácter que sabe que no está en sus argumentos (Nprobablemente funcionará en el 99% de los casos):Esto se vuelve aún más interesante con los operadores unarios y
-y/- los dos últimos se llevan a la práctica los términos de la multiplicación y exponenciación. Aquí hay una lista de cosas que puede hacer, donde la última columna asume que la función pasó los argumentosa, b, c:Otros operadores son comunes
!=,==,&&,||. Menos comunes a tener en cuenta son|,@*,/*. Para concluir, aquí hay un pequeño truco extra:¡Siga experimentando con estos y avíseme si encuentra otras aplicaciones útiles o particularmente interesantes!
fuente
Sqrt@2o2^.5=>√2a[[1]]=>a〚1〛#+#2&=>+##&Flatten@a=>Join@@a(a veces)Function[x,x^2]=>xx^2o#^2&a〚1;;-1;;2〛=>a〚;;;;2〛a〚2;;-1 ;;2〛=>a〚2;;;;2〛a〚All,1〛=>a〚;;,1〛{{1}}〚1,1〛=>Tr@{{1}}0&~Array~10=>0Range@10Range[10^3]=>Range@1*^3fuente
〚y〛toma 3 bytes cada uno (suponga UTF8)Operadores como funciones
Inspirado por el reciente descubrimiento de Dennis para Julia , pensé en investigar esto para Mathematica. Sabía que Mathematica define una gran cantidad de operadores no utilizados, pero nunca le prestó mucha atención.
Como referencia, la lista de todos los operadores se puede encontrar aquí en forma de una tabla de precedencia. El triángulo en la última columna indica si ese operador tiene un significado incorporado o no. Si bien no todos los que no se pueden definir fácilmente, la mayoría sí.
Convenientemente, hay dos operadores no utilizados con un punto de código inferior a 256, de modo que se pueden usar como bytes individuales en un archivo fuente codificado ISO 8859-1:
±(0xB1) se puede usar como operador de prefijo unario o como operador de infijo binario.·(0xB7) se puede utilizar como operador infijo variadic o n-ary, para n> 2.Sin embargo, hay una trampa más: por alguna extraña razón al definir estos operadores, necesita un espacio delante de ellos, o Mathematica intenta analizar una multiplicación. Sin embargo, al usarlos no necesita espacios:
Compare esto con:
Esto ahorra un byte cuando se define la función y dos bytes cuando se usa. Tenga en cuenta que la definición de
·no guardará bytes para cuatro operandos y comenzará a costar bytes para más operandos, pero el uso aún puede guardar bytes, dependiendo de la precedencia de los operadores utilizados en los argumentos. También es bueno tener en cuenta que puede definir de manera económica una función variada que luego se puede llamar de manera mucho más eficiente:Pero tenga en cuenta que no es fácilmente posible llamar a estas funciones variadas con un solo argumento. (Podría hacerlo
CenterDot[x]o##&[]·xsi realmente lo necesita, hay una buena posibilidad de que esté mejor con una solución diferente).Por supuesto, esto no está guardando nada para soluciones en las que una función sin nombre es suficiente, pero a veces es necesario definir funciones auxiliares para su uso posterior, y a veces es más corto definir funciones con nombre, por ejemplo, para establecer diferentes definiciones para diferentes parámetros. En esos casos, usar un operador en su lugar puede ahorrar una cantidad decente de bytes.
Tenga en cuenta que el uso de estos archivos codificados ISO 8859-1
$CharacterEncodingdebe establecerse en un valor compatible, como el predeterminado de WindowsWindowsANSI. En algunos sistemas, este valor predeterminadoUTF-8no podrá leer estos puntos de código desde bytes individuales.fuente
Elegir valores basados en enteros
El enfoque ingenuo para elegir entre
yyz, dependiendo de sixes0o1esSin embargo, hay una forma más corta:
Esto funciona porque
[[0]]da laHeadde una expresión, en este casoy, mientras que[[1]]solo da el primer elemento - en este caso el primer argumento,z.Incluso puede usar esto para elegir entre más de dos valores:
Tenga en cuenta que esto no funcionará si
ues una función que realmente se evalúa como algo. Es importante que Mathematica se mantengau[v,w]como está. Sin embargo, esto funciona en la mayoría de los casos, incluso siues un número, una cadena o una lista.Los créditos para este truco van a alephalpha: descubrí esto en una de sus respuestas.
Si
xse basa en 1 en lugar de en cero, solo useo
En algunos casos raros, incluso puede hacer uso del hecho de que la multiplicación no se evalúa para algunos valores:
Sin embargo, tenga en cuenta que Mathematica reordenará los argumentos, de una multiplicación si permanece sin evaluar, por lo que lo anterior es idéntico a
fuente
Alternativas a
LengthEsto ha sido completamente reescrito con algunas sugerencias de LegionMammal978 y Misha Lavrov. Muchas gracias a los dos.
En muchos casos,
Lengthse puede acortar un poco haciendo uso deTr. La idea básica es convertir la entrada en una lista de1s, de modo que lasTrsume , lo que equivale a la longitud de la lista.La forma más común de hacer esto es usar
1^x(para una listax). Esto funciona porquePoweresListabley1^npara la mayoría de los valores atómicosnes justo1(incluidos todos los números, cadenas y símbolos). Entonces ya podemos guardar un byte con esto:Por supuesto, esto supone que
xes una expresión con mayor precedencia que^.Si
xcontiene solo0sy1s, podemos guardar otro byte usandoFactorial(suponiendo quextenga mayor prioridad que!):En algunos casos raros,
xpodría tener una precedencia más baja que^una precedencia aún mayor que la multiplicación. En ese caso, también tendrá una precedencia menor que@, por lo que realmente necesitamos compararLength[x]. Un ejemplo de tal operador es.. En esos casos, aún puede guardar un byte con este formulario:Finalmente, algunos comentarios sobre qué tipo de listas funcionan:
Como se mencionó en la parte superior, esto funciona en listas planas que contienen solo números, cadenas y símbolos. Sin embargo, también funcionará en algunas listas más profundas, aunque en realidad calcula algo ligeramente diferente. Para una matriz rectangular n -D, el uso
Trle brinda la dimensión más corta (en oposición a la primera). Si sabe que la dimensión más externa es la más corta, o sabe que son todas iguales, entonces lasTrexpresiones -son equivalentes aLength.fuente
Length@x == Tr[1^x]. Debería funcionar con la mayoría de las listas.Tr[x!]lugar deTr[1^x]guardar un byte en el caso especial dondexsolo contiene ceros y unos.Explore soluciones recursivas : Mathematica es multi-paradigma, pero el enfoque funcional es a menudo el más económico.
NestWhilepuede ser una solución muy compacta a problemas de búsqueda, yNestWhileListyFoldListson poderosos cuando se necesita devolver o procesar los resultados de iteraciones intermedios.Map (/@),Apply (@@, @@@),MapThread, Y realmente todo el contenido de Wolfram programación funcional página de documentación es potente cosas.Forma acortada para incremento / decremento : por ejemplo, en lugar de
While[i<1,*code*;i++]que pueda hacerWhile[i++<1,*code*]No olvide que puede aumentar / disminuir previamente : por ejemplo, en
--ilugar dei--. Esto a veces puede ahorrarle unos pocos bytes en el código circundante al eliminar una operación preparatoria.Corolario del n. ° 5 de David Carraher: cuando se usa la misma función muchas veces, asignarle un símbolo puede ahorrar bytes. Por ejemplo, si está usando
ToExpression4 veces en una solución, let=ToExpressionpermite usart@*expression*después. Sin embargo, antes de hacer esto, considere si la aplicación repetida de la misma función indica una oportunidad para un enfoque recursivo más económico.fuente
MapThreada menudo puede ser reemplazado por\[Transpose]. TIO .No lo use
{}si lo está usando@@@.En algunos casos, puede encontrar una expresión como:
Es posible reducir bytes escribiendo:
Alternativestiene una precedencia muy baja, por lo que generalmente está bien escribir expresiones (una excepción notable son las funciones puras; solo puede usarlo en el elemento más a la izquierda deAlternatives).Tenga en cuenta que
f@@a|b|c(en lugar def@@{a,b,c}) no funciona porqueApplytiene una precedencia mayor queAlternative.En este caso, simplemente debes usar
f@@{a,b,c}.fuente
Solo Mathematica 10
Formularios de operador
Mathematica 10 admite las llamadas "formas de operador", lo que básicamente significa que algunas funciones se pueden cursar. Hacer curry de una función es crear una nueva función arreglando uno de sus operadores. Digamos que estás usando
SortBy[list, somereallylongfunction&]muchoslists diferentes . Antes, es probable que haya asignadoSortByasy la función pura afpor loAhora puedes curry
SortBy, lo que significa que ahora puedes hacerLo mismo funciona para muchas otras funciones, que tienen una lista o función argumento, incluyendo (pero no limitado a)
Select,Map,Nearest, etc.ybeltukov en Mathematica.SE pudo producir una lista completa de estos :
Composición y composición derecha
Hay nuevas shorthands para
Composition(@*) yRightComposition(/*). Un ejemplo obviamente ideado donde estos pueden guardar caracteres se ve en las siguientes tres líneas equivalentesfuente
No escriba funciones de argumento 0
No hay necesidad de código como este:
Simplemente puede usar una variable con
:=para forzar la reevaluación del lado derecho:Esto también significa que puede alias cualquier acción que realice a menudo (incluso si es algo así
n++) a un solo carácter a un costo de 5 bytes. Entonces, en el caso den++que pague después del cuarto uso:fuente
Use
%para obtener una variable libreEste consejo solo es aplicable si se puede suponer el entorno REPL de Mathematica.
%no se define cuando el código se ejecuta como un script.Cuando pueda hacer uso de las funciones REPL, no haga esto:
En cambio, recuerde que Mathematica almacena la última expresión evaluada (terminada en nueva línea) en
%:La nueva línea agregada cuesta un byte, pero está ahorrando dos al eliminar
a=, por lo que, en general, esto ahorra un byte.En algunos casos (por ejemplo, cuando desea imprimir el valor de
atodos modos), incluso puede dejar de lado;, guardando dos bytes:Uno o dos bytes pueden parecer bastante menores, pero este es un caso importante, ya que hace que la extracción de expresiones repetidas (que es una técnica muy común) sea mucho más útil cuando se juega al golf:
La técnica normal de extraer expresiones repetidas cuesta cuatro bytes de sobrecarga, que deben guardarse mediante usos adicionales de la expresión. Aquí hay una breve tabla del número mínimo de usos de una expresión (por longitud de la expresión) para extracción en una variable con nombre para guardar cualquier cosa:
Al usar la variable sin nombre, será posible guardar un par de bytes con mucha más frecuencia:
No creo
%%o%npuedo usarlo para jugar al golf, porque si no los usas al menos dos veces, puedes poner la expresión justo donde se necesita. Y si lo usa dos veces, el carácter adicional en el nombre de la variable cancela los ahorros por omitir algunosx=.fuente
Comprobando si una lista está ordenada
Esto es esencialmente un corolario de este consejo, pero esta es una tarea suficientemente común que creo que justifica su propia respuesta.
La forma ingenua de verificar si una lista está en orden es usar
Podemos hacer un byte mejor con
Sin embargo, esto no funciona si ya no tenemos lo que queremos registrar en una variable. (Necesitaríamos algo como lo
Sort[a=...]==aque es innecesariamente largo). Sin embargo, hay otra opción:Lo mejor es que esto se puede usar para verificar si la entrada está ordenada inversamente para el mismo recuento de bytes:
Se puede guardar un byte más si a) sabemos que los elementos de la lista son distintos yb) conocemos un límite inferior entre 0 y 9 (inclusive; o límite superior para el orden inverso):
Para ver por qué esto funciona, consulte "Secuencias de argumentos" en la sugerencia vinculada en la parte superior.
fuente
##>0&@@a. Similar para límite superior para ordenado.Repetir una cuerda
En lugar de
StringRepeat[str,n]usar(0Range[n]+str)<>"". O sistrno depende de ningún argumento de ranura, aún mejor esArray[str&,n]<>""según este consejo.fuente
StringRepeat[s,n+1]usarArray[s&,n]<>s(incluso cuando ya tienen+1una variable, también).Table[str,n]<>""Si necesita una lista de números ordenados al revés, no use
pero
para guardar seis bytes. Ordenar por un valor negativo también es útil para
SortByescenarios:fuente
-Sort@-x?Puede pegar una expresión en la
Breakque puede guardar uno o dos caracteres. Ejemplo ( otros detalles no revelados para mayor claridad ):se puede convertir en
para salvar a un personaje Si la expresión en cuestión no tiene menor prioridad que la aplicación de función, incluso puede guardar otro carácter:
se puede convertir en
Aunque no está documentado, el argumento
Breakparece ser devuelto por el ciclo circundante, lo que puede conducir a ahorros aún mayores.fuente
Para eliminar todos los espacios en blanco de una cadena
s, useEs decir, use
StringSplitel valor predeterminado (dividido en componentes que no sean espacios en blanco) y simplemente vuelva a unirlos. Probablemente, el mismo sea el más corto si quieres deshacerte de cualquier otro personaje o subcadena:fuente
Alternativas a
RangeUna tarea muy común es aplicar algún tipo de función a todos los números del 1 al a
n(generalmente se proporciona como entrada). Básicamente, hay 3 formas de hacer esto (usando una función de identidad sin nombre como ejemplo):Tiendo a ir por el primero (por cualquier razón), pero rara vez es la mejor opción.
Usando en su
ArraylugarEl ejemplo anterior muestra que usar
Arraytiene el mismo número de bytes. Sin embargo, tiene la ventaja de que es una sola expresión. En particular, si desea seguir procesando el resultado con una funciónf, puede usar la notación de prefijo, que guarda un byte sobreRange:Además, puede omitir paréntesis alrededor de su función sin nombre que podría haber necesitado
Range, por ejemplo,Si no desea usarlo más (o con un operador que tiene menor prioridad), puede escribirlo
Arrayen notación infija y también guardar un byte:Por lo tanto,
Arrayes casi seguro mejor queRange.Usando en su
TablelugarAhora la tabla tiene que compensar 3 bytes, o al menos 2 cuando la notación infijada es una opción:
Cuando no use la notación infija,
Tablepodría permitirle omitir paréntesis si su función consta de varias declaraciones:Esto aún es más largo, pero ofrece ahorros adicionales en el caso mencionado a continuación.
Los ahorros reales se
Tabledeben al hecho de que no se debe descartar el nombre de la variable en ejecución. A menudo, habrá anidado funciones sin nombre donde desea utilizar la variable externa dentro de una de las funciones internas. Cuando eso sucede,Tablees más corto queRange:No solo guarda los caracteres para asignarlos
i, sino que también puede reducir la función a una sola declaración en el proceso, lo que le permite usar la notación infija encima. Como referencia,Arraytambién es más largo en este caso, pero aún más corto queRange:¿Cuándo lo usarías realmente
Range?Siempre que no necesite una llamada de función para procesar los valores, por ejemplo, cuando la asignación se puede realizar mediante una operación vectorizada. Por ejemplo:
Por supuesto, también es más corto si no desea asignar ninguna función, por ejemplo,
fuente
f/@Range[x]regularmente ...Encontrar el número más pequeño que satisface una condición
Algunos constructos like
i=1;While[cond[i],i++]están bien como están, pero hay una alternativa que es dos bytes más corta:El código anterior reemplaza repetidamente un número
ipori+1mientras cumple la condicióncond[i]. En este caso,icomienza en1.Tenga en cuenta que el número máximo predeterminado de iteraciones es 2 ^ 16 (= 65536). Si necesita más iteraciones que eso,
Whilesería mejor. (MaxIterations->∞es demasiado largo)fuente
Abuso de evaluación de cortocircuito
A veces puede reemplazar
Ifcon un operador lógico.Por ejemplo, supongamos que desea hacer una función que verifique si un número es primo, e imprimir
2*(number) - 1es si es verdadero:Es más corto si usas en su
&&lugar:Incluso cuando tiene varias expresiones, aún guarda byte (s):
Puede usar
||para casos en los que desea que la condición seaFalse:Estos trucos funcionan porque los operadores lógicos pueden estar en cortocircuito ; el segundo argumento y, posteriormente, ni siquiera necesitan ser expresiones booleanas válidas.
Por supuesto, esto no funciona si necesita el valor de retorno de
Ifo cuando necesita argumentos tanto verdaderos como falsosIf.fuente
Aquí hay una lista con un montón de formularios de entrada del operador que pueden acortar muchas cosas. Algunos de estos se han mencionado en otras publicaciones, pero la lista es larga y siempre me sorprende encontrar algunas cosas nuevas allí:
fuente
Utilizando
Optional (:)Optional (:)se puede usar para expandir listas en reemplazos, sin tener que definir una regla separada para la expansión.Esta respuesta de mí y esta respuesta de @ngenisis son ejemplos.
Uso
El reemplazo anterior utiliza primero el patrón
{p___, a_, b_, q___}y encuentra una coincidencia quebcumple una determinada condición.Cuando no se encuentra dicha coincidencia, se omite
a_y en su lugar se busca{p___, b_, q___}.ano está incluido en la búsqueda y se supone que tiene el valor0.Tenga en cuenta que la segunda búsqueda de patrones solo funcionaría para
beso ocurre al comienzo de la lista; si unbvalor que satisface una condición está en el medio, entonces{p___, a_, b_, q___}(que tiene una precedencia más alta) lo igualará en su lugar.El reemplazo es equivalente a anteponer a
0cuando sebproduce una condición satisfactoria al comienzo de la lista. (es decir, no es necesario definir una regla separada{b_, q___} /; cond[b] :> ...)fuente
Sepa cuándo (y cuándo no) usar argumentos de función pura con nombre
Para el golf de código, los
Functionargumentos puros se referencian más comúnmente usandoSlots; por ejemplo,#para el primer argumento,#2para el segundo, etc. (vea esta respuesta para más detalles).En muchos casos, querrás anidar
Functions. Por ejemplo,1##&@@#&es unFunctionque toma una lista como su primer argumento y genera el producto de sus elementos. Aquí está esa función enTreeForm:Los argumentos pasados al nivel superior
Functionsolo pueden llenarSlotsysSlotSequencepresentes en el nivel superior, lo que en este caso significa queSlotSequenceen el interiorFunctionno habrá ninguna forma de acceder a los argumentos al nivel superiorFunction.Sin embargo, en algunos casos, es posible que desee un
Functionanidado dentro de otroFunctionpara poder hacer referencia a argumentos externosFunction. Por ejemplo, es posible que desee algo comoArray[fun,...]&, donde la funciónfundepende de un argumento al nivel superiorFunction. Para concretar, digamos quefundebería dar al resto del cuadrado de su módulo de entrada la entrada al nivel superiorFunction. Una forma de lograr esto es asignar el argumento de nivel superior a una variable:Dondequiera que
xaparezca en lo internoFunctionMod[#^2,x]&, se referirá al primer argumento a lo externoFunction, mientras que#se referirá al primer argumento a lo internoFunction. Un mejor enfoque es utilizar el hecho de queFunctiontiene una forma de dos argumentos donde el primer argumento es un símbolo o una lista de símbolos que representarán argumentos con nombre para elFunction(en lugar deSlots sin nombre ). Esto termina ahorrándonos tres bytes en este caso:es el carácter de uso privado de tres bytes queU+F4A1representa el operador infijo binario\[Function]. También puede usar la forma binaria deFunctionotroFunction:Esto es equivalente a lo anterior. La razón es que, si está utilizando argumentos con nombre, se supone que
SlotsySlotSequencespertenecen al siguienteFunctionanterior que no utiliza argumentos con nombre.Ahora, solo porque podamos anidar
Functions de esta manera, no significa que siempre debamos hacerlo. Por ejemplo, si quisiéramos seleccionar aquellos elementos de una lista que son menores que la entrada, podríamos sentir la tentación de hacer algo como lo siguiente:En realidad, sería más corto de usar
Casesy evitaría la necesidad de un anidado porFunctioncompleto:fuente
Puede guardar un byte trabajando
PrependoPrependTo:o
Desafortunadamente, esto no ayuda para los más comunes
Append, que parece ser el equivalente más corto de unArray.push()en otros idiomas.fuente
Mathematica 10.2:
BlockMapesPartition+MapEste consejo también podría titularse, "Lea las notas de la versión, todas". (Como referencia, aquí están las notas de la versión 10.2 y aquí la versión 10.3 de hoy ).
De todos modos, incluso las versiones menores contienen una gran cantidad de nuevas características, y una de las más útiles (para jugar al golf) de 10.2 es la nueva
BlockMapfunción. Básicamente se combinaPartitionyMapes ideal para los golfistas, porquePartitionse usa con bastante frecuencia y es un nombre de función realmente molesto y largo. La nueva función no se acortaráPartitionpor sí sola, pero cada vez que desee asignar una función a las particiones (lo que probablemente ocurre con mayor frecuencia), ahora puede guardar un byte o dos:Los ahorros se hacen aún mayores cuando la nueva posición de la función sin nombre le permite guardar algunos paréntesis:
Desafortunadamente, no tengo idea de por qué no agregué
BlockApplymientras estaban en eso ...También tenga en cuenta que
BlockMapno admite el cuarto parámetro con el que puede usarPartitionpara obtener una lista cíclica:fuente
Almacenar funciones y expresiones en una variable
Si su respuesta termina usando las mismas funciones o expresiones varias veces, puede considerar almacenarlas en variables.
Si su expresión es longitud
ly la usanveces, normalmente usaríal * nbytes.Sin embargo, si lo almacena en una variable de longitud 1, solo tomaría
3 + l + nbytes (o2 + l + nbytes, si asigna la variable donde no la necesitaráCompoundExpression (;)o paréntesis).Por ejemplo, consideremos un problema simple, encontrar primos gemelos menores que N.
Se podría escribir esta solución de 54 bytes:
En este ejemplo, la función
PrimeQse usa tres veces.Al asignar
PrimeQun nombre de variable, el recuento de bytes se puede reducir. Los dos siguientes son 48 bytes (54 - 6 bytes):fuente
Para lograr una lista ascendente de clave-valor, use en
Sortlugar deSortByPara listas como
list = {{1, "world"}, {0, "universe"}, {2, "country"}}, las siguientes tres declaraciones son casi equivalentes.Combinar
SelectySortByA veces necesitamos seleccionar entradas de un conjunto más grande y ordenarlas para encontrar un mínimo / máximo. En algunas circunstancias , dos operaciones podrían combinarse en una.
Por ejemplo, como mínimo, las siguientes dos declaraciones son casi equivalentes.
y
1/0es decirComplexInfinity, que es "más grande" que todos los números reales.Para una lista de valores clave, por ejemplo:
fuente
Aplanar un
Arraycon##&Cuando use una matriz multidimensional para calcular una lista de resultados que necesita ser aplanada, use
##&como cuarto argumento. Esto reemplaza las cabezas de la matriz con##&(equivalente aSequence) en lugar deList, por lo que el resultado final será un (plano)Sequencede resultados.En dos dimensiones, compare
Por supuesto,
Join@@Array[f,dims]sigue siendo 2 (o 3, si se puede usar la notación infija) bytes más cortos que{Array[f,dims,1,##&]}.En tres o más dimensiones,
{Array[f,dims,origin,##&]}siempre es más corto que la alternativa, incluso si el origen es 1.fuente
Valores predeterminados
Los valores predeterminados tratan los argumentos de patrones faltantes de manera eficiente. Por ejemplo, si queremos un patrón de coincidencia
Exp[c_*x]en una regla para cualquier valor dec, el ingenuousa muchos más bytes que si usamos el valor predeterminado para
ccuando falta:El uso de un valor predeterminado, se indica con un punto después el patrón:
c_..Los valores predeterminados están asociados con las operaciones: en el ejemplo anterior, la operación está
Timesactivadac_.*xy, porc_lo tanto, se toma un valor faltante del valor predeterminado asociado conTimes, que es 1. ParaPlus, el valor predeterminado es 0:Para
Powerexponentes, el valor predeterminado es 1:fuente