Que dicas gerais você tem para jogar golfe no Mathematica? Estou procurando idéias que possam ser aplicadas para codificar problemas de golfe em geral que sejam pelo menos um pouco específicos para o Mathematica (por exemplo, "remover comentários" não é uma resposta).
(Norm[#-#2]&)
do que paraEuclideanDistance
.Algumas funções internas com nomes longos podem ser substituídas por expressões mais curtas.
Por exemplo:
Total
=>Tr
Transpose
=>Thread
ou\[Transpose]
True
=>1<2
False
=>1>2
Times
=>1##&
Alternatives
=>$|##&
IntegerQ
=>⌊#⌋==#&
a[[1]]
=>#&@@a
a[[All,1]]
=>#&@@@a
ConstantArray[a,n]
=>Array[a&,n]
ouTable[a,{n}]
Union@a
=>{}⋃a
oua⋃a
ToExpression@n
=>FromDigits@n
sen
é um númeroDivisible[n,m]
=>m∣n
FromDigits[n,2]
=>Fold[#+##&,n]
Sen
é uma lista de0
s e1
sComplex@z
=>{1,I}.z
ondez
está uma lista do formulário{x,y}
fonte
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}}]
Fold
truqueFromDigits
também funciona para qualquer outra base, exceto10
. Por exemploFromDigits[n,5]
->Fold[4#+##&,n]
(com o bônus de salvar um byte extra para bases100
e1000
).U+F3C7
.Echo
seja uma opção, porque ela imprime>>
(e um espaço) em STDOUT antes de imprimir a string real.Complex[x,y] => {1,I}.{x,y}
, eu acho quex+y*I
é muito mais curto com o mesmo efeito?Listas com valores repetidos
Este é um vetor bastante comum para se trabalhar:
Acontece que isso pode ser reduzido por um byte:
Ainda mais bytes são salvos se o vetor for maior que dois zeros. Isso também pode ser usado para inicializar matrizes zero, por exemplo, o seguinte fornece uma matriz 2x2 de zeros:
Isso também pode ser usado para valores diferentes de zero se forem suficientemente grandes ou muitos ou negativos. Compare os seguintes pares:
Mas lembre-se de que, a partir de 6 valores, você estará melhor
1~Table~6
nesse caso (potencialmente mais cedo, dependendo dos requisitos de precedência).A razão pela qual isso funciona é que
,
introduz dois argumentos na lista, mas argumentos omitidos (em qualquer lugar do Mathematica) são implícitosNull
. Além disso, a multiplicação éListable
e0*x
é0
para quase todosx
(exceto para coisas comoInfinity
eIndeterminate
), então aqui está o que está acontecendo:Para listas de
1
s, você pode usar um truque semelhante usando regras de exponenciação. Existem duas maneiras diferentes de salvar bytes, se você tiver pelo menos três1
s na lista:fonte
1^{,,,}
é um byte menor que0{,,,}+1
.{,,}^0
. Eu vou editar a postagem.Conheça seus argumentos de função pura
Ao jogar código no golfe, você costuma empregar uma abordagem funcional, na qual usa funções anônimas (puras) com a
&
sintaxe abreviada. Existem várias maneiras diferentes de acessar os argumentos de uma função e, geralmente, você pode economizar alguns bytes tendo uma boa noção das possibilidades.Acessando argumentos únicos
Você provavelmente sabe disso se já usou funções puras antes. O n º argumento é referido como
#n
, e#
atua como um alias para#1
. Portanto, se, digamos, você quiser escrever uma função que tome como parâmetros outra função e seu argumento (para passar o argumento para essa função), useIsso não funciona com números negativos (como você pode usar ao acessar listas).
Acessando argumentos nomeados (novo na V10)
Um dos principais recursos novos de linguagem do Mathematica 10 é o
Association
s, que são basicamente mapas de valores-chave com tipos de chave arbitrários, escritos comoSe essa associação for passada como o primeiro argumento para uma função pura, você poderá acessar alguns se os argumentos forem parâmetros nomeados:
Observe que
#
ainda se refere a toda a associação conforme o esperado. Para que os parâmetros nomeados funcionem, as chaves devem ser cadeias de caracteres (não funcionará se você usar variáveis indefinidas, por exemplo), e essas cadeias devem começar com uma letra e conter apenas letras e dígitos.O argumento "auto"
#0
Um recurso menos conhecido é que
#0
também existe e fornece o próprio objeto de função. Isso pode ser realmente útil em quines e em generalizados. De fato, o menor quine Mathematica (eu sei) éO que é um pouco chato é que ele não fornece os caracteres exatos digitados. Por exemplo, se usado
@
para aplicação de função, ele ainda será renderizado[...]
e espaços serão inseridos em alguns lugares. Isso normalmente tornará o quine um pouco mais longo do que você gostaria, mas sempre funcionará, jogando o quine primeiro e depois apenas copiando sua saída - que agora deve ser um quine real.Além de quines, isso também significa que você pode escrever código recursivo sem precisar nomear sua função. Compare estas três implementações de Fibonacci (ingênuas, mas eficientes):
Sequências de argumentos
Agora é aqui que a mágica real começa. As seqüências não são usadas frequentemente no golfe, porque
Sequence
é um nome muito longo para valer a pena na maioria das vezes. Mas em funções puras é onde elas brilham. Se você não estiver familiarizado com sequências, elas são basicamente como splats em alguns outros idiomas; se você usar uma sequência em umaList
ou na lista de argumentos de uma função, seus elementos serão automaticamente expandidos em slots separados. tãoAgora, em funções puras
##
ou##1
é uma sequência de todos os argumentos. Da mesma forma,##2
é uma sequência de todos os argumentos a partir do segundo,##3
todos os argumentos a partir do terceiro etc. Portanto, para começar, podemos apenas reimplementarSequence
como##&
, economizando 5 bytes. Como exemplo de uso, isso nos fornece uma alternativa paraJoin@@list
(consulte esta dica ), que não salva nenhum bytes, mas é bom saber de qualquer maneira:Isso aplaina efetivamente o primeiro nível de uma lista aninhada. O que mais podemos fazer com isso? Aqui está uma alternativa 2 bytes mais curta para
RotateLeft
:Só para essas coisas, vale a pena manter esse recurso em mente. No entanto, podemos fazer melhor! As sequências ficam realmente interessantes quando consideramos que os operadores são realmente implementados como funções ocultas. Por exemplo,
a+b
na verdade avalia comoPlus[a,b]
. Então, se dermos uma sequência ...Este truque foi usado nesta dica para economizar um byte
Times
, porque a justaposição tecnicamente também é apenas um operador:Você também pode usá-lo para salvar um byte
Unequal
se você tiver um valor de caractere único ou variável que você sabe que não esteja em seus argumentos (N
provavelmente funcionará em 99% dos casos):Isso fica ainda mais interessante com operadores unários
-
e/
- os dois últimos são realmente implementados em termos de multiplicação e exponenciação. Aqui está uma lista de coisas que você pode fazer, onde a última coluna assume que a função recebeu os argumentosa, b, c
:Outros operadores comuns são
!=
,==
,&&
,||
. Os menos comuns para se manter em mente são|
,@*
,/*
. Para concluir, aqui está um pequeno truque de bônus:Continue experimentando isso e deixe-me saber se você encontrar outras aplicações úteis ou particularmente interessantes!
fonte
Sqrt@2
ou2^.5
=>√2
a[[1]]
=>a〚1〛
#+#2&
=>+##&
Flatten@a
=>Join@@a
(às vezes)Function[x,x^2]
=>xx^2
ou#^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@10
Range[10^3]
=>Range@1*^3
fonte
〚
e use〛
3 bytes cada (assuma UTF8) #Operadores como funções
Inspirado pela recente descoberta de Dennis para Julia , pensei em investigar isso no Mathematica. Eu sabia que o Mathematica define um grande número de operadores não utilizados, mas nunca prestou muita atenção a ele.
Para referência, a lista de todos os operadores pode ser encontrada aqui na forma de uma tabela de precedência. O triângulo na última coluna indica se esse operador tem um significado interno ou não. Embora nem todos os que não podem ser definidos facilmente, a maioria deles pode.
Convenientemente, existem dois operadores não utilizados com um ponto de código menor que 256, para que possam ser usados como bytes únicos em um arquivo de origem codificado ISO 8859-1:
±
(0xB1) pode ser usado como um operador de prefixo unário ou como um operador de infixo binário.·
(0xB7) pode ser usado como um operador de infix variável ou n-ária, para n> 2.Porém, há mais um problema: por alguma razão estranha ao definir esses operadores, você precisa de um espaço na frente deles, ou o Mathematica tenta analisar uma multiplicação. Ao usá-los, você não precisa de espaços:
Compare isso com:
Portanto, isso economiza um byte ao definir a função e dois bytes ao usá-la. Observe que a definição de
·
não salvará bytes para quatro operandos e começará a custar bytes para mais operandos, mas o uso ainda poderá salvar bytes, dependendo da precedência dos operadores usados nos argumentos. Também é bom observar que você pode definir de forma barata uma função variadica que pode ser chamada com muito mais eficiência:Mas observe que não é possível chamar facilmente essas funções variadas com um único argumento. (Você pode fazer isso
CenterDot[x]
ou,##&[]·x
se realmente precisar, há uma boa chance de você estar melhor com uma solução diferente.)Obviamente, isso não está salvando nada para soluções em que uma função sem nome é suficiente, mas às vezes você precisa definir funções auxiliares para uso posterior, e às vezes é mais curto definir funções nomeadas, por exemplo, para definir definições diferentes para parâmetros diferentes. Nesses casos, o uso de um operador pode salvar uma quantidade decente de bytes.
Observe que o uso desses arquivos codificados ISO 8859-1 precisa
$CharacterEncoding
ser definido como um valor compatível, como o padrão do WindowsWindowsANSI
. Em alguns sistemas, esses padrõesUTF-8
não podem ler esses pontos de código a partir de bytes únicos.fonte
Escolhendo valores com base no número inteiro
A abordagem ingênua para escolher entre
y
ez
, dependendo dex
ser0
ou1
nãoNo entanto, há uma maneira mais curta:
Isso funciona porque
[[0]]
dá aHead
expressão de, neste casoy
, enquanto[[1]]
apenas fornece o primeiro elemento - nesse caso, o primeiro argumentoz
,.Você pode usar isso para escolher entre mais de dois valores:
Observe que isso não funcionará se
u
for uma função que realmente avalia algo. É importante que o Mathematica continueu[v,w]
como está. No entanto, isso funciona na maioria dos casos, incluindo seu
é um número, uma sequência ou uma lista.Os créditos para esse truque vão para alefalpha - eu descobri isso em uma de suas respostas.
Se
x
for baseado em 1 e não em zero, use apenasou
Em alguns casos raros, você pode até usar o fato de que a multiplicação não é avaliada para alguns valores:
Observe, porém, que o Mathematica realmente reordenará os argumentos, de uma multiplicação se permanecer sem avaliação, portanto, o acima é idêntico a
fonte
Alternativas para
Length
Isso foi totalmente reescrito com algumas sugestões de LegionMammal978 e Misha Lavrov. Muito obrigado a ambos.
Em muitos casos,
Length
pode ser reduzido um pouco usandoTr
. A idéia básica é transformar a entrada em uma lista de1
s, para que aTr
soma seja igual à duração da lista.A maneira mais comum de fazer isso é usar
1^x
(para uma listax
). Isso funciona porquePower
éListable
e1^n
para a maioria dos valores atômicosn
é justo1
(incluindo todos os números, cadeias e símbolos). Portanto, já podemos salvar um byte com isso:Obviamente, isso pressupõe que
x
é uma expressão com maior precedência que^
.Se
x
contiver apenas0
s e1
s, podemos salvar outro byte usandoFactorial
(supondox
que a precedência seja maior que!
):Em alguns casos raros,
x
pode ter precedência menor do^
que a multiplicação, mas ainda maior. Nesse caso, ele também terá menor precedência do que@
, portanto, realmente precisamos comparar comLength[x]
. Um exemplo desse operador é.
. Nesses casos, você ainda pode salvar um byte com este formulário:Finalmente, algumas observações sobre que tipo de lista isso funciona:
Como mencionado na parte superior, isso funciona em listas simples contendo apenas números, seqüências de caracteres e símbolos. No entanto, ele também funcionará em algumas listas mais profundas, embora na verdade calcule algo ligeiramente diferente. Para uma matriz retangular n- D, use
Tr
fornece a menor dimensão (em oposição à primeira). Se você sabe que a dimensão mais externa é a mais curta, ou sabe que são todas iguais, asTr
expressões -existem aindaLength
.fonte
Length@x == Tr[1^x]
. Deve funcionar com a maioria das listas.Tr[x!]
vez deTr[1^x]
salvar um byte no caso especial em quex
apenas contém zeros e uns.Explore soluções recursivas - o Mathematica é multiparadigma, mas a abordagem funcional é geralmente a mais econômica.
NestWhile
pode ser uma solução muito compacta para pesquisar problemasNestWhileList
eFoldList
é poderosa quando você precisa retornar ou processar os resultados de iterações intermediárias.Map (/@)
,Apply (@@, @@@)
,MapThread
, E realmente tudo sobre o Wolfram Programação Funcional página de documentação é coisa potente.Formulário reduzido para incremento / decremento - por exemplo, em vez de
While[i<1,*code*;i++]
você pode fazerWhile[i++<1,*code*]
Não esqueça que você pode pré-incrementar / diminuir - por exemplo, em
--i
vez dei--
. Às vezes, isso pode economizar alguns bytes no código circundante, eliminando uma operação preparatória.Corolário de # 5 de David Carraher: Quando a mesma função é usada várias vezes, atribuir um símbolo a ela pode salvar bytes. Por exemplo, se você estiver usando
ToExpression
quatro vezes em uma solução,t=ToExpression
poderá usá-lot@*expression*
posteriormente. No entanto, antes de fazer isso, considere se a aplicação repetida da mesma função indica uma oportunidade para uma abordagem recursiva mais econômica.fonte
MapThread
muitas vezes pode ser substituído por\[Transpose]
. TIO .Não use
{}
se você estiver usando@@@
.Em alguns casos, você pode encontrar uma expressão como:
É possível reduzir bytes escrevendo:
Alternatives
tem uma precedência muito baixa, por isso geralmente é bom escrever expressões (uma exceção notável são funções puras; você pode usá-lo apenas no elemento mais à esquerda deAlternatives
).Observe que
f@@a|b|c
(em vez def@@{a,b,c}
) não funciona porqueApply
tem uma precedência maior queAlternative
.Nesse caso, você deve simplesmente usar
f@@{a,b,c}
.fonte
Apenas Mathematica 10
Formulários do operador
O Mathematica 10 suporta as chamadas "formas de operador", o que basicamente significa que algumas funções podem ser curry. Currying uma função é criar uma nova função, corrigindo um de seus operadores. Digamos, você está usando
SortBy[list, somereallylongfunction&]
muitoslist
s diferentes . Antes, você provavelmente teria atribuídoSortBy
as
ea função pura paraf
assimAgora você pode curry
SortBy
, o que significa que agora você pode fazerO mesmo funciona para um monte de outras funções, que levam um argumento lista ou função, incluindo (mas não limitado a)
Select
,Map
,Nearest
, etc.ybeltukov no Mathematica.SE conseguiu produzir uma lista completa dos seguintes :
Composição e composição correta
Existem novas abreviações para
Composition
(@*
) eRightComposition
(/*
). Um exemplo obviamente artificial, em que estes podem salvar caracteres, é visto nas três linhas equivalentes a seguirfonte
Não escreva funções com 0 argumentos
Não há necessidade de código como este:
Você pode simplesmente usar uma variável com
:=
para forçar a reavaliação do lado direito:Isso também significa que você pode alternar qualquer ação que você executa com freqüência (mesmo que seja apenas algo parecido
n++
) para um único caractere ao custo de 5 bytes. Então, no caso den++
ele pagar depois do quarto uso:fonte
Use
%
para obter uma variável livreEssa dica é aplicável apenas se o ambiente REPL do Mathematica puder ser assumido.
%
não está definido quando o código é executado como um script.Quando você puder usar os recursos do REPL, não faça isso:
Em vez disso, lembre-se de que o Mathematica armazena a última expressão avaliada (terminada por nova linha) em
%
:A nova linha adicionada custa um byte, mas você está economizando dois com a remoção
a=
. Portanto, no geral, isso economiza um byte.Em alguns casos (por exemplo, quando você deseja imprimir o valor de
a
qualquer maneira), pode até deixar de fora;
, salvando dois bytes:Um ou dois bytes podem parecer razoavelmente menores, mas esse é um caso importante, pois torna a extração de expressões repetidas (que é uma técnica muito comum) muito mais útil ao jogar golfe:
A técnica normal de extrair expressões repetidas custa quatro bytes de sobrecarga, que precisam ser salvos por outros usos da expressão. Aqui está uma tabela curta do número mínimo de usos de uma expressão (pelo comprimento da expressão) para extração em uma variável nomeada para salvar qualquer coisa:
Usando a variável sem nome, será possível salvar alguns bytes com muito mais frequência:
Eu não penso
%%
ou%n
posso ser usado para jogar golfe, porque se você não os usar pelo menos duas vezes, poderá colocar a expressão exatamente onde é necessário. E se você usá-lo duas vezes, o caractere adicional no nome da variável cancela a economia por omitir algunsx=
.fonte
Verificando se uma lista está classificada
Este é essencialmente um corolário dessa dica, mas é uma tarefa suficientemente comum que acho que merece sua própria resposta.
A maneira ingênua de verificar se uma lista está em ordem é usar
Podemos fazer um byte melhor com
No entanto, isso não funcionará se ainda não tivermos o que queremos verificar em uma variável. (Precisávamos de algo como o
Sort[a=...]==a
que é desnecessariamente longo.) No entanto, há outra opção:A melhor coisa é que isso pode ser usado para verificar se a entrada é classificada inversamente para a mesma contagem de bytes:
Mais um byte pode ser salvo se: a) sabemos que os elementos da lista são distintos eb) sabemos um limite inferior entre 0 e 9 (inclusive; ou limite superior para ordem inversa):
Para ver por que isso funciona, consulte "Sequências de argumentos" na dica vinculada na parte superior.
fonte
##>0&@@a
. Semelhante para o limite superior para classificado.Repetindo uma string
Em vez de
StringRepeat[str,n]
usar(0Range[n]+str)<>""
. Ou sestr
não depender de nenhum argumento de slot, o melhor éArray[str&,n]<>""
usar esta dica.fonte
StringRepeat[s,n+1]
usarArray[s&,n]<>s
(mesmo quando você já possuin+1
uma variável).Table[str,n]<>""
Se você precisar de uma lista de números ordenados ao contrário, não use
mas
para salvar seis bytes. A classificação por um valor negativo também é útil para
SortBy
cenários:fonte
-Sort@-x
?Você pode colar uma expressão na
Break
qual pode salvar um ou dois caracteres. Exemplo ( outros detalhes não são utilizados para maior clareza ):pode ser transformado em
para salvar um caractere. Se a expressão em questão não tiver precedência menor que o aplicativo de funções, você poderá salvar outro caractere:
pode ser transformado em
Embora não documentado, o argumento
Break
parece retornar ao loop circundante, o que pode potencialmente levar a ainda mais economia.fonte
Para remover todo o espaço em branco de uma string
s
, useOu seja, use
StringSplit
o padrão (dividido em componentes que não sejam espaços em branco) e simplesmente junte-os novamente. O mesmo provavelmente ainda é o mais curto se você quiser se livrar de qualquer outro caractere ou substring:fonte
Alternativas para
Range
Uma tarefa muito comum é aplicar algum tipo de função a todos os números de 1 a a
n
(geralmente dados como entrada). Existem essencialmente três maneiras de fazer isso (usando uma função de identidade sem nome como exemplo):Costumo optar pelo primeiro (por qualquer motivo), mas essa raramente é a melhor escolha.
Usando em
Array
vez dissoO exemplo acima mostra que o uso
Array
tem a mesma contagem de bytes. No entanto, tem a vantagem de ser uma expressão única. Em particular, se você quiser processar o resultado com uma função,f
poderá usar a notação de prefixo, que salva um byteRange
:Além disso, você pode omitir parênteses em torno de sua função sem nome, com a qual você pode precisar
Range
, por exemploSe você não quiser usá-lo mais (ou com um operador que tenha menor precedência), poderá escrever-
Array
se em notação de infixo e também salvar um byte:Portanto,
Array
é quase certamente melhor queRange
.Usando em
Table
vez dissoAgora, a tabela precisa compensar 3 bytes ou pelo menos 2 quando a notação infix é uma opção:
Quando não
Table
estiver usando notação infix, poderá omitir parênteses se sua função consistir em várias instruções:Isso ainda é mais longo, mas gera economia extra no caso mencionado abaixo.
A economia real deriva do fato de
Table
dar um nome à variável em execução não deve ser descartada. Freqüentemente, você terá funções anônimas aninhadas nas quais deseja usar a variável externa dentro de uma das funções internas. Quando isso acontece,Table
é mais curto queRange
:Você não apenas salva os caracteres para atribuir
i
, como também pode reduzir a função a uma única instrução no processo, o que permite o uso de notação infix sobre ela. Para referência,Array
também é mais longo neste caso, mas ainda menor queRange
:Quando você realmente usaria
Range
?Sempre que você não precisar de uma chamada de função para processar os valores, por exemplo, quando o mapeamento puder ser realizado por meio de uma operação vetorizada. Por exemplo:
Obviamente, também é mais curto se você não deseja mapear nenhuma função, por exemplo,
fonte
f/@Range[x]
regularmente ... #Encontrar o menor número que satisfaça uma condição
Algumas construções
i=1;While[cond[i],i++]
são boas como estão, mas há uma alternativa que é dois bytes mais curta:O código acima substitui repetidamente um número
i
pori+1
enquanto ele atende à condiçãocond[i]
. Nesse caso,i
começa em1
.Observe que o número máximo padrão de iterações é 2 ^ 16 (= 65536). Se você precisar de mais iterações do que isso,
While
seria melhor. (MaxIterations->∞
é muito longo)fonte
Avaliação de curto-circuito de abuso
Às vezes, você pode substituir
If
por um operador lógico.Por exemplo, digamos que você queira criar uma função que verifique se um número é primo e print
2*(number) - 1
é se for verdadeiro:É mais curto se você usar
&&
:Mesmo quando você tem várias expressões, ainda salva byte (s):
Você pode usar
||
para casos em que deseja que a condição sejaFalse
:Esses truques funcionam porque os operadores lógicos podem sofrer um curto-circuito ; o segundo argumento e, posteriormente, nem precisam ser expressões booleanas válidas.
Obviamente, isso não funcionará se você precisar do valor de retorno
If
ou quando precisar de argumentos verdadeiros e falsos deIf
.fonte
Aqui está uma lista com vários formulários de entrada do operador que podem reduzir muitas coisas. Algumas delas foram mencionadas em outros posts, mas a lista é longa e sempre me surpreendo ao descobrir algumas coisas novas por lá:
fonte
Usando
Optional (:)
Optional (:)
pode ser usado para expandir listas em substituições, sem precisar definir uma regra separada para a expansão.Esta resposta por mim e esta resposta por @ngenisis são exemplos.
Uso
A substituição acima usa primeiro o padrão
{p___, a_, b_, q___}
e encontra uma correspondência queb
atenda a uma determinada condição.Quando nenhuma correspondência é encontrada, ela é omitida
a_
e, em vez disso , é procurada{p___, b_, q___}
.a
não está incluído na pesquisa e Assume-se que o valor0
.Observe que a segunda pesquisa de padrões funcionaria apenas para
b
isso ocorrendo no início da lista; se umb
valor que satisfaz uma condição estiver no meio, então{p___, a_, b_, q___}
(que tem uma precedência mais alta) corresponderá a ele.A substituição é equivalente a anexar a
0
quandob
ocorre uma condição satisfatória no início da lista. (ou seja, não há necessidade de definir uma regra separada{b_, q___} /; cond[b] :> ...
)fonte
Saiba quando (e quando não) usar argumentos de função pura nomeados
Para código de golfe,
Function
argumentos puros são mais comumente referenciados usandoSlot
s; por exemplo,#
para o primeiro argumento,#2
para o segundo, etc. (veja esta resposta para mais detalhes).Em muitos casos, você desejará aninhar
Function
s. Por exemplo,1##&@@#&
é umFunction
que pega uma lista como seu primeiro argumento e gera o produto de seus elementos. Aqui está essa função emTreeForm
:Argumentos passados para o nível superior
Function
só pode preenchimentoSlot
s eSlotSequence
s presente no nível superior, que neste meio de caso que oSlotSequence
no interiorFunction
não terá qualquer maneira de acessar argumentos para o nível superiorFunction
.Em alguns casos, no entanto, convém que um
Function
aninhado em outroFunction
seja capaz de referenciar argumentos para o externoFunction
. Por exemplo, você pode querer algo comoArray[fun,...]&
, onde a funçãofun
depende de um argumento para o nível superiorFunction
. Para concretude, digamos quefun
deve dar ao restante do quadrado do seu módulo de entrada a entrada para o nível superiorFunction
. Uma maneira de conseguir isso é atribuir o argumento de nível superior a uma variável:Onde quer que
x
apareça no interiorFunction
Mod[#^2,x]&
, ele se referirá ao primeiro argumento para o exteriorFunction
, enquanto que#
se referirá ao primeiro argumento ao interiorFunction
. Uma abordagem melhor é usar o fato deFunction
ter uma forma de dois argumentos em que o primeiro argumento é um símbolo ou lista de símbolos que representará argumentos nomeados paraFunction
(em oposição aSlot
s sem nome ). Isso acaba poupando três bytes neste caso:
é o caractere de uso privado de três bytes queU+F4A1
representa o operador de infixo binário\[Function]
. Você também pode usar a forma binária deFunction
dentro de outraFunction
:Isso é equivalente ao acima. A razão é que, se você estiver usando argumentos nomeados, então
Slot
S eSlotSequences
são assumidos pertencer a próximaFunction
acima do qual não utiliza argumentos nomeados.Agora, apenas porque podemos aninhar
Function
s dessa maneira, não significa que devemos sempre. Por exemplo, se quisermos escolher os elementos de uma lista que são menores que a entrada, podemos ficar tentados a fazer algo como o seguinte:Na verdade, seria mais curto usar
Cases
e evitar a necessidade de um aninhadoFunction
inteiramente:fonte
Você pode salvar um byte por trabalhar em torno
Prepend
ouPrependTo
:ou
Infelizmente, isso não ajuda no mais comum
Append
, o que parece ser o equivalente mais curto de umArray.push()
em outros idiomas.fonte
Mathematica 10.2:
BlockMap
éPartition
+Map
Essa dica também pode ser intitulada "Leia as notas de versão, todas elas". (Para referência, aqui estão as notas de versão 10.2 e aqui da versão 10.3 de hoje .)
De qualquer forma, mesmo versões menores contêm diversos recursos novos, e um dos mais úteis (para jogar golfe) da versão 10.2 é a nova
BlockMap
função. Essencialmente combinaPartition
eMap
, o que é ótimo para os golfistas, porquePartition
é usado com bastante frequência e é um nome de função realmente irritantemente longo. A nova função não será reduzidaPartition
por si só, mas sempre que você quiser mapear uma função para as partições (o que provavelmente acontece com mais frequência), agora você pode salvar um ou dois bytes:A economia fica ainda maior quando a nova posição da função sem nome permite salvar alguns parênteses:
Infelizmente, não faço ideia por que não adicionei também
BlockApply
enquanto estavam lá ...Observe também que
BlockMap
não suporta o quarto parâmetro com o qual você pode usarPartition
para obter uma lista cíclica:fonte
Armazenando funções e expressões em uma variável
Se sua resposta acabar usando as mesmas funções ou expressões várias vezes, considere armazená-las em variáveis.
Se sua expressão é longa
l
e você a usan
vezes, normalmente usarial * n
bytes.No entanto, se você armazená-lo em uma variável de comprimento 1, levaria apenas
3 + l + n
bytes (ou2 + l + n
bytes, se você atribuir a variável aonde não precisaráCompoundExpression (;)
nem parênteses).Por exemplo, vamos considerar um problema simples, encontrando primos gêmeos menores que N.
Pode-se escrever esta solução de 54 bytes:
Neste exemplo, a função
PrimeQ
é usada três vezes.Ao atribuir
PrimeQ
um nome de variável, a contagem de bytes pode ser reduzida. Ambos são 48 bytes (54 - 6 bytes):fonte
Para obter uma lista crescente de valores-chave, use em
Sort
vez deSortBy
Para listas como
list = {{1, "world"}, {0, "universe"}, {2, "country"}}
, as três instruções a seguir são quase equivalentes.Combine
Select
eSortBy
Às vezes, precisamos escolher entradas de um conjunto maior e classificá-las para encontrar um mínimo / máximo. Sob algumas circunstâncias , duas operações podem ser combinadas em uma.
Por exemplo, no mínimo, as duas instruções a seguir são quase equivalentes.
e
1/0
éComplexInfinity
, que é "maior" que todos os números reais.Para uma lista de valores-chave, por exemplo:
fonte
Achatando um
Array
com##&
Ao usar uma Matriz multidimensional para calcular uma lista de resultados que precisam ser nivelados, use
##&
como o quarto argumento. Isso substitui as cabeças da matriz por##&
(equivalente aSequence
) em vez deList
, portanto, o resultado final será um (plano)Sequence
de resultados.Em duas dimensões, compare
Obviamente,
Join@@Array[f,dims]
ainda são 2 (ou 3, se a notação infix puder ser usada) bytes menores que{Array[f,dims,1,##&]}
.Em três ou mais dimensões,
{Array[f,dims,origin,##&]}
é sempre menor que a alternativa, mesmo que a origem seja 1.fonte
Valores padrão
Os valores padrão lidam com argumentos de padrão ausentes de maneira eficiente. Por exemplo, se quisermos correspondência de padrões
Exp[c_*x]
em uma regra para qualquer valor dec
, a ingênuausa muito mais bytes do que se usarmos o valor padrão
c
sempre que estiver ausente:O uso de um padrão é indicado com um ponto após o padrão:
c_.
.Os valores padrão estão associados às operações: no exemplo acima, a operação está
Times
inseridac_.*x
e,c_
portanto , um valor ausente é obtido do valor padrão associado aTimes
, que é 1. ParaPlus
, o valor padrão é 0:Para
Power
expoentes, o padrão é 1:fonte