Quels conseils généraux avez-vous pour jouer au golf dans Mathematica? Je recherche des idées pouvant être appliquées aux problèmes de code de golf en général, qui soient au moins quelque peu spécifiques à Mathematica (par exemple, "supprimer les commentaires" n'est pas une réponse).
(Norm[#-#2]&)
au lieu deEuclideanDistance
.Certaines fonctions intégrées avec des noms longs peuvent être remplacées par des expressions plus courtes.
Par exemple:
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
sin
est un nombreDivisible[n,m]
=>m∣n
FromDigits[n,2]
=>Fold[#+##&,n]
ifn
est une liste de0
s et1
sComplex@z
=>{1,I}.z
oùz
est une liste du formulaire{x,y}
la source
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
astuceFromDigits
fonctionne aussi pour n'importe quelle autre base sauf10
. Par exempleFromDigits[n,5]
->Fold[4#+##&,n]
(avec le bonus de sauvegarder un octet supplémentaire pour les bases100
et1000
).U+F3C7
.Echo
soit une option, car cela imprime>>
(et un espace) sur STDOUT avant d’imprimer la chaîne réelle.Complex[x,y] => {1,I}.{x,y}
, je pense quex+y*I
c'est beaucoup plus court avec le même effet?Listes avec des valeurs répétées
C'est un vecteur commun avec lequel travailler:
Il s'avère que cela peut être raccourci par un octet:
Encore plus d'octets sont enregistrés si le vecteur est plus long que deux zéros. Ceci peut également être utilisé pour initialiser des matrices nulles, par exemple, ce qui suit donne une matrice 2x2 de zéros:
Ceci peut également être utilisé pour des valeurs non nulles si elles sont suffisamment grandes ou suffisamment nombreuses ou négatives. Comparez les paires suivantes:
Mais rappelez-vous qu'à partir de 6 valeurs, il vaut mieux
1~Table~6
dans ce cas (potentiellement plus tôt, en fonction des exigences de priorité).La raison pour laquelle cela fonctionne est que cela
,
introduit deux arguments dans la liste, mais les arguments omis (n'importe où dans Mathematica) sont desNull
s implicites . En outre, la multiplication estListable
, et0*x
est0
pour presque toutx
(sauf pour des choses commeInfinity
etIndeterminate
), alors voici ce qui se passe:Pour les listes de
1
s, vous pouvez utiliser une astuce similaire en utilisant des règles d’exponentiation. Il existe deux manières différentes de sauvegarder des octets si vous avez au moins trois1
secondes dans la liste:la source
1^{,,,}
un octet est inférieur à0{,,,}+1
.{,,}^0
. Je vais éditer le post.Connaissez vos arguments de fonction purs
Lorsque vous jouez au code de golf, vous utiliserez souvent une approche fonctionnelle, consistant à utiliser des fonctions anonymes (pures) avec une
&
syntaxe abrégée. Il y a beaucoup de façons d'accéder aux arguments d'une telle fonction, et vous pouvez souvent supprimer quelques octets en ayant une bonne compréhension des possibilités.Accéder à des arguments simples
Vous le savez probablement si vous avez déjà utilisé des fonctions pures. Le n ième argument est appelé
#n
, et#
agit comme un alias pour#1
. Donc, si, par exemple, vous voulez écrire une fonction qui prenne comme paramètres une autre fonction et son argument (pour passer l'argument à cette fonction), utilisezCela ne fonctionne pas avec les nombres négatifs (tels que ceux que vous pourriez utiliser pour accéder aux listes).
Accès aux arguments nommés (nouveauté V10)
L’une des nouvelles fonctionnalités majeures de Mathematica 10 est
Association
s, qui sont essentiellement des mappes clé-valeur avec des types de clé arbitraires, écrits comme suit:Si une telle association est passée en tant que premier argument à une fonction pure, vous pouvez accéder à certains si ses arguments en tant que paramètres nommés:
Notez que
#
fait toujours référence à toute l'association comme prévu. Pour que les paramètres nommés fonctionnent, les clés doivent être des chaînes (cela ne fonctionnera pas si vous utilisez des variables non définies, par exemple), et ces chaînes doivent commencer par une lettre et ne contenir que des lettres et des chiffres.Le "soi" argument
#0
Une fonctionnalité moins connue est celle qui
#0
existe également et vous donne l'objet fonction lui-même. Cela peut être vraiment utile dans les quines et les quines généralisées. En fait, la quine la plus courte de Mathematica (à ma connaissance) estCe qui est légèrement ennuyeux, c'est que cela ne vous donnera pas les caractères exacts que vous avez entrés. Par exemple si utilisation
@
pour une application de fonction, il restera rendu en tant que[...]
et des espaces seront insérés à certains endroits. La quine sera généralement un peu plus longue que vous ne le voudriez, mais cela fonctionnera toujours, en jouant d'abord sur la quine, puis en copiant simplement sa sortie - qui devrait maintenant être une vraie quine.Outre quines, cela signifie également que vous pouvez écrire du code récursif sans avoir à nommer votre fonction. Comparez ces trois implémentations de Fibonacci (naïves mais golfées):
Séquences d'arguments
Maintenant, c’est là que commence la vraie magie. Les séquences ne sont pas souvent utilisées dans le golf, parce que
Sequence
c'est un nom trop long pour qu'il en vaille la peine la plupart du temps. Mais dans les fonctions pures, c'est là où elles brillent. Si vous n'êtes pas familier avec les séquences, elles ressemblent fondamentalement aux splats dans d'autres langues. Si vous utilisez une séquence dans uneList
liste d'arguments ou une liste d'arguments d'une fonction, ses éléments seront automatiquement développés dans des emplacements distincts. AlorsMaintenant, dans les fonctions pures
##
ou##1
est une séquence de tous les arguments. De même,##2
est une séquence de tous les arguments commençant à partir du deuxième,##3
tous les arguments commençant à partir du troisième, etc. Ainsi, pour commencer, nous pouvons simplement réimplémenterSequence
en##&
économisant 5 octets. À titre d'exemple d'utilisation, cela nous fournit une alternative àJoin@@list
(voir cette astuce ), qui ne sauvegarde aucun octet, mais qui est bon à savoir de toute façon:Cela aplatit efficacement le premier niveau d'une liste imbriquée. Que pouvons-nous faire avec ça? Voici une alternative plus courte de 2 octets à
RotateLeft
:Rien que pour ces choses, il convient de garder cette caractéristique à l’esprit. Cependant, nous pouvons faire mieux! Les séquences deviennent vraiment intéressantes quand on considère que les opérateurs sont réellement implémentés en tant que fonctions sous le capot. Par exemple
a+b
évalue àPlus[a,b]
. Donc, si nous donnons à cela une séquence ...Cette astuce a été utilisée dans cette astuce pour enregistrer un octet sur
Times
, car la juxtaposition n’est techniquement qu’un opérateur:Vous pouvez également l'utiliser pour enregistrer un octet
Unequal
si vous avez une valeur à caractère unique ou une variable dont vous savez qu'elle ne figure pas dans vos arguments (N
fonctionnera probablement dans 99% des cas):Cela devient encore plus intéressant avec les opérateurs unaires
-
et/
- les deux derniers sont en réalité mis en œuvre en termes de multiplication et d’exponentiation. Voici une liste de choses que vous pouvez faire, où la dernière colonne suppose que la fonction a reçu les argumentsa, b, c
:D' autres opérateurs sont communs
!=
,==
,&&
,||
. Les moins communes à garder à l' esprit sont|
,@*
,/*
. Pour conclure, voici un petit bonus:Continuez à expérimenter avec ceux-ci et faites-moi savoir si vous trouvez d'autres applications utiles ou particulièrement intéressantes!
la source
Sqrt@2
ou2^.5
=>√2
a[[1]]
=>a〚1〛
#+#2&
=>+##&
Flatten@a
=>Join@@a
(parfois)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
la source
〚
et〛
Opérateurs en tant que fonctions
Inspiré par la récente découverte de Dennis par Julia, je pensais que je devrais examiner cela pour Mathematica. Je savais que Mathematica définissait un grand nombre d'opérateurs inutilisés, mais je n'y avais jamais prêté attention.
Pour référence, la liste de tous les opérateurs peut être trouvée ici sous la forme d'un tableau de priorité. Le triangle dans la dernière colonne indique si cet opérateur a une signification intégrée ou non. Bien que tous ceux qui ne le sont pas ne puissent pas être définis facilement, la plupart d’entre eux le peuvent.
De manière pratique, il existe deux opérateurs inutilisés avec un point de code inférieur à 256, de sorte qu'ils peuvent être utilisés comme octets simples dans un fichier source codé ISO 8859-1:
±
(0xB1) peut être utilisé comme opérateur préfixe unaire ou comme opérateur infixe binaire.·
(0xB7) peut être utilisé comme opérateur d'infixe variadique ou n-aire, pour n> 2.Il y a cependant un autre inconvénient: pour une raison étrange lorsque vous définissez ces opérateurs, vous avez besoin d'un espace devant eux, sinon Mathematica essaie d'analyser une multiplication. Lorsque vous les utilisez, vous n'avez pas besoin d'espaces:
Comparez ceci avec:
Donc, cela enregistre un octet lors de la définition de la fonction et deux octets lors de son utilisation. Notez que la définition de
·
ne permettra pas d'économiser des octets pour quatre opérandes et commencera à coûter des octets pour plus d'opérandes, mais que l'utilisation pourra toujours économiser des octets, en fonction de la priorité des opérateurs utilisés dans les arguments. Il est également bon de noter que vous pouvez définir à moindre coût une fonction variadique qui peut ensuite être appelée beaucoup plus efficacement:Mais notez qu'il est difficile d'appeler ces fonctions variadiques avec un seul argument. (Vous pouvez faire
CenterDot[x]
ou##&[]·x
si vous en avez réellement besoin, il y a de fortes chances que vous ayez une solution différente.)Bien sûr, cela ne sauvegarde rien pour les solutions où une fonction non nommée suffit, mais vous devez parfois définir des fonctions d'assistance pour une utilisation ultérieure, et parfois il est plus court de définir des fonctions nommées, par exemple pour configurer différentes définitions pour différents paramètres. Dans ces cas, utiliser plutôt un opérateur peut économiser une quantité décente d'octets.
Notez que l'utilisation de ces fichiers codés ISO 8859-1 nécessite
$CharacterEncoding
une valeur compatible, telle que la valeur par défaut de WindowsWindowsANSI
. Sur certains systèmes, cette valeur par défautUTF-8
ne permet pas de lire ces points de code à partir d’un seul octet.la source
Choisir des valeurs basées sur un entier
L'approche naïve de choisir entre
y
etz
, selon quex
est0
ou1
estCependant, il existe un moyen plus court:
Cela fonctionne parce que
[[0]]
donne laHead
d'une expression, dans ce casy
, alors[[1]]
donne juste le premier élément - dans ce cas , le premier argument,z
.Vous pouvez même l'utiliser pour choisir entre plus de deux valeurs:
Notez que cela ne fonctionnera pas si
u
c'est une fonction qui évalue quelque chose. Il est important que Mathematica conserve la situation actuelleu[v,w]
. Cependant, cela fonctionne dans la plupart des cas, y compris s'ilu
s'agit d'un nombre, d'une chaîne ou d'une liste.Les crédits pour cette astuce vont à Alephalpha - j'ai découvert cela dans l'une de ses réponses.
Si
x
est basé sur 1 au lieu de zéro, utilisez simplementou
Dans de rares cas, vous pouvez même utiliser le fait que la multiplication n'est pas évaluée pour certaines valeurs:
Notez cependant que Mathematica réorganisera en réalité les arguments d’une multiplication si elle n’est pas évaluée, ce qui est identique à ce qui précède.
la source
Alternatives à
Length
Cela a été entièrement réécrit avec quelques suggestions de LegionMammal978 et Misha Lavrov. Un grand merci à tous les deux.
Dans de nombreux cas,
Length
peut être un peu raccourci en utilisantTr
. L’idée de base est de transformer l’entrée en une liste de1
s, de sorte queTr
résumer, qui seront alors égaux à la longueur de la liste.Le moyen le plus courant consiste à utiliser
1^x
(pour une listex
). Cela fonctionne carPower
c’est justeListable
et1^n
pour la plupart des valeurs atomiques (y compris tous les nombres, chaînes et symboles). Nous pouvons donc déjà économiser un octet avec ceci:n
1
Bien entendu, cela suppose qu’il
x
s’agit d’une expression ayant une priorité plus élevée que^
.Si
x
ne contient que0
s et1
s, nous pouvons enregistrer un autre octet en utilisantFactorial
(en supposantx
que la priorité est supérieure à!
):Dans de rares cas,
x
la préséance peut être inférieure^
à la multiplication, mais néanmoins supérieure. Dans ce cas, la préséance sera également inférieure à celle de@
, nous avons donc vraiment besoin de comparerLength[x]
. Un exemple d'un tel opérateur est.
. Dans ces cas, vous pouvez toujours enregistrer un octet avec ce formulaire:Enfin, quelques remarques sur le type de listes sur lesquelles cela fonctionne:
Comme indiqué en haut, cela fonctionne sur des listes non hiérarchiques contenant uniquement des nombres, des chaînes et des symboles. Cependant, cela fonctionnera également sur des listes plus profondes, bien qu'il calcule en réalité quelque chose de légèrement différent. Pour un tableau rectangulaire n- D, utiliser
Tr
vous donne la dimension la plus courte (par opposition à la première). Si vous savez que la dimension la plus extérieure est la plus courte, ou si vous savez qu'elles sont toutes identiques, lesTr
expressions -express sont toujours équivalentesLength
.la source
Length@x == Tr[1^x]
. Devrait fonctionner avec la plupart des listes.Tr[x!]
au lieu deTr[1^x]
pour sauvegarder un octet dans le cas spécial oùx
ne contient que des zéros et des uns.Explorer des solutions récursives - Mathematica est multi-paradigme, mais l'approche fonctionnelle est souvent la plus économique.
NestWhile
peut être une solution très compacte aux problèmes de rechercheNestWhileList
etFoldList
est puissant lorsque vous devez renvoyer ou traiter les résultats d'itérations intermédiaires.Map (/@)
,Apply (@@, @@@)
,MapThread
, Et vraiment tout sur Wolfram fonctionnelle Programmation page de documentation est une chose puissante.Forme abrégée pour incrémenter / décrémenter - Par exemple, à la place de ce que
While[i<1,*code*;i++]
vous pouvez faireWhile[i++<1,*code*]
N'oubliez pas que vous pouvez effectuer une pré-incrémentation / décrémentation - par exemple,
--i
au lieu dei--
. Cela peut parfois vous faire économiser quelques octets dans le code environnant en éliminant une opération préparatoire.Corollaire au n ° 5 de David Carraher: lorsque la même fonction est utilisée à plusieurs reprises, lui attribuer un symbole peut économiser des octets. Par exemple, si vous utilisez
ToExpression
4 fois dans une solution,t=ToExpression
vous permet de l'utilisert@*expression*
par la suite. Toutefois, avant de procéder ainsi, déterminez si l'application répétée de la même fonction indique une possibilité d'adopter une approche récursive plus économique.la source
MapThread
peut souvent être remplacé par\[Transpose]
. TIO .Ne pas utiliser
{}
si vous utilisez@@@
.Dans certains cas, vous pouvez rencontrer une expression telle que:
Il est possible de réduire les octets en écrivant:
Alternatives
a une priorité très faible, il est donc généralement acceptable d'écrire des expressions (une exception notable étant les fonctions pures; vous ne pouvez l'utiliser que dans l'élément le plus à gauche deAlternatives
).Notez que
f@@a|b|c
(au lieu def@@{a,b,c}
) ne fonctionne pas carApply
a une priorité plus élevée queAlternative
.Dans ce cas, vous devriez simplement utiliser
f@@{a,b,c}
.la source
Mathematica 10 uniquement
Formulaires d'opérateur
Mathematica 10 prend en charge les "formes d'opérateur", ce qui signifie que certaines fonctions peuvent être curry. Currying une fonction est de créer une nouvelle fonction en fixant l'un de ses opérateurs. Dis, tu utilises
SortBy[list, somereallylongfunction&]
beaucoup de choses différenteslist
. Avant, vous auriez probablement assignéSortBy
às
et la fonction pure àf
tantMaintenant, vous pouvez curry
SortBy
, ce qui signifie que vous pouvez maintenant faireLes mêmes œuvres pour beaucoup d'autres fonctions qui prennent un argument de liste ou de la fonction, y compris (mais sans s'y limiter)
Select
,Map
,Nearest
, etc.ybeltukov sur Mathematica.SE a été en mesure de produire une liste complète de ces - :
Composition et RightComposition
Il y a de nouveaux raccourcis pour
Composition
(@*
) etRightComposition
(/*
). Un exemple évidemment artificiel où ceux-ci peuvent sauver des caractères est vu dans les trois lignes équivalentes suivantesla source
Ne pas écrire des fonctions à 0 argument
Il n'y a pas besoin de code comme celui-ci:
Vous pouvez simplement utiliser une variable avec
:=
pour forcer la réévaluation du côté droit:Cela signifie également que vous pouvez aliaser n'importe quelle action que vous effectuez souvent (même si c'est quelque chose du genre
n++
) avec un seul caractère au prix de 5 octets. Donc, dans le cas oùn++
cela rapporte après la quatrième utilisation:la source
Utiliser
%
pour obtenir une variable libreCe conseil ne s'applique que si l'environnement REPL de Mathematica peut être supposé.
%
n'est pas défini lorsque le code est exécuté en tant que script.Lorsque vous pouvez utiliser les fonctionnalités REPL, ne faites pas ceci:
N'oubliez pas que Mathematica stocke la dernière expression évaluée (terminée par une nouvelle ligne) dans
%
:La nouvelle ligne ajoutée coûte un octet, mais vous en économisez deux en supprimant
a=
, donc globalement, cela enregistre un octet.Dans certains cas (par exemple, lorsque vous souhaitez imprimer la valeur de
a
toute façon), vous pouvez même laisser la;
, en sauvegardant deux octets:Un ou deux octets peuvent sembler assez mineurs, mais il s'agit d'un cas important, car il rend l'extraction d'expressions répétées (technique très courante) beaucoup plus utile lors de la pratique du golf:
La technique normale d'extraction d'expressions répétées coûte quatre octets de surcharge, qui doivent être sauvegardés par d'autres utilisations de l'expression. Voici un court tableau du nombre minimum d'utilisations d'une expression (par la longueur de l'expression) à extraire dans une variable nommée pour enregistrer quoi que ce soit:
En utilisant la variable non nommée, il sera possible de sauvegarder quelques octets beaucoup plus souvent:
Je ne pense pas
%%
ou%n
ne peux pas être utilisé pour jouer au golf, car si vous ne les utilisez pas au moins deux fois, vous pouvez simplement mettre l'expression là où elle est nécessaire. Et si vous l'utilisez deux fois, le caractère supplémentaire dans le nom de la variable annule les économies réaliséesx=
.la source
Vérifier si une liste est triée
C’est essentiellement un corollaire de cette astuce, mais c’est une tâche suffisamment commune pour que je pense qu’elle mérite sa propre réponse.
Le moyen naïf de vérifier si une liste est en ordre est d'utiliser
On peut mieux faire un octet avec
Cependant, cela ne fonctionne pas si nous ne disposons pas de la chose que nous voulons déjà archiver dans une variable. (Nous aurions besoin de quelque chose comme
Sort[a=...]==a
ce qui est inutilement long.) Cependant, il existe une autre option:La meilleure chose à faire est que cela peut être utilisé pour vérifier si l'entrée est triée de manière inverse pour le même nombre d'octets:
Un octet supplémentaire peut être sauvegardé si a) nous savons que les éléments de la liste sont distincts et b) nous connaissons une limite inférieure comprise entre 0 et 9 (inclus; ou une limite supérieure pour un ordre de tri inversé):
Pour voir pourquoi cela fonctionne, consultez "Séquences d'arguments" dans l'info-bulle liée en haut.
la source
##>0&@@a
. Semblable pour la limite supérieure pour trié.Répéter une chaîne
Au lieu d'
StringRepeat[str,n]
utiliser(0Range[n]+str)<>""
. Ou sistr
ne dépend d'aucun argument de slot, le mieux estArray[str&,n]<>""
de suivre cette astuce.la source
StringRepeat[s,n+1]
utiliséArray[s&,n]<>s
(même si vous avez déjàn+1
une variable).Table[str,n]<>""
Si vous avez besoin d’une liste de numéros triée en ordre inverse, n’utilisez pas
mais
pour économiser six octets. Le tri par valeur négative est également utile pour les
SortBy
scénarios:la source
-Sort@-x
?Vous pouvez coller une expression dans
Break
laquelle vous pouvez enregistrer un ou deux caractères. Exemple ( autres détails non détaillés pour plus de clarté ):peut être transformé en
pour sauvegarder un personnage. Si l'expression en question n'a pas une priorité inférieure à celle de l'application de la fonction, vous pouvez même enregistrer un autre caractère:
peut être transformé en
Bien que non documenté, l'argument à
Break
semble être renvoyé par la boucle environnante, ce qui peut potentiellement permettre de réaliser encore plus d'économies.la source
Pour supprimer tous les espaces d'une chaîne
s
, utilisezAutrement dit, utilisez
StringSplit
la valeur par défaut (divisée en composants non blancs) et reliez-les simplement. La même chose est probablement toujours la plus courte si vous voulez vous débarrasser de tout autre caractère ou sous-chaîne:la source
Alternatives à
Range
Une tâche très courante consiste à appliquer une sorte de fonction à tous les nombres de 1 à a
n
(généralement donnés en entrée). Il y a essentiellement 3 façons de faire cela (en utilisant une fonction d'identité non nommée comme exemple):J'ai tendance à aller pour le premier (pour une raison quelconque), mais c'est rarement le meilleur choix.
Utiliser à la
Array
placeL'exemple ci-dessus montre que l'utilisation
Array
a le même nombre d'octets. Cependant, il a l'avantage d'être une expression unique. En particulier, si vous souhaitez continuer à traiter le résultat avec une fonction,f
vous pouvez utiliser la notation préfixe, qui enregistre un octet surRange
:De plus, vous pourrez peut-être omettre les fonctions non nommées dont vous auriez peut-être besoin entre parenthèses
Range
, par exemple:Si vous ne voulez plus l'utiliser (ou avec un opérateur moins prioritaire), vous pouvez plutôt écrire
Array
lui-même en notation infixe et sauvegarder également un octet:Par conséquent,
Array
est presque certainement meilleur queRange
.Utiliser à la
Table
placeMaintenant, la table doit compenser 3 octets, ou au moins 2 lorsque la notation infixe est une option:
Lorsque vous n'utilisez pas la notation infixe,
Table
vous pouvez éventuellement omettre les parenthèses si votre fonction est composée de plusieurs instructions:C'est encore plus long, mais donne des économies supplémentaires avec dans le cas mentionné ci-dessous.
Les économies réelles proviennent du fait que
Table
la variable en cours d’exécution ne doit pas être ignorée. Vous aurez souvent des fonctions imbriquées non nommées dans lesquelles vous souhaitez utiliser la variable externe à l'intérieur de l'une des fonctions internes. Lorsque cela se produit,Table
est plus court queRange
:Non seulement vous enregistrez les caractères à affecter
i
, mais vous pouvez également réduire la fonction à une seule instruction du processus, ce qui vous permet d'utiliser la notation infixe par-dessus. Pour référence,Array
est également plus long dans ce cas, mais toujours plus court queRange
:Quand utiliseriez-vous réellement
Range
?Chaque fois que vous n'avez pas besoin d'un appel de fonction pour traiter les valeurs, par exemple lorsque le mappage peut être effectué via une opération vectorisée. Par exemple:
Bien sûr, il est également plus court si vous ne souhaitez pas mapper une fonction du tout, par exemple
la source
f/@Range[x]
régulièrement ...Trouver le plus petit nombre qui satisfait une condition
Certains types de construction
i=1;While[cond[i],i++]
sont corrects tels quels, mais il existe une alternative plus courte de deux octets:Le code ci-dessus remplace à plusieurs reprises un numéro
i
pari+1
tant qu'il remplit la conditioncond[i]
. Dans ce cas,i
commence à1
.Notez que le nombre maximum d'itérations par défaut est 2 ^ 16 (= 65536). Si vous avez besoin de plus d'itérations,
While
cela serait mieux. (MaxIterations->∞
est trop long)la source
Abuser de court-circuit d'évaluation
Vous pouvez parfois remplacer
If
par un opérateur logique.Par exemple, supposons que vous souhaitiez créer une fonction qui vérifie si un nombre est premier et que l’impression l’
2*(number) - 1
est si c’est vrai:C'est plus court si vous utilisez
&&
plutôt:Même si vous avez plusieurs expressions, vous enregistrez toujours le (s) octet (s):
Vous pouvez utiliser
||
pour les cas où vous souhaitez que la condition soitFalse
:Ces astuces fonctionnent parce que les opérateurs logiques peuvent être court-circuités ; le deuxième argument et par la suite n'ont même pas besoin d'être des expressions booléennes valides.
Bien sûr, cela ne fonctionne pas si vous avez besoin de la valeur de retour
If
ou lorsque vous avez besoin des arguments Trueity et Falsy deIf
.la source
Voici une liste avec des charges de formulaires de saisie d'opérateur pouvant raccourcir beaucoup de choses. Certains d'entre eux ont été mentionnés dans d'autres publications, mais la liste est longue et je suis toujours surpris de trouver quelques nouveautés:
la source
En utilisant
Optional (:)
Optional (:)
peut être utilisé pour développer des listes dans des remplacements, sans avoir à définir une règle distincte pour le développement.Cette réponse de moi et cette réponse de @ngenisis sont des exemples.
Usage
Le remplacement ci-dessus utilise d’abord le motif
{p___, a_, b_, q___}
et trouve une correspondance quib
répond à une certaine condition.Lorsqu'aucune correspondance de ce type n'est trouvée, elle est omise
a_
et recherchée à la place{p___, b_, q___}
.a
n'est pas inclus dans la recherche et est supposé avoir la valeur0
.Notez que la deuxième recherche de modèle ne fonctionne que pour
b
que qui se produit au début de la liste; si uneb
valeur remplissant une condition est au milieu, alors{p___, a_, b_, q___}
(qui a une priorité plus élevée) lui correspondra à la place.Le remplacement équivaut à ajouter un préfixe
0
lorsqu'uneb
condition satisfaisante est remplie au début de la liste. (c.-à-d. qu'il n'est pas nécessaire de définir une règle séparée,{b_, q___} /; cond[b] :> ...
)la source
Savoir quand (et quand non) utiliser des arguments de fonction purs nommés
Pour le golf de code, les
Function
arguments purs sont le plus souvent référencés en utilisantSlot
s; par exemple#
pour le premier argument,#2
pour le second, etc. (voir cette réponse pour plus de détails).Dans de nombreux cas, vous voudrez imbriquer des
Function
s. Par exemple,1##&@@#&
est unFunction
qui prend une liste comme premier argument et génère le produit de ses éléments. Voici cette fonction dansTreeForm
:Les arguments passés au niveau supérieur
Function
ne peuvent remplir que les élémentsSlot
s etSlotSequence
s présents au niveau supérieur, ce qui signifie que, dans ce cas,SlotSequence
les éléments internesFunction
ne disposeront d'aucun moyen d'accéder aux arguments du niveau supérieurFunction
.Dans certains cas, cependant, vous pouvez souhaiter qu'un
Function
imbriqué dans un autreFunction
puisse référencer des arguments à l'extérieurFunction
. Par exemple, vous pouvez vouloir quelque chose commeArray[fun,...]&
, où la fonctionfun
dépend d'un argument au plus haut niveauFunction
. Pour être concret, supposons que celafun
donne le reste du carré de son entrée modulo l’entrée au niveau supérieurFunction
. Une façon d'accomplir ceci est d'affecter l'argument de niveau supérieur à une variable:Où que ce soit
x
à l'intérieurFunction
Mod[#^2,x]&
, cela fera référence au premier argument à l'extérieurFunction
, alors que#
fera référence au premier argument à l'intérieurFunction
. Une meilleure approche consiste à utiliser le fait quiFunction
a une forme à deux arguments, le premier argument étant un symbole ou une liste de symboles qui représentera des arguments nommés àFunction
(par opposition à des noms non nommésSlot
). Cela finit par nous sauver trois octets dans ce cas:
est le caractère d'utilisation privée sur trois octetsU+F4A1
représentant l'opérateur infixe binaire\[Function]
. Vous pouvez également utiliser la forme binaire deFunction
dans un autreFunction
:Ceci est équivalent à ce qui précède. La raison en est que, si vous utilisez des arguments nommés, alors
Slot
s etSlotSequences
sont supposés appartenir à nextFunction
qui n’utilise pas d’arguments nommés.Maintenant
Function
, ce n'est pas parce que nous pouvons faire la nidification de cette manière que nous devrions toujours le faire. Par exemple, si nous souhaitons sélectionner les éléments d’une liste inférieurs à l’entrée, nous pourrions être tentés de procéder de la manière suivante:Il serait en fait plus court d’utiliser
Cases
et d’éviter la nécessité d’un nichéFunction
complet:la source
Vous pouvez enregistrer un octet en travaillant autour
Prepend
ouPrependTo
:ou
Malheureusement, cela n’aide en rien le plus courant
Append
, qui semble être l’équivalent le plus court de unArray.push()
dans d’autres langues.la source
Mathematica 10.2:
BlockMap
estPartition
+Map
Cette astuce pourrait également s'intituler "Lisez les notes de version, toutes". (Pour référence, voici les notes de publication de 10.2 et de la version 10.3 d’aujourd’hui .)
Quoi qu'il en soit, même les versions mineures contiennent une multitude de nouvelles fonctionnalités, et l'une des plus utiles (pour le golf) à partir de 10.2 est la nouvelle
BlockMap
fonction. Il combine essentiellementPartition
etMap
, ce qui est excellent pour les golfeurs, car ilPartition
est utilisé assez souvent, et c’est un nom de fonction vraiment ennuyeux. La nouvelle fonction ne se raccourcira pasPartition
d'elle-même, mais chaque fois que vous souhaitez mapper une fonction sur les partitions (ce qui arrive probablement plus souvent qu'autrement), vous pouvez maintenant enregistrer un octet ou deux:Les économies deviennent encore plus importantes lorsque la nouvelle position de la fonction non nommée vous permet de vous épargner quelques parenthèses:
Malheureusement, je ne sais pas pourquoi n'a pas aussi ajouté
BlockApply
pendant qu'ils y étaient ...Notez également que
BlockMap
ne prend pas en charge le 4ème paramètre que vous pouvez utiliserPartition
pour obtenir une liste cyclique:la source
Stocker des fonctions et des expressions dans une variable
Si votre réponse finit par utiliser les mêmes fonctions ou expressions plusieurs fois, vous pouvez envisager de les stocker dans des variables.
Si votre expression est longue
l
et que vous l'utilisezn
fois, elle utilisera normalement plus d'l * n
octets.Cependant, si vous la stockez dans une variable de longueur 1, cela ne prend que des
3 + l + n
octets (ou des2 + l + n
octets, si vous affectez la variable sans utiliser deCompoundExpression (;)
parenthèses).Par exemple, considérons un problème simple, trouver des nombres premiers jumeaux inférieurs à N.
On pourrait écrire cette solution de 54 octets:
Dans cet exemple, la fonction
PrimeQ
est utilisée trois fois.En attribuant
PrimeQ
un nom de variable, le nombre d'octets peut être réduit. 48 octets (54 à 6 octets) sont les deux suivants:la source
Pour obtenir une liste de valeurs-clés croissante, utilisez
Sort
plutôt queSortBy
Pour les listes telles que
list = {{1, "world"}, {0, "universe"}, {2, "country"}}
, les trois déclarations suivantes sont presque équivalentes.Combiner
Select
etSortBy
Parfois, nous devons sélectionner des entrées dans un ensemble plus grand et les trier pour trouver un minimum / maximum. Dans certaines circonstances , deux opérations pourraient être combinées en une seule.
Par exemple, pour un minimum, les deux déclarations suivantes sont presque équivalentes.
et
1/0
estComplexInfinity
, qui est "plus grand" que tous les nombres réels.Pour une liste de valeurs-clés, par exemple:
la source
Résoudre et Réduire: liste automatique de variables
Lorsque la liste des variables pour
Solve
etReduce
est omise, elles résolvent toutes les variables libres dans la ou les expressions. Exemples:Particulièrement
Solve
sur leIntegers
,NonNegativeIntegers
etPositiveIntegers
est extrêmement puissant pour les problèmes de dénombrement.la source
Les valeurs par défaut
Les valeurs par défaut traitent les arguments de modèle manquants de manière efficace. Par exemple, si nous voulons appliquer une correspondance de modèle
Exp[c_*x]
à une règle pour n’importe quelle valeur dec
, le naïfutilise beaucoup plus d'octets que si nous utilisions la valeur par défaut
c
chaque fois qu'elle est manquante:L'utilisation d'un défaut est indiqué par un point après le modèle:
c_.
.Les valeurs par défaut sont associées aux opérations: dans l'exemple ci-dessus, l'opération est
Times
en coursc_.*x
et une valeur manquante pourc_
est donc extraite de la valeur par défaut associée àTimes
, qui est 1. PourPlus
, la valeur par défaut est 0:Pour les
Power
exposants, la valeur par défaut est 1:la source