Conseils pour jouer au golf à MATL

20

MATL est un langage golfique créé par Luis Mendo . MATL s'est avéré très compétitif, battant souvent les soumissions dans d'autres langues de golf telles que Pyth, CJam et Jelly.

Quels sont les conseils utiles pour jouer au golf en MATL? (Comme toujours, un conseil par réponse, s'il vous plaît!)

Stewie Griffin
la source
5
C'est certainement un grand avantage si vous connaissez du Matlab / Octave. Quelques astuces de Tips for golfing in Matlab and Tips for golfing in Octave used in MATL also.
flawr
Suggestion: il semble que accumarray( XQ) puisse être assez puissant (peut-être même plus que dans MATLAB / Octave car ces poignées de fonction de longueur ont des codes numériques pratiques), mais je ne le connais pas assez bien pour illustrer avec de bons exemples. Si c'est réellement utile, quelqu'un pourrait-il créer une réponse avec des idées sur la façon de l'utiliser?
sundar

Réponses:

7

Connaître les littéraux prédéfinis

Bien que certains d'entre eux conservent des informations lorsqu'ils sont copiés dans le presse-papiers, ils ont tous une valeur prédéfinie.

  • F, pousse 0 (en fait Faux )
  • T, pousse 1 (en fait True )
  • H, pousse 2 (valeur prédéfinie du presse-papiers)
  • I, pousse 3 (valeur prédéfinie du presse-papiers)
  • K, pousse 4 (valeur prédéfinie du presse-papiers)
  • J, pousse 0 + 1j (valeur prédéfinie du presse-papiers)

Je ne sais pas si j'ai couvert toutes les valeurs prédéfinies.

Adnan
la source
Juste pour être complet (et au cas où vous voudriez ajouter à votre réponse): chaque niveau de presse-papiers a Légalement une valeur prédéfinie, mais ils sont destinés à des usages spéciaux (plutôt que des valeurs générales communes). Par exemple, 1Ldonne [1 0](qui est utilisé comme index 1:end), 2Ldonne [0 -1 1](pour 1:-1:end). Fonctionne également let Oprend 0 entrées par défaut et produit 0et 1respectivement
Luis Mendo
Je ne vois pas en quoi cela est utile ... Je ne peux pas simplement écrire 4?
Cyoce
@Cyoce L'utilité est d'éviter un espace comme séparateur. Si vous voulez pousser 1, alors 4, 14ne le fera pas. Vous en auriez besoin 1 4. Ou 1Kpour économiser un octet
Luis Mendo
@LuisMendo ah, je vois. Je suppose que j'ai supposé qu'il utilisait uniquement la méthode du numéro à un chiffre (je ne sais pas pourquoi)
Cyoce
1
Un autre cas où Kau lieu de 4est pratique est: 1-4signifie: pousser 1, puis pousser -4; alors que 1-Ksignifie: pousser 1, soustraire de tout ce qui est en dessous dans la pile, puis pousser4
Luis Mendo
5

La &méta-fonction (spécification alternative d'entrée / sortie)

La manière traditionnelle de spécifier le nombre d'arguments d'entrée à passer à une fonction consiste à utiliser la $méta-fonction

2$:     % Two-input version of :

De même, pour spécifier le nombre d'arguments de sortie, vous pouvez utiliser la #méta-fonction spécifiant soit le nombre d'arguments de sortie,

2#S     % Two-output version of sort

ou si vous passez un nombre supérieur au nombre d'arguments de sortie définis pour une fonction, seule la mod(N, numberOfOutputs) + 1sortie est fournie.

4#S     % Get only the second output of sort

Vous pouvez en outre spécifier un tableau logique comme entrée #pour récupérer uniquement des arguments de sortie spécifiques.

TFT#u   % Three output version of unique and discard the second output

Toutes ces spécifications d'entrée / sortie sont pratiques mais elles augmentent très rapidement le nombre d'octets. Pour y faire face, MATL a introduit la &méta-fonction dans la version 17.0.0 . Cette &méta-fonction agit comme un raccourci pour une spécification d'entrée ou de sortie particulière pour une fonction. Voyons ce que cela signifie.

Dans notre exemple ci-dessus, nous voulions utiliser la version à deux entrées de :(crée un vecteur de valeurs également espacées). Alors que le nombre par défaut d'arguments d'entrée :est 1(crée un tableau à partir de [1...N]), il est très courant qu'un utilisateur veuille spécifier la valeur de début de la plage qui nécessite la deuxième entrée. Donc, pour :, nous avons défini &un raccourci pour 2$.

10      % Push 10 to the stack
12      % Push 12 to the stack
2$:     % Create an array: [10, 11, 12] 

Devient maintenant le suivant, économisant un octet !

10 12 &:

Comment déterminer le nombre alternatif d'arguments?

La spécification d'entrée / sortie qui se &traduit par est spécifique à la fonction de sorte que nous optimisons les économies d'octets.

La section des arguments d'entrée / sortie de la description de l'aide pour chaque fonction a été mise à jour pour indiquer quel est ce nombre alternatif d'entrées / sorties (le cas échéant). Le nombre possible d'arguments d'entrée ou de sortie est affiché sous forme de plage et les valeurs par défaut pour chacun sont affichées entre parenthèses. La spécification d'entrée / sortie qui peut être remplacée par &est indiquée après le /caractère entre parenthèses.

Voici la section des arguments d'entrée / sortie de la description de l'aide pour :

 +- Min-Max range of # of inputs
 |        +----- Alt. Default # of inputs
 |        |
 V        V
1--3 (1 / 2); 1 <--- Possible / Default # of outputs
      ^       
      |       
  Default # of inputs

Comment avez-vous déterminé ce que &signifie pour chaque fonction?

Très soigneusement. En utilisant l' API StackExchange , nous avons pu télécharger toutes les réponses MATL qui ont déjà été utilisées dans un défi PPCG. En analysant chacune des réponses, nous avons ensuite pu déterminer la fréquence à laquelle chaque spécification d'entrée / sortie était utilisée pour chaque fonction. En utilisant ces informations, nous avons ensuite pu identifier objectivement la spécification d'entrée / sortie que la &méta-fonction devrait représenter pour chaque fonction. Parfois, il n'y avait pas de gagnant clair, donc de nombreuses fonctions ne sont actuellement pas &définies.

Voici le script que nous avons utilisé (malheureusement, il est écrit en MATLAB et non MATL).

Et voici un exemple de l'histogramme de $/ #usage

Suever
la source
1
Cette fonctionnalité a été suggérée par @Suever. À l'origine, cela &signifiait "augmenter le nombre d'entrées de 1 par rapport à la valeur par défaut". Sa suggestion s'est avérée beaucoup plus utile
Luis Mendo
5

Familiarisez-vous avec les définitions de vérité / fausse de MATL

Alors que true( T) et false( F) représentent clairement la sortie vérité et fausse, respectivement, la définition largement acceptée de vérité / fausse nous donne un peu plus de flexibilité dans MATL.

La définition stipule:

if (x)
    disp("x is truthy");
else
    disp("x is falsy");
end

Nous pouvons donc écrire un test MATL de vérité / fausse rapide qui parcourra toutes les entrées et affichera si elles ont été considérées comme véridiques ou fausses

` ? 'truthy' } 'falsey' ]DT

Voici une version en ligne.

Ce que cela signifie en MATL

Ce que cela se traduit réellement dans MATL (et donc dans MATLAB et Octave), c'est qu'une condition est considérée comme vraie si, si elle n'est pas vide et que les composants réels de toutes ses valeurs sont non nuls . Il y a deux parties à souligner.

  1. Non nul : cela signifie précisément cela, différent de zéro ( ==). Cela inclut les nombres positifs, les nombres négatifs, les caractères non nuls, etc. Vous pouvez facilement vérifier en convertissant une valeur donnée en une logicalvaleur ( g) ou vous pouvez utiliser~~

    F           % Falsy
    T           % Truthy
    0           % Falsy
    1           % Truthy
    2           % Truthy
    -1          % Truthy
    'a'         % Truthy
    ' '         % Truthy (ASCII 32)
    char(0)     % Falsy  (ASCII 0)  
    
  2. Toutes les valeurs : en général, nous pensons que les scalaires sont vrais ou faux, mais dans MATL, nous pouvons évaluer les scalaires, les vecteurs de ligne, les vecteurs de colonne ou même les matrices multidimensionnelles et ils sont considérés comme véridiques si et seulement si chaque valeur unique est non nul (tel que défini ci-dessus), sinon ils sont faux. Voici quelques exemples pour démontrer

    [1, 1, 1]           % Truthy
    [1, 0, 0]           % Falsey
    [1, 1, 1; 1, 1, 1]  % Truthy
    [1, 0, 1; 1, 1, 1]  % Falsey
    'Hello World'       % Truthy
    

Le cas à un bord, comme mentionné ci-dessus, est un tableau vide [], qui est toujours considéré comme faux ( exemple )

Comment puis-je l'utiliser pour mieux jouer au golf?

Si le défi mentionne simplement que votre sortie doit être véridique ou fausse, vous pouvez probablement exploiter la définition ci-dessus pour raser quelques octets de votre réponse. Pour éviter toute confusion, il est recommandé d'inclure un lien vers le test de vérité / fausse en ligne ci-dessus dans votre réponse pour aider à expliquer le fonctionnement des valeurs MATL de vérité / fausse.

Quelques exemples spécifiques:

  • Une réponse se terminant par A. Si le défi nécessite une sortie véridique ou fausse et que vous terminez votre réponse en all( A) pour créer un scalaire, vous pouvez supprimer ce dernier octet et votre réponse restera correcte (à moins que la sortie ne soit []depuis []est falsemais []Aest true).

  • S'assurer qu'un tableau ne contient qu'une seule valeur unique : utilise &=à la place de un1=. Si toutes les valeurs d'un tableau sont égales, une comparaison d'égalité diffusée par élément produira une N x Nmatrice de toutes les valeurs . Si toutes les valeurs ne sont pas égales, cette matrice contiendra certaines 0valeurs et sera donc considérée comme fausse.

Suever
la source
4

Entrée implicite

La plupart des fonctions acceptent un certain nombre d'entrées. Ces entrées proviennent du haut de la pile. Si le haut de la pile ne contient pas suffisamment d'arguments, il tirera l'argument restant de l'entrée. (Voir la section 7.3 dans la documentation) Je voudrais citer l'explication originale:

Les entrées implicites peuvent être vues comme suit: la pile est étendue indéfiniment en dessous du bas, c'est-à-dire aux positions 0, -1, -2, ... avec des valeurs qui ne sont pas initialement définies, mais qui sont résolues à la volée via une entrée implicite . Ces entrées ne sont demandées à l'utilisateur que lorsqu'elles sont nécessaires, dans l'ordre dans lequel elles sont nécessaires. Si plusieurs entrées sont requises en même temps, elles suivent l'ordre normal de la pile, c'est-à-dire que l'entrée la plus profonde de la pile (étendue) est entrée en premier.

flawr
la source
2
L'entrée implicite est une fonctionnalité qui a été suggérée par @flawr
Luis Mendo
6
@flawr doit être un gars vraiment intelligent. : D
flawr
3

Les tableaux logiques peuvent souvent être utilisés comme tableaux numériques

Vous pouvez souvent utiliser la TFnotation " " au lieu des tableaux de zéros et de uns. Par exemple, FTFest le même que [0,1,0], seulement qui FTFproduit des logicalvaleurs, pas des doublevaleurs. Ce n'est généralement pas un problème, car toute opération arithmétique traitera les valeurs logiques comme des nombres. Par exemple, FTFQdonne [1,2,1]( Qest "augmenter de 1").

Dans certains cas, la conversion d'un nombre en binaire peut être plus courte. Par exemple, [1,0,1], TFTet 5Bsont les mêmes; encore une fois avec la prudence que les deux derniers sont des logicalvaleurs.


Un cas où la différence entre TF(logique) et [1 0](numérique) importe est lorsqu'il est utilisé comme indices. Un tableau de type logicalutilisé comme index signifie: choisir les éléments correspondant à T, éliminer ceux correspondant à F. Donc [10 20]TF)produit 10(sélectionner le premier élément), alors que [10 20][1 0])produit [10 20](l'indice [1 0]a l'interprétation de 1:end, qui, tous les éléments de choisir le tableau).

Luis Mendo
la source
3

Pour boucle de taille n-1

Envisager de remplacer

tnq:"...

avec

td"...

pour enregistrer jusqu'à un octet entier ou plus .

Sanchises
la source
@Luis true! Je pensais que l'on pourrait avoir besoin du vecteur d'origine en boucle, mais ce n'est pas possible dans la première approche non plus. Va supprimer cette remarque.
Sanchises
Mais vous n'enregistrez pas nécessairement 1 octet; vous économisez 1 ou 2 selon que vous avez besoin de @/ X@dans la boucle ou non. Vous pouvez peut-être simplement dire "pour économiser des octets"
Luis Mendo
3

Déplacez les choses depuis la boucle vers l'intérieur de la boucle, pour exploiter la fin implicite

Les endinstructions de boucle ,, ]peuvent être omises s'il n'y a pas de code après elles. Ils sont implicitement remplis par l'analyseur MATL.

Donc, si vous pouvez déplacer des éléments depuis la boucle vers l'intérieur de la boucle, vous pouvez enregistrer la finale ].

À titre d'exemple spécifique, le code suivant recherche le nombre de zéros de fin dans la factorielle d'un nombre N(voir ici ):

  • Le code boucle de 1à N.
  • Pour chacun de ces nombres, il calcule ses facteurs premiers et détermine combien de fois 5est présent.
  • La réponse est que le nombre cumulé de fois 5apparaît (cela fonctionne car pour chacun 5il y en a au moins un 2).

La première idée était :"@Yf5=]vs(notez qu'il y a des instructions après la boucle):

:      % Range from 1 to implicit input
"      % For each number in that vector
  @    %   Push that number
  Yf   %   Vector of prime factors (with repetitions)
  5=   %   True for entries that equal `5`, and `false` for the rest
]      % End for
v      % Concatenate all vectors as a column vector
s      % Sum. Implicitly display

Puisque vpar défaut concatène tout le contenu de la pile, il peut être déplacé dans la boucle. Et comme l'addition est associative, elle speut aussi être déplacée. Cela laisse ]à la fin du code, et donc il peut être omis :"@Yf5=vs:

:      % Range from 1 to implicit input
"      % For each number in that vector
  @    %   Push that number
  Yf   %   Vector of prime factors (with repetitions)
  5=   %   True for entries that equal `5`, and `false` for the rest
  v    % Concatenate all vectors so far as a column vector
  s    % Sum. Inplicitly end loop and display
Luis Mendo
la source
je ne connais pas un centime de cette langue écrite hiéroglyphique, mais je réserverai peut-être une grande partie de mon temps à l'étudier les trois prochains mois.
Abr001am
@ Agawa001 :-) Vous constaterez qu'il est assez similaire à Matlab. Vous pouvez également demander ou commenter ici
Luis Mendo
3

Manière plus courte de définir un tableau numérique vide, si la pile est vide

Pour pousser un tableau numérique vide que vous utilisez normalement []. Cependant, si la pile est vide, vous pouvez enregistrer un octet en utilisant v. Par défaut, cette fonction concatène verticalement tout le contenu de la pile, donc si la pile est vide, elle produit le tableau vide.

Vous pouvez le voir en action par exemple ici .

Luis Mendo
la source
2

Certaines fonctions sont étendues par rapport à MATLAB ou Octave

Si vous venez de MATLAB ou Octave, vous trouverez que de nombreuses fonctions MATL sont similaires aux fonctions de ces langages. Mais dans bon nombre d'entre eux, la fonctionnalité a été étendue.

Par exemple, considérons la reshapefonction de MATLAB , à laquelle correspond MATLAB e. Les extraits de codereshape([10 20 30 40 50 60], 2, 3) et reshape([10 20 30 40 50 60], 2, [])respectivement signifient «remodeler le vecteur ligne [10 20 30 40 50 60en une matrice 2 × 3» ou «en une matrice 2 lignes avec autant de colonnes que nécessaire». Ainsi, le résultat, dans les deux cas, est le tableau 2D

10    30    50
20    40    60

Quelque chose comme reshape([10 20 30 40 50 60], 2, 2)ou reshape([10 20 30 40 50 60], 5, [])donnerait une erreur en raison de tailles incompatibles. Cependant, MATL supprimera les éléments dans le premier cas ( essayez-le en ligne! ) Ou remplira de zéros dans le second ( essayez-le en ligne! ) Pour produire, respectivement,

10 30
20 40 

et

10 60
20  0
30  0
40  0
50  0

Les autres fonctions qui ont des fonctionnalités étendues par rapport à leurs homologues MATLAB sont (liste non exhaustive) S( sort), Yb( strsplit), m( ismember), h( horzcat), v( vertcat), Zd( gcd), Zm( lcm), YS( circshift), YA( dec2base), ZA( base2dec), Z"( blanks).

Luis Mendo
la source
1

Récupère l'index du premier élément non nul, le cas échéant

La ffonction donne les indices de tous les éléments non nuls d'un tableau. Souvent, vous voulez l'index du premier élément différent de zéro. Ce serait f1): appliquer fet choisir son premier élément. Mais si le tableau d'origine ne contient aucune valeur non nulle f, un tableau vide sera généré ([] ) , et essayer de choisir son premier élément donnera une erreur.

Une exigence courante et plus robuste consiste à obtenir l'indice du premier élément s'il y en a au moins un et []sinon. Cela pourrait être fait avec une ifbranche après f, mais cela coûte cher. Une meilleure façon est d' fX<appliquer la fonction minimale X<à la sortie de f. X<renvoie un tableau vide lorsque son entrée est un tableau vide.

Essayez-le en ligne! (Notez qu'un tableau vide ne s'affiche pas du tout). Ou voyez un exemple de ceci au travail ici .

Luis Mendo
la source
1

Générer une plage tant qu'un tableau donné

TL; WR : utilisez à la fplace de n:si le tableau n'a que des éléments non nuls.


Il est souvent nécessaire de générer un tableau [1 2 ... L]Lest le nombre d'éléments d'un tableau donné. La façon standard de le faire est n:. Par exemple, le codetn:* prend un vecteur numérique en entrée et calcule chaque entrée multipliée par son index.

Si le tableau donné est garanti pour ne contenir que des entrées non nulles (par exemple, il est formé d'entiers positifs ou est une chaîne avec des caractères imprimables), n:peut être remplacé par f, qui produit un tableau avec les indices des entrées non nulles. Ainsi, le code ci-dessus devient tf*, ce qui économise 1 octet.

Quelques exemples plus élaborés: 1 , 2 , 3 .

Luis Mendo
la source
1

Définition efficace des littéraux de tableau numérique

Voici quelques méthodes qui peuvent être utilisées pour économiser des octets lors de la définition des littéraux de tableau numérique. Des liens sont donnés vers des exemples de réponses qui les utilisent. Ceux-ci ont été obtenus en utilisant le script d'analyse créé par @Suever .

Concaténation et littéraux prédéfinis

Pour les tableaux avec de petits nombres, vous pouvez parfois utiliser la concaténation (fonctions het v), ainsi que des littéraux prédéfinis pour éviter d'utiliser des espaces comme séparateurs: comparer [2 4], 2 4het 2Kh, qui définissent tous le tableau [2 4]. De même, 2K1vavec une pile vide définit [2; 4; 1]. Exemple .

Lettres dans les littéraux de tableau numérique

Pour des nombres légèrement plus grands, vous pouvez économiser des espaces en exploitant le fait que certaines lettres ont des significations numériques dans les littéraux de tableau. Donc, au lieu de [3 5 2 7;-4 10 12 5]vous pouvez utiliser [IAHC;dX12A]. Exemple .

Plus précisément, dans les littéraux de tableau,

  • O, l, H I KOnt leurs significations habituelles 0, ...,4
  • A, ..., Esignifie 5, ...,9
  • X veux dire 10
  • a, ... dsignifie -1, ...,-4
  • Jet Gméchant 1jet-1j
  • P veux dire pi
  • Y veux dire inf
  • Nsignifie NaN.

Chaîne et différences consécutives

Pour de plus grands nombres, définir une chaîne et calculer ses différences consécutives (avec d) peut aider: au lieu de [20 10 35 -6]vous pouvez utiliser '!5?b\'d. Cela fonctionne car dutilise les points de code des caractères pour calculer les différences. Exemple .

Luis Mendo
la source