GolfScript obtient trop souvent son propre chemin et je pense qu'un répertoire de conseils pratiques pour jouer au golf en J pourrait aider dans la lutte contre l'empire du mal. Quels conseils avez-vous pour raccourcir ce langage déjà laconique?
Pour ceux qui souhaitent apprendre J, le point de départ évident est le site jsoftware et en particulier le vocabulaire , le guide Learning J et le guide des programmeurs J for C.
GolfScript gets its own way far too often
en 2019.Réponses:
Il y a un certain nombre de subtilités pour éliminer les derniers caractères de J. Pour ce qui suit, supposons que chaque majuscule est un verbe primitif (c'est-à-dire que je supprime les espaces qui seraient autrement nécessaires pour délimiter les noms).
Lorsque vous avez un train en cours et que vous devez appliquer une fonction au sommet d'une autre à mi-chemin
([:FLGR)
et(LF@:GR)
avoir le même nombre de caractères, mais en(LF@GR)
enregistre un. Si le cadre de G est supérieur ou égal au rang de monade de F, c'est une transformation valide. Notamment, tous les trains ont un rang infini, tout comme la, ,. ,: ~. /: \: [ ]
plupart des utilisations de#
et|.
.Si vous devez sélectionner des chaînes dans une liste et que ces chaînes n'ont pas d'espace, utilisez
>i{ab`cd`ef
. C'est sale, mais il enregistre des caractères pour chaque nouvelle chaîne que vous devez traiter, à moins que vous ne tiriez que des caractères uniques, et même dans ce cas, la liste de caractères doit être de longueur 4 pour être plus courte. Ce qui se passe, c'est que les noms non définis sont traités comme des références aux verbes, et lorsque vous prenez les gérondifs de ces verbes, vous obtenez une chaîne encadrée du nom. Tous les noms qui sont déjà définis comme ayant un nom, un adverbe ou une conjonction de type ne peuvent pas être utilisés de cette manière, car ces noms sont résolus avant de`
pouvoir y avoir.Si vous avez la chance d'avoir une expression avec laquelle travailler et pas seulement un verbe tacite, cela vaut presque toujours la peine d'attribuer tous les bits que vous réutilisez à des variables, qu'il s'agisse de noms, de verbes ou d'adverbes. Les parens se rentabilisent parfois en s'intégrant à l'endroit où vous aviez des espaces auparavant, et la plupart de ces définitions en valent la peine si elles sont réutilisées une fois de plus.
Des conjonctions comme
(FGH)^:(u`v`w)
peuvent être réécritesu`v`w(FGH^:)
. Cela fonctionne pour n'importe quelle longueur de train, même 1, même si vous n'enregistrez rien si cette astuce supprime les parens du bon argument. Cette astuce ne fonctionne que lorsque vous préchargez l'opérande de gauche. (Vous n'avez aucune idée de ce qui vient de se produire? Recherchez des adverbes tacites et étudiez la section Analyse et exécution du dictionnaire J.)N'utilisez pas
a.&i.
, utilisezu:
!{&a.
et3&u:
sont équivalents sur la longueur, cependant, et le premier pourrait être plus utile dans une conjonction (selon la conjonction).Des choses comme
(2%~F)
et(F%2:)
sont de longueur équivalente. C'est utile parce que parfois, selon l'apparence du reste de votre train, vous pouvez le restructurer avec des@
astuces comme écrit au premier point, pour sauver des personnages désespérés. (Et bien sûr, siF
c'est le cas]
et que le train est une monade, l'utilisation%&2
sauve un char, duh.)Trains en forme de crochet avec
]
ou[
comme verbe le plus à gauche, par exemple(]FGH)
.]
vous permet de diviser une application dyadique et d'utiliser uniquement le bon argument. (Échangez à gauche avec(]FGH)~
, à une pénalité d'au moins 1 caractère, peut-être plus.) Enregistre un caractère plus(FGH)@]
, et est très pratique dans les gérondifs![
dans un crochet appliqué monadiquement vous permet de faire quelque chose pour les effets secondaires du côté droit, puis de renvoyer l'argument à nouveau. L'utilisation la plus courante est avec1!:2
, peut-être avec le formatage indésirable.Les E / S sont nulles. Accélérez le processus en faisant des boucles avec tout ce que vous pouvez.
1!:1
a un rang0
, et les deux1!:2 3
ont un rang_ 0
, par exemple, alors utilisez-le en créant des tableaux de 1 et passez1!:1
directement dessus. Notez qu'il a".
également le rang 1, vous pouvez donc généralement le mettre directement après1!:1
, et ne pas avoir à le joindre via@
ou à classer les manigances.Ce n'est pas facile de trouver des endroits où mettre cela, mais cela
::
peut être utile.::]^:_
est une combinaison particulièrement puissante, par exemple, qui vous permet de faire quelque chose de dangereux jusqu'à ce que vous ne puissiez plus le faire. (Sous réserve des^:_
mises en garde habituelles en boucle.)Cela vous permet également d'utiliser
{
sur des listes qui n'ont pas l'index souhaité, car cela génère une erreur de domaine lorsque cela se produit. Utile, par exemple, pour prendre la tête d'une liste uniquement si elle existe (essayez d'utiliser::]
pour renvoyer la liste vide, ou::_1:
pour renvoyer un code d'erreur, etc.).]`($:@u)@.v
peuvent généralement être raccourcisu^:v^:_
, en particulier sur les définitions deu
etv
qui peuvent être utilisés avec. Un cas similaire est valable pour le conditionnel commeu^:(1-v)
contre]`[email protected]
. Considérez vos options, surtout lorsque vous avez beaucoup de verbes nommés flottant. C'est aussi un peu plus flexible, mais rappelez-vous, si vous l'utilisez$:
, il y a une profondeur de récursivité avec laquelle il est facile de se heurter. (Habituellement, quelque chose comme 1800 itérations?)la source
%&2
sauve un char, duh." Et-:
sauve un autre!La chose la plus importante lorsque vous jouez au golf en J est non seulement de comprendre le problème, mais de le réduire à une série de transformations de tableau. Vous devez comprendre cette façon de penser pour réussir avec le code J.
Par exemple, un défi récent a demandé de résoudre le plus grand problème de sous- réseau . L'algorithme de stock pour résoudre ce problème est l'algorithme de Kadane a la description informelle suivante:
Une traduction en code impératif est simple:
Cet algorithme semble compliqué pour J à première vue car il existe une boucle explicite qui ne ressemble pas à une réduction au premier abord. Si vous vous rendez compte de ce que fait l'algorithme, vous pouvez démêler les étapes individuelles et voir qu'il effectue en fait deux opérations de tableau simples:
Maintenant, ces deux étapes sont très faciles à implémenter en J. Voici une traduction:
(0 >. +)/\. y , 0
- Cette étape opère à l'autre extrémité du tableau pour mieux s'adapter au paradigme de J.0 >. +
est tacite0 >. x + y
.>./ y
Ensemble, nous obtenons une implémentation très concise de l'algorithme:
Si vous apprenez cette façon d'aborder l'implémentation des algorithmes, vos solutions seront aussi laconiques que ce code.
Voici quelques astuces que j'ai accumulées au fil du temps. Cette liste sera élargie au fur et à mesure que j'acquérirai plus de connaissances en golf J.
=
est étrange au début, mais est très utile dans les défis artistiques ASCII.&
dans des contextes tacites lorsque vous voulez une conjonction de pouvoir. Le vocabulaire suggèreu@[&0
un remplacement tacite à4 : 'u^:x y
moi et moi aussi.[:
ou@:
dans une séquence commeu@v
en choisissant une varianteu
qui a un argument de gauche. Par exemple, pour supprimer le premier élément du résultat dev
, utilisez1}.v
au lieu de[:}.v
si ce}.@v
n'est pas possible pour une raison quelconque.] v
est souvent plus court quev@]
si vous souhaitez utiliser monadicv
dans un contexte dyadique. Cela est utile surtout quand ilv
y a un long train de verbes.m (n v w) y
au lieu de(n v m&w) y
. Cela peut permettre d'éviter les espaces et les parenthèses.#\
au lieu de>:@i.@#
.u &. v
est utile quandv
a un avers. Sinon, vous pouvez utiliser[: vinv u & v
ou à lau & (v :. vinv)
place.^:_
est extrêmement utile pour les algorithmes où vous souhaitez atteindre la convergence, comme un remplissage ou des simulations.=.
et=:
peuvent être intégrés n'importe où dans une phrase. Utilisez-le pour créer des lignes simples où la notation tacite ne suffit pas.,
au lieu de plusieurs réductions lors de la réduction de tableaux multidimensionnels.la source
Méfiez-vous des boucles.
Alors que J a des structures en boucle (
for. do. end.
,while. do. end.
et variations), si vous vous trouvez à les utiliser , il y a une possibilité que votre algorithme ne joue pas aux forces de golf de J et qu'il ya des économies de caractère à effectuer.^:
la conjonction de puissance est votre amie. Pour exécuter un verbex
fois:Si vous avez besoin du résultat de chaque itération dans une liste:
Vous pouvez également utiliser
^:
pour exécuter un verbe conditionnellement:Doublez
+:
si^:
l'élément est supérieur à 33<]
(le"0
change le rang du verbe pour qu'il fonctionne un élément à la fois).la source
(i.x)
exemple, c'estf^:(<x)
-à- dire qu'elles sont équivalentes àf^:(i.x)
.Contribution
1!:1[1
prendra une ligne d'entrée terminée en appuyant sur la touche Entrée.1!:1[3
prendra un certain nombre de lignes d'entrée (terminé par Ctrl-D sur mon Mac, Ctrl-C sur Windows).Si vous essayez de saisir des nombres, l'utilisation
".
évaluera la chaîne et renverra une liste de nombres prêts à être manipulés. Si vous saisissez un numéro mais devez opérer sur les chiffres individuellement".,.
(grâce au commentaire de Jan Dvorak pour cela) ou"."0
diviserez la chaîne en chiffres séparés:Si vous lisez des chaînes, le moyen le plus court pour obtenir une liste encadrée de chaînes distinctes est d'utiliser
;:
. Cela fonctionne mieux pour les chaînes séparées par des espaces:la source
1!:1[2
fonctionnerait (le cas échéant)?1!:
page (je ne suis pas un expert en J), 2 est l'écran, donc la saisie depuis l'écran n'a pas beaucoup de sens.2
ne soit pas valide? Je n'ai pas mon ordinateur J sur moi pour l'essayer pour le moment. Où je vois2
, juste en dessous des notes1!:1
, c'est pour1!:2
.".
est de rang 1-xx et,.
produit toujours un tableau 2D,".,' ',.
(assembler avec espace, défiler et évaluer; 8 caractères) peut être remplacé par juste".,.
(défiler et évaluer; 4 caractères).Utiliser l'itération pour calculer des séquences
En règle générale, la résolution d'un défi de séquence OEIS nécessite l'utilisation d'une des formules données sur sa page. Certains d'entre eux s'adaptent bien à J, et d'autres moins. Les formules récursives sont simples, cependant, l'itération peut ne pas être simple. Un modèle que j'ai commencé à utiliser est
où
s
est la première valeur de la séquence,f
est un verbe qui calculera le terme suivant étant donné le terme précédent, etn
est l'index de base zéro du terme que vous souhaitez calculer. Cette méthode repose sur le fait que lors du calcul de la puissance d'une dyade, le LHS est lié à la dyade pour former une nouvelle monade, et cette monade est imbriquée sur la valeur initiale. La dyade donnée à l'adverbe de puissance est un crochet où(]f)
est donné l'indicen
sur le LHS et la valeur d'un terme dans la séquences
. Le crochet s'appliqueraf
ens
tant que monade, puis ignoreran
pour renvoyer le résultat def s
.Bibliothèque standard
Parfois, vous trouverez peut-être que J prendra en charge un verbe dans sa bibliothèque standard . Par exemple, la plupart des opérations entières au niveau du bit sont liées à des noms plus courts que l'utilisation de l'appel primitif.
Des fonctions intégrées de date et d'heure sont également disponibles.
Gammes
Si vous avez un ensemble de valeurs
[a, b, c]
et que vous souhaitez former une plage basée sur leur produit[0, 1, 2, ..., a*b*c-1]
, l'approche typique serait de trouver leur produit, puis de former une plage qui pourrait[:i.*/
coûter 6 octets. Une manière plus courte est,@i.
de 4 octets cari.
peut former des tableaux multidimensionnels tout en comptant toujours, et l'aplatir produira une plage équivalente.Impression en continu
Une manière tacite d'imprimer une valeur et de continuer à l'utiliser sans boucle explicite est
([echo)
pour un cas monadique.echo
est un verbe de la bibliothèque standard qui imprime son contenustdout
dans le même format que celui utilisé dans l'interpréteur. Le crochet passe ensuite la même valeur d'entrée à l'aide du[
verbe gauche .Base 10 chiffres d'un entier
La manière standard d'acquérir les 10 chiffres de base d'un entier est celle
10#.inv]
qui coûte 8 octets de trop! Une alternative consiste à le convertir en une chaîne et à l'analyser au rang 0,"."0@":
ce qui économise un octet, mais une méthode encore meilleure consiste à,.&.":
enregistrer un autre octet, ce qui rend le coût final 6 octets au lieu de 8.la source
Envisagez d'utiliser une définition explicite au lieu d'écrire un verbe tacite; sûr
3 :'
et'
coûte 5 octets, mais vous pouvez économiser beaucoup@
,@:
et de[:
cette façon.la source
Quelques astuces (assez) courantes que j'ai vues
Je partage quelques choses qui m'ont été utiles. Fondamentalement, ce sont tous des conseils que j'ai reçus moi-même, mais je n'ai pas de crédits pour la plupart.
Somme d'un tableau de rang un
Au lieu d'utiliser
+/@:(FGH)
use(1#.FGH)
. Cela signifie une dégradation de la base 1, ce qui signifie en fait la somme d'un tableau. Bien qu'il soit plus long que+/
cela, il ne nécessite pas de bouchon ou de composition, ce qui le rend souvent beaucoup plus court que l'utilisation+/
.Compter les dernières vérités
Si vous avez une liste booléenne et que vous souhaitez compter le nombre de vérités de fin, utilisez
#.~
. Voyez ici . La réponse APL explique bien comment cela fonctionne. Certes, cela ne m'a été utile que deux fois, mais j'ai pensé que je le partagerais de toute façon.En dessous de (&.)
Pas une astuce spécifique, mais juste une suggestion générale: l'adverbe
&.
-under conduit souvent à des solutions élégantes et (surtout) courtes. Gardez cela à l'esprit lorsque vous jouez au golf.Souvent, il est utile pour les défis de conversion binaire et autres bases, par exemple ce code qui supprime le bit le plus significatif d'un nombre:
}.&.#:
(convertir en liste de chiffres binaires, supprimer le premier chiffre, puis annuler la conversion en liste de chiffres binaires et convertir retour à la décimale). La solution simple est deux octets:#.@}.@#:
.Sous est également utile pour les défis où vous devez travailler avec des chiffres décimaux, car vous pouvez utiliser
u&.":
. Par exemple, les miles à court de manière à diviser donne à DÉCIMALES utilisations sous:,.&.":
.Un dernier exemple est de trouver l'ampleur d'un vecteur :,
+/&.:*:
notez que vous devez collecter tous les résultats de*:
-square avec&.:
-under puisque*:
-square est de rang zéro.la source
Des moyens plus courts de jouer avec les rangs
Parfois, vous aurez du code comme
<"0 i.3 3
, où vous souhaitez appliquer un verbev
au rangr
. Cependant, si vous utilisez un nom (comme0
), vous devrez souvent inclure un espace. Pour éviter cela, vous pouvez utiliser un autre verbeu
de rang équivalent et utiliser à lau"v
place. Par exemple, puisque+
a rang0 0 0
, nous pouvons utiliser à la<"+
place de<"0
.Voici un tableau de tous les verbes et de leurs rangs (obtenus en utilisant
v b. 0
):Pour utiliser ce tableau, trouvez le rang souhaité
r
sur le côté gauche, puis choisissez un verbe appropriév
dans le côté droit. Par exemple, si j'ai besoin de vectoriser un verbev
en profondeur2 _ 2
, je trouve ce rang à gauche et je choisis%.
à droite. Ensuite, j'utilisev"%.
au lieu dev"2 _ 2
.la source
strings
bibliothèque: conseils de golfLa bibliothèque de chaînes est extrêmement utile pour faire quoi que ce soit avec la manipulation de chaînes. Bien sûr, cela prend
include'strings'
(ce qui est très coûteux, compte tenu de J), mais vous pouvez parfois en retirer les avantages.stringreplace
Vous trouvez-vous en utilisant le remplacement de chaîne? Observez que
A stringreplace B
c'est la même chose queB rplc A
.En fait, voici comment
rplc
est mis en œuvre:cuts
Le verbe
cuts
fournit ainsi:Donc, c'est vraiment trancher une chaîne.
la source
Obtenir des nombres de 0 à 4
S'il y a une restriction sur l'utilisation de chiffres dans votre code:
0
%_
: un divisé par l'infini.1
#_
: combien d'infinis?2
#_ _
: deux infinis.3
verb
: il y a un intégré.4
dyad
: un autre intégré.Obtenir des nombres de 10 à 35
Base-inifinity littéraux: 11 :
_bb
, 26 :_bq
etc.la source
Programmation tacite
Les bases
Verbe dyadique
Verbe monadique
Misc
Des trucs
(F x) G (H y)
Solution Tacite:
(G~F)~H
; selon les verbes réels, pensez à réorganiser les arguments gauche et droit à supprimer~
.Remplacements monadic-dyadiques
la source
(G~F)~H
est une pure bonté pétillante!&
est votre ami, utilisez-le à bon escientv
est un verbe,n
est un substantifx
ety
sont des arguments gauche et droit, respectivement.Monade
&
: Introduire à l'~
intérieur de la chaîne adverbe / conjonctionUne chaîne adverbe / conjonction évalue à partir de la gauche. Donc, quelque chose comme ça
_2&+/\&.>
ne fonctionnera pas parce qu'il analyse comme(_2&+)/\&.>
nous le voulons_2&(+/\)&.>
. Dans ce cas, l'échange de la gauche / droite de+/\
peut enregistrer un octet, comme dans+/\~&_2&.>
car celui-ci est analysé comme((+/\)~)&_2&.>
. Pour voir pourquoi cela fonctionne:Dyad
&
: répéterx
foisSaviez-vous que si vous donnez un argument de gauche
x
à&
, la fonction l'appliquex
foisy
? Plusieurs défis vous demandent de faire certainsx
temps de fonctionnement . Il est principalement réalisable de deux manières:^:
sans l'opérande droitSi l'opération est
v
,v^:
devient alors un train d'adverbe qui, lorsqu'on lui donne un opérande gauche, devient un verbe monadique. Il env
est ainsi appliquéy
,x
fois.&
comme conjonction la plus externePour l'utiliser, vous devez identifier une constante
n
et un verbe dyadiqueu
, de sorte que soitn u y
ouy u n
soit équivalent àv
. Ensuite, vous pouvez écriren&u
ouu&n
résoudre la tâche entière. Cette forme est plus efficace lorsque le choix de la constante est évident, par exemple 3 in3 u:
(convertir les caractères en valeurs ASCII).En outre,
u&n
est légèrement préférable àn&u
lorsque la structure la plus externe deu
est une conjonction ou un adverbe (dans ce cas , vousn&u
devriez le fairen&(u)
; vous pouvez le faire à lau~&n
place).Notez que vous pouvez placer le dyadique
&
n'importe où dans un train pour obtenir la répétition d'une fonction arbitraire en argument arbitraire, dans le sens similaire à dynamique^:
.la source