Conseils pour jouer au golf dans CJam

43

CJam est un langage de golf basé sur une pile inspiré de GolfScript, créé par l’utilisateur aditsu de PPCG .

Donc, dans la même veine que d’autres astuces spécifiques aux langues:

Quels conseils généraux avez-vous pour jouer au golf dans CJam? Merci de poster un pourboire par réponse.

Martin Ender
la source
4
Voir aussi Conseils pour jouer au golf dans GolfScript ; les langues sont suffisamment similaires pour que de nombreuses astuces puissent être adaptées dans les deux cas.
Ilmari Karonen
2
@IlmariKaronen Après avoir examiné les réponses à cette question, je dirais que seulement la moitié d'entre elles s'appliquent à CJam, en raison de différences syntaxiques ou logiques dans les langues.
Optimiseur

Réponses:

23

Corrigez le modulo pour les nombres négatifs

Il est souvent gênant que le résultat de l'opération modulo donne le même signe que le premier opérande. Par exemple, -5 3%donne -2au lieu de 1. Le plus souvent, vous voulez ce dernier. La solution naïve consiste à appliquer modulo, à ajouter le diviseur une fois et à appliquer à nouveau modulo:

3%3+3%

Mais c'est long et moche. Au lieu de cela, nous pouvons utiliser le fait que l' indexation de tableau est toujours modulaire et fait fonctionner correctement avec des indices négatifs. Nous transformons donc simplement le diviseur en une plage et avons accès à:

3,=

Appliqué à -5, cela donne 1comme prévu. Et ce n'est qu'un octet plus long que celui intégré %!

Si le module est une puissance de 2, vous pouvez enregistrer un autre octet en utilisant une méthode arihmétique au niveau du bit (qui est également beaucoup plus rapide). Comparer:

32,=
31&

Pour le cas particulier d’ 65536 == 2^16un autre octet, vous pouvez enregistrer en utilisant le comportement d’emballage du type de caractère:

ci
Martin Ender
la source
13

Pousser des plages de caractères concaténés

  • La chaîne contenant tous les chiffres "0123456789"peut être écrite comme

    A,s
    
  • Les lettres ASCII majuscules ( A-Z) peuvent être insérées comme

    '[,65>
    

    qui génère la chaîne de tous les caractères jusqu’à Z , puis rejette les 65 premiers (jusqu’à @ ).

  • Toutes les lettres ASCII ( A-Za-z) peuvent être poussées comme

    '[,65>_el+
    

    qui fonctionne comme ci-dessus, puis crée une copie, convertit en minuscule et ajoute.

    Mais il y a un moyen plus court de le faire!

    Ensuite, l' ^opérateur souvent négligé (différences symétriques pour les listes) permet de créer les mêmes plages tout en économisant trois octets:

    '[,_el^
    

    '[,crée la plage de tous les caractères ASCII jusqu'à Z , _elcrée une copie en minuscule et ^ne conserve que les caractères des deux chaînes qui apparaissent dans une, mais pas les deux.

    Comme toutes les lettres de la première chaîne sont en majuscules, toutes les lettres de la seconde sont en minuscules et que tous les caractères autres que des lettres figurent dans les deux chaînes, le résultat est une chaîne de lettres.

  • La RFC 1642 Base64 alphabet ( A-Za-z0-9+/) peut être poussée en utilisant la technique ci-dessus et en ajoutant les non-lettres:

    '[,_el^A,s+"+/"+
    

    Une façon tout aussi courte de pousser cette chaîne utilise uniquement des différences symétriques:

    "+,/0:[a{A0":,:^
    

    Comment pouvons-nous trouver la chaîne au début?

    Toutes les plages utilisées de caractères ( A-Z, a-z, 0-9, +, /) peuvent être poussés comme la différence symétrique de gamme pour que démarre à l'octet nul, à savoir 'A,'[,^, 'a,'{,^, '0,':,^, '+,',,^et '/,'0,^.

    Par conséquent, l’exécution :,:^sur "A[a{):+,/0"poussera les caractères souhaités, mais pas dans le bon ordre.

    Comment trouvons-nous le bon ordre? La force brute à la rescousse! Le programme

    '[,_el^A,s+"+/"+:T;"0:A[a{+,/0"e!{:,:^T=}=
    

    itère sur toutes les permutations possibles de la chaîne, applique :,:^et compare le résultat à la sortie souhaitée ( permalien ).

  • L’alphabet de la base 64 utilisé, par exemple avec crypt ( .-9A-Za-z), peut être généré en utilisant la méthode ci-dessus:

    ".:A[a{":,:^
    

    C'est la méthode la plus courte que je connaisse.

    Étant donné que tous les caractères de la sortie souhaitée sont dans l'ordre ASCII, il n'est pas nécessaire d'effectuer une itération sur des permutations.

  • Toutes les plages de caractères concaténés ne peuvent pas être déplacées dans l'ordre souhaité à l'aide de :,:^.

    Par exemple, la plage 0-9A-Za-z;-?ne peut pas être poussée en exécutant :,:^sur une permutation de "0:A[a{;@".

    Cependant, nous pouvons trouver une variation pivotée de la chaîne souhaitée qui peut, en utilisant le code

    A,'[,_el^'@,59>]s2*:T;"0:A[a{;@"e!{:,:^T\#:I)}=Ip
    

    qui imprimera ( permalien ) les éléments suivants:

    10
    0:@[a{A;
    

    Cela signifie que

    "0:@[a{A;":,:^Am>
    

    a le même effet que

    A,'[,_el^'@,59>]s
    

    qui ne peut être utilisé qu'avec une pile vide sans préfixe a [.

Dennis
la source
11

Éviter {…}{…}?

Supposons que vous avez un entier sur la pile. Si c'est étrange, vous voulez le multiplier par 3 et ajouter 1; sinon vous voulez le diviser par 2.

Une déclaration "normale" si / else ressemblerait à ceci:

_2%{3*)}{2/}?

Cependant, l'utilisation de blocs n'est généralement pas la solution, car elle {}{}ajoute déjà quatre octets. ?peut également être utilisé pour sélectionner l'un des deux éléments de la pile:

_2%1$3*)@2/?

C'est un octet plus court.


Bloc-? avec une instruction if vide est toujours un no-go. Par exemple,

{}{2/}?

est deux octets plus long que

{2/}|

Si vous avez plutôt

{2/}{}?

et la chose que vous vérifiez est un entier non négatif, vous pouvez le faire

g)/

Les nouvelles {}&et {}|sont pratiques, mais parfois problématiques si vous ne pouvez pas encombrer la pile.

Pourtant, dans le cas de

_{…}{;}?

vous pouvez utiliser une variable temporaire à la place:

:T{T…}&
Dennis
la source
1
!)/et g)/sont plus courts dans les exemples.
Jimmy23013
11

Changer de relevé

CJam n'a pas de déclarations switch. Si les instructions fonctionnent aussi bien, mais elles ont {{}{}?}{}?déjà 12 octets de long ...

Si nous pouvons transformer la condition en un petit entier non négatif, nous pouvons transformer toutes les instructions case en une chaîne délimitée et évaluer le résultat correspondant.

Par exemple, si nous voulons exécuter code0si l’entier de la pile est 0 , code1s’il s’agit de 1 , et code2s’il est 2 , nous pouvons soit utiliser

_{({code2}{code1}?}{;code0}?

ou

[{code0}{code1}{code2}]=~

ou

"code0 code1 code2"S/=~

S/divise la chaîne en ["code0" "code1" "code2"], =extrait le bloc correspondant et ~évalue le code.

Cliquez ici pour voir les instructions de commutateur en action.

Enfin, comme suggéré par @ jimmy23013 et @RetoKoradi, nous pouvons raccourcir davantage le changement dans certains cas. Say code0, code1et code2avoir des longueurs L 0 , L 1 et L 2 , respectivement.

Si L 0 = L 1 ≥ L 2

"code0code1code2"L/=~

peut être utilisé à la place, où Lest L 0 . Au lieu de diviser un séparateur, /divise la chaîne en morceaux de même longueur.

Si L 0 ≥ L 1 ≥ L 2 ≥ L 0 - 1 ,

"cccooodddeee012">3%~

peut être utilisé à la place. >supprime 0, 1 ou 2 éléments du début de la chaîne et 3%extrait tous les trois éléments (en commençant par le premier).

Dennis
la source
Pour le dernier exemple, cela a-t-il un avantage "code0code1code2"5/=~? Cela me semble beaucoup plus simple et c'est la même longueur.
Reto Koradi
@RetoKoradi Si tous les extraits ont la même longueur, aucun avantage. Pour des longueurs différentes, votre méthode peut être à la fois plus courte et plus longue que la méthode du module.
Dennis
11

Golfing tableau commun et valeurs de chaîne

Certains tableaux ou chaînes courts apparaissent de temps en temps, par exemple pour initialiser des grilles. Naïvement, ils peuvent coûter 4 octets ou plus, il est donc intéressant de rechercher des opérations sur des valeurs intégrées qui donneront le même résultat. En particulier, la conversion de base est souvent utile.

  • [0 1]peut être écrit comme 2,.
  • [1 0]peut être écrit comme YYb(c'est-à-dire 2 en binaire).
  • [1 1]peut être écrit comme ZYb(c'est-à-dire 3 en binaire).
  • La matrice [[0 1] [1 0]]peut être écrite comme 2e!.
  • [LL] peut être écrit comme SS/(divisant un seul espace par des espaces).
  • "\"\""peut être écrit comme L`.
  • "{}"peut être écrit comme {}s.

Ce dernier peut être étendu aux cas où vous voulez que tous les types de crochets enregistrent un autre octet:

  • "[{<()>}]"peut être écrit comme {<()>}a`.
  • "()<>[]{}"peut être écrit comme {<()>}a`$.

En particulier, l’astuce de conversion de base peut être utile à garder à l’esprit pour certains cas obscurs qui apparaissent de temps en temps. Par exemple, [3 2]serait E4b(14 en base 4).

Dans des cas encore plus rares, vous pouvez même trouver mfutile l' opérateur de factorisation . Eg [2 7]est Emf.

N'hésitez pas à étendre cette liste si vous rencontrez d'autres exemples.

Martin Ender
la source
10

Effacement de la pile

Si vous voulez juste effacer toute la pile, enveloppez-la dans un tableau et affichez-la:

];

Ce qui est un peu plus délicat, c’est que si vous avez fait beaucoup de calculs, mais que vous vouliez seulement garder l’élément supérieur de la pile et tout mettre au rebut. L’approche naïve consisterait à stocker l’élément supérieur dans une variable, à vider la pile, à pousser la variable. Mais il existe une alternative beaucoup plus courte: envelopper la pile dans un tableau et extraire le dernier élément:

]W=

(Merci à Optimizer qui m'a montré cela l'autre jour.)

Bien sûr, s'il n'y a que deux éléments sur la pile, \;c'est plus court.

Martin Ender
la source
\;ne ferait apparaître que l'élément en dessous du TOS. Vouliez-vous dire ;;?
CalculatriceFeline
1
@CalculatorFeline La seconde partie de la réponse concerne tout effacer sauf le TOS.
Martin Ender
9

e et des pouvoirs de dix

Comme dans beaucoup d'autres langues, vous pouvez écrire à la 1e3place de 1000CJam.

Cela fonctionne pour les bases non entières et même pour les exposants non entiers. Par exemple, 1.23e2appuie sur 123.0 et 1e.5sur 3.1622776601683795 (racine carrée de 10 ).

Ce qui est pas évident immédiatement que 1e3est en fait deux jetons:

  • 1pousse le nombre entier 1 sur la pile.

  • e3le multiplie par 1000 .

Pourquoi est-ce important?

  • Vous pouvez faire appel e<numeric literal>à quelque chose qui est déjà sur la pile.

    2 3 + e3 e# Pushes 5000.
    
  • Vous pouvez mapper e<numeric literal>sur un tableau.

    5 , :e3  e# Pushes [0 1000 2000 3000 4000].
    
Dennis
la source
9

Normes euclidiennes

La manière simple de calculer la norme euclidienne d’un vecteur, c’est-à-dire la racine carrée de la somme des carrés de ses éléments, est la suivante:

2f#:+mq

Cependant, il existe un moyen beaucoup plus court.

mh, l'opérateur hypoténuse, extrait deux entiers a et b de la pile et pousse sqrt (a 2 + b 2 ) .

Si nous avons un vecteur x: = [x 1 … x n ], n> 1 sur la pile, :mh(réduire par hypoténuse) permettra d'obtenir ce qui suit:

  • Les premiers x 1 et x 2 sont poussés et mhsont exécutés en laissant sqrt (x 1 2 + x 2 2 ) sur la pile.

  • Ensuite, x 3 est poussé et mhest exécuté à nouveau, laissant
    sqrt (sqrt (x 1 2 + x 2 2 ) 2 + x 3 2 ) = sqrt (x 1 2 + x 2 2 + x 3 2 ) sur la pile.

  • Une fois que x n a été traité, il ne reste que sqrt (x 1 2 +… x n 2 ) , la norme euclidienne de x .

Si n = 1 et x 1 <0 , le code ci-dessus produira un résultat incorrect. :mhzfonctionne sans condition. (Merci à @ MartinBüttner pour l'avoir signalé.)

J'ai utilisé cette astuce pour la première fois dans cette réponse .

Dennis
la source
2
Bien sûr, cela a des implications pour l'analyse numérique de votre programme ...
Peter Taylor
8

Convertir à partir de la base n avec une liste de nombres supérieure à n

CJam convertit une liste en un nombre de cette formule: A 0 * n l + A 1 * n l-1 + A 2 * n l-2 + A l * n 0 (avec non négatif n). nest la base et lest la longueur de la liste. Cela signifie que i peut être n'importe quel entier, ce qui ne doit pas nécessairement être compris dans la plage [0,n).

Quelques exemples:

  • 0bextrait le dernier élément et le convertit en entier. Fonctionne comme W=iet enregistre un octet s'il ne s'agit pas d'un entier. Mais tout le reste de la liste doit également pouvoir être converti en entier.
  • 1brenvoie la somme. Fonctionne comme :i:+et enregistre deux octets s’ils ne sont pas des nombres entiers. Cela fonctionne aussi avec des listes vides alors :+que non.
  • [i{_1&9 32?_@\m2/}16*;]W%:cconvertit un caractère en une chaîne de fins de ligne et de tabulations, qui peut être reconvertie avec 2bc. La fonction d'encodage n'est pas facile à jouer dans un programme de code-golf, cependant. Mais vous n'en avez généralement pas besoin.
  • Vous pouvez utiliser le code suivant pour convertir une chaîne en caractères Unicode non 16 bits, qui peuvent être reconvertis avec 2A#b128b:c. (Les explications seront ajoutées plus tard. Ou peut-être que j'écrirai une nouvelle version plus tard.)

    128b2A#b         " Convert to base 1024. ";
    W%2/)W%\:+       " Convert to two base 1024 digit groups. ";
    [0X@
    {
      _54+
      @I+_Am>@\-
      _Am<@+ 0@-@1^
    }fI
    ]);)
    @\+[~+]2A#b_2G#<!{2A#b}*
    \W%+:c
    

La méthode similaire fonctionne avec n'importe quel ensemble d' nentiers ayant des valeurs différentes mod n, si vous pouvez trouver un moyen de vous débarrasser du chiffre le plus significatif.

jimmy23013
la source
8

Utiliser $comme ternaire si

Lorsque vous ne craignez pas de perdre de la mémoire, c.-à-d. En laissant sur la pile des éléments inutilisés que vous éclaircirez plus tard ];, l'opérateur de copie $peut être un substitut pratique à l'opérateur ternaire ?.

? fonctionne bien si vous parvenez à calculer la condition avant de choisir entre les deux éléments, mais le plus souvent, la condition dépend en fait de ces éléments, et son résultat s'ajoute aux résultats beaucoup plus naturels.

Si vous avez A B Csur la pile, vous pouvez exécuter

!$

au lieu de

\@?

copier Bsi Cest la vérité et Aautrement.

Si Cest un booléen réel ( 0ou 1), vous pouvez exécuter

$

au lieu de

@@?

copier Asi Cest la vérité et Bautrement.

Dennis
la source
Avec le recul, c’est un tour assez évident, mais je n’y avais jamais pensé auparavant. Je l'ai utilisé pour la première fois dans cette réponse .
Dennis
7

Carte pour les listes imbriquées

Disons que vous avez une liste imbriquée, comme une matrice:

[[0 1 2][3 4 5][6 7 8]]

Ou un tableau de chaînes:

["foo""bar"]

Et vous voulez mapper un bloc sur le niveau imbriqué (c'est-à-dire l'appliquer à chaque nombre ou à chaque caractère). La solution naïve est un imbriqué %:

{{...}%}%

Cependant, vous pouvez réellement pousser le bloc interne sur la pile, puis l'utiliser f%. fest "mapper avec un paramètre supplémentaire", donc il mappera %sur la liste externe, en utilisant le bloc comme second paramètre:

{...}f%

Enregistre deux octets.

Une autre astuce pour faire quelque chose for (i=0; i<5; ++i) for (j=0; j<5; ++j) {...}est comme

5,_f{f{...}}

L'extérieur fmappera sur la première plage, fournissant la deuxième plage comme paramètre supplémentaire. Mais maintenant, si vous utilisez à fnouveau, seul l'élément de pile supérieur est un tableau. Vous pouvez donc fmapper le bloc interne sur celui-ci, en fournissant la "variable d'itération" externe en tant que paramètre supplémentaire. Cela signifie que le bloc interne est exécuté avec iet jsur la pile.

Cela a le même nombre de caractères que de simplement mapper un bloc sur un produit cartésien (bien que ce dernier soit plus court si vous avez besoin des paires sous forme de tableaux):

5,_m*{~...}%

La différence réside dans le fait que cette version génère un seul tableau de résultats pour toutes les paires, alors que la version double fgénère une liste imbriquée, ce qui peut être utile si vous souhaitez stocker les résultats dans une grille, les variables d'itérateur constituant les coordonnées.

Merci à Dennis de m'avoir montré cette astuce.

0.6.4 Mise à jour

fet :ont maintenant été immensément améliorés en prenant n'importe quel autre opérateur, y compris eux-mêmes. Cela signifie que vous pouvez économiser encore plus d'octets maintenant. Le mappage d'un opérateur sur une liste imbriquée s'est encore raccourci:

{:x}%
{x}f%
::x

Cela n’aide pas vraiment à mapper des blocs sur des listes imbriquées.

Quant aux blocs ou opérateurs appliqués au produit cartésien, ils ont également été raccourcis, aussi bien pour les blocs que pour les opérateurs:

5,_f{f{...}}
5,_ff{...}

5,_f{fx}
5,_ffx

Ce qui est bien, c'est que vous pouvez maintenant les imbriquer. Vous pouvez donc aussi facilement appliquer un opérateur au troisième niveau d'une liste:

:::x

Ou un bloc avec quelques ruses:

{...}ff%
Martin Ender
la source
Excellente mise à jour. Mais il n'y a toujours pas de f~...
jimmy23013
@ user23013 fattend un opérateur binaire, ~est unaire; est-ce que tu voulais peut-être :~? En outre, nous pouvons en discuter en chat
Aditsu
Est-ce que je manque quelque chose à propos de cette mise à jour 0.6.4? Je reçois toujours des messages d'erreur lors de ces astuces, comme Unhandled char after ':': :( lien )
Runer112
2
@ Runer112 fonctionne pour moi. Assurez-vous de recharger correctement (c.-à-d. Pas à partir du cache). Selon votre navigateur, Ctrl + F5 devrait fonctionner.
Martin Ender
@ MartinBüttner C'était en effet causé par une mise en cache idiote. Merci.
Runer112
7

Opérateurs vectorisés pour l'art ASCII

Pour de nombreux défis artistiques ASCII, il est utile de générer deux modèles différents pour les superposer ultérieurement. Les opérateurs vectorisés peuvent être très utiles pour réaliser différents types de superpositions.

Une des propriétés utiles de la vectorisation par opérateur est que l'opérateur n'est exécuté qu'une seule fois pour chaque élément de la chaîne / du tableau le plus court, tandis que les éléments du plus grand élément n'ayant pas d'équivalent restent inchangés.

  • .e<

    L'opérateur minimum e<fonctionne pour des paires de chaînes, caractères, tableaux et entiers; il sort deux objets de la pile et pousse le bas vers l'arrière.

    Dans la mesure où un espace a un point de code inférieur à tous les autres caractères ASCII imprimables, il .e<peut être utilisé pour "effacer" des parties d'un motif généré:

    "\/\/\/\/\/" "    " .e<
    
    e# This pushes "    \/\/\/".
    

    Pour un exemple complet, voir ma réponse à Me Want Honeycomb .

  • .e>

    L'opérateur maximum e>fonctionne comme l'opérateur minimum, avec le résultat opposé.

    De nouveau, en raison du point de code bas de l'espace, .e>peut être utilisé pour insérer un motif de caractères imprimables dans un bloc d'espaces:

    [[" " " " " " " "] [" " " " " " " "]][["+" "" "-" ""]["" "*" "" "/"]] ..e>
    
    e# This pushes [["+" " " "-" " "] [" " "*" " " "/"]].
    

    Pour un exemple complet, voir ma réponse à Seven Slash Display .

  • .e&

    L'opérateur logique AND e&pousse son argument de gauche s'il est faux et son argument de droite sinon.

    Si aucun des modèles ne contient d'éléments de fausseté, vous pouvez utiliser cette option pour imposer inconditionnellement un modèle à un autre:

    "################" " * * * *" .e&
    
    e# This pushes " * * * *########".
    

    Pour un exemple complet, voir ma réponse à Imprimer le drapeau américain! .

  • .e|

    L'opérateur OU logique e|peut être utilisé comme ci-dessus, avec un ordre d'argument inversé:

    " * * * *" "################" .e|
    
    e# This pushes " * * * *########".
    
Dennis
la source
6

Utiliser &pour vérifier si un élément est dans une liste

Pour

1 [1 2 3] #W>
1 [1 2 3] #)

Vous pouvez utiliser

1 [1 2 3] &,
1 [1 2 3] &

au lieu de cela, qui renvoie 0/1 et vérité / falsey respectivement.

jimmy23013
la source
6

z et tableaux non rectangulaires

L'opérateur zip ztranspose les lignes et les colonnes d'un tableau A 1 à deux dimensions , dont les éléments peuvent également être itérables.

Pour les tableaux non rectangulaires - contrairement aux zipfonctions intégrées de, par exemple, Python (tronque les lignes à la même longueur) ou Ruby (complète les lignes avec nil) - CJam convertit simplement les colonnes du tableau en lignes, en ignorant leur longueur et les lacunes.

Par exemple, zipper le tableau

[
  [1]
  [2 4]
  [3 5 6]
]

est équivalent à zipper le tableau

[
  [1 4 6]
  [2 5]
  [3]
]

ou le tableau

[
  [1]
  [2 4 6]
  [3 5]
]

comme les trois actions poussent

[
  [1 2 3]
  [4 5]
  [6]
]

sur la pile.

Bien que cela ne signifie pas qu'il zne s'agit pas d'une involution (ce qui serait utile à l'occasion), il a quelques applications.

Par exemple:

  • Nous pouvons aligner les colonnes d'un tableau vers le haut (c'est-à-dire, transformer le premier tableau en deuxième) en zippant deux fois:

    zz
    
  • Des modifications mineures de la méthode ci-dessus peuvent être utilisées pour des problèmes similaires.

    Par exemple, pour aligner les colonnes d'un tableau vers le bas (c'est-à-dire, pour transformer le deuxième tableau en premier), nous pouvons compresser deux fois avec un ordre de rang inversé:

    W%zzW%
    
  • Avec un tableau de chaînes, nous pouvons calculer la longueur de la plus longue chaîne comme ceci:

    :,:e>
    

    Cependant, en compressant et en calculant le nombre de lignes du résultat, nous pouvons économiser trois octets:

    z,
    

1 Si l'une des "lignes" de A n'est pas itérable, traitez- zles comme des singletons, afin que la compression fonctionne pour des tableaux arbitraires.

Dennis
la source
1
Juste une façon différente de visualiser la même chose, mais pour moi, le comportement est beaucoup plus logique si j’imagine zconvertir des colonnes en lignes, alors que les valeurs vides sont ignorées. Dans l'exemple, la première colonne de l'entrée est 1, 2, 3, la deuxième colonne est 4, 5 (la position vide est ignorée) et la troisième colonne est 6. Il s'agit alors des lignes du résultat.
Reto Koradi
@RetoKoradi C'est une bien meilleure façon de le décrire.
Dennis
6

Exceptions

Toutes les exceptions sont fatales dans CJam. La sortie vers STDERR étant ignorée par défaut , nous pouvons l'utiliser à notre avantage.

Tous les opérateurs de CJam travaillent en supprimant zéro ou plusieurs éléments de la pile, en effectuant une tâche et en poussant zéro ou plus sur la pile. Des exceptions se produisent pendant l'exécution de la tâche. Les éléments sont donc affichés, mais rien n'est renvoyé.

Voici quelques cas d'utilisation:

  • Effacer une petite pile

    Pour effacer une pile contenant deux éléments, @peut être utilisée. @tente de faire apparaître trois éléments de pile, mais échoue après le deuxième.

    Tout autre opérateur faisant apparaître trois éléments servirait le même but.

    Voir en action ici .

  • Retrait de deux ou trois éléments de la pile

    Tout opérateur non implémenté pour ces éléments particuliers peut être utilisé pour extraire deux ou trois éléments de la pile juste avant de quitter.

    Pour faire apparaître deux éléments, bfonctionne si l’un d’eux est un caractère ou si aucun d’eux n’est un entier.

    Pour faire apparaître trois éléments, tfonctionne si aucun des deux éléments les plus bas n’est un élément itérable, l’itérateur le plus bas n’est vide ou aucun d’eux n’est un entier.

  • Sortir d'une boucle

    Il est parfois nécessaire de sortir d'une boucle lorsqu'un nombre entier devient zéro ou qu'une chaîne devient trop courte. Plutôt que de tester ces conditions, si les opérations impliquées échouent pour zéro, chaîne vide ou singletons, nous pouvons simplement laisser le programme suivre son cours naturel.

    Pour un exemple impliquant l'arithmétique, voir ici .

    Pour un exemple impliquant des chaînes, voir ici .

  • Exécution conditionnelle

    Si le code source ne doit pas être exécuté pour certains types d’entrée, nous pouvons parfois utiliser un opérateur qui échoue avec ce type d’entrée.

    Par exemple, iéchouera pour les chaînes qui ne sont pas évaluées comme un entier et ewéchouera pour les chaînes de longueur 0 ou 1.

    Voir en action ici .

Dennis
la source
5

Max / Min d'un tableau

En voici un pour les débutants!

Lorsque vous devez rechercher le nombre maximal ou minimal dans un tableau, le moyen le plus simple et le plus simple consiste à trier le tableau, puis à extraire le premier ou le dernier élément.

Donc, si le tableau est dans la variable A

A$W=

est le maximum et

A$0=

est le minimum.

Obtenir les deux en même temps est également possible

A$)\0=

Cela peut sembler évident après la lecture, mais la première tentative de quiconque a tendance à aller vers l'utilisation de e<ou e>via une itération à travers le tableau, ce qui ressemble à

A{e<}*

qui est 2 octets plus long, et même plus si vous voulez à la fois max et min.

Optimiseur
la source
Bien sûr, si le reste du tableau restant sur la pile ne vous gêne pas, vous pouvez utiliser (et )au lieu de 0=et W=.
Martin Ender
Maintenant, il y a :e<et:e>
aditsu
@aditsu Bien qu'ils ne soient pas plus courts que la pointe ci-dessus.
Optimiseur
5

Utiliser un horodatage pour les grands nombres

Si vous avez besoin d'un nombre très grand, mais arbitraire, vous utiliserez généralement une notation scientifique telle que, 9e9ou éleverez l'une des grandes variables intégrées à un pouvoir similaire, comme KK#. Cependant, si vous ne vous souciez pas du nombre réel, et qu'il n'est pas nécessaire que ce soit toujours le même (par exemple, la limite supérieure d'un nombre aléatoire), vous pouvez le faire en deux octets en utilisant

es

au lieu. Cela donne l'horodatage actuel en millisecondes et est de l'ordre de 10 12

Martin Ender
la source
3
Notez également que si vous souhaitez un grand nombre arbitraire et que vous souhaitez supprimer un nombre positif, vous pouvez l'utiliser e9.
Jimmy23013
5

Vérifier que deux chaînes / tableaux ne sont pas égaux

Parfois, vous voulez une valeur de vérité quand deux chaînes ou des tableaux ne sont pas égaux, et une valeur de faux si elles le sont. La solution évidente est deux octets:

=!

Vérifiez l'égalité et inversez le résultat. Cependant, dans certaines conditions, vous pouvez utiliser

#

Lorsque #est appliqué à deux tableaux, il recherche le deuxième tableau en tant que sous-tableau du premier (et vous donne l'index de départ du sous-tableau). Donc, si les deux tableaux sont identiques, le sous-tableau sera trouvé dès le début et donnera 0, ce qui est faux. Mais si le second tableau ne peut pas être trouvé, il donnera la -1vérité.

La raison pour laquelle nous avons besoin de conditions supplémentaires sur les deux tableaux est que cela génère également une valeur de fausseté si le deuxième tableau est un préfixe non trivial du premier, par exemple:

"abc""ab"#

donne 0bien que les cordes ne soient pas les mêmes. La condition la plus simple qui exclut ce cas est si vous savez que les deux tableaux auront la même longueur - dans ce cas, si l'un est un préfixe de l'autre, vous savez qu'ils sont égaux. Mais dans certaines circonstances, des conditions plus faibles peuvent également suffire. Par exemple, si vous savez que les chaînes sont triées, un préfixe sera toujours la première chaîne, pas la seconde.

Martin Ender
la source
5

c et entiers 16 bits

Pour ajouter (ou soustraire) des entiers 16 bits non signés avec un retour à la ligne approprié, vous pouvez utiliser +65536%ou +2G#%.

cependant,

+ci

est beaucoup plus courte. Les caractères se superposent à 65 536 points , si bien que les transtypages sur Character ( c) puis sur Long ( i) ont un effet similaire à 65536%, avec l'avantage supplémentaire que le résultat ne sera pas négatif.

Le même truc peut être utilisé pour pousser 65535 :

Wci
Dennis
la source
4

Ensembles de puissance

Supposons que vous avez un tableau et que vous voulez un tableau avec tous les sous-ensembles possibles de ce tableau. L'astuce consiste à commencer par un tableau vide, puis, pour chaque élément, à dupliquer les sous-ensembles que vous avez déjà et à y ajouter le nouvel élément (en conservant le résultat précédent là où l'élément n'a pas été ajouté ). Notez que vous devez initialiser la pile avec le cas de base, c’est-à-dire un tableau contenant uniquement un tableau vide: Cela pourrait ressembler à ceci:

[1 2 3 4 5]La\{1$f++}/

La bonne chose à ce propos est que vous pouvez exécuter immédiatement des calculs sur le sous-ensemble, éventuellement sans ajouter de caractères. Disons que vous voulez les produits de tous les sous-ensembles. Dans ce cas, le cas de base est un tableau contenant 1, et à chaque étape, vous prenez la liste précédente des produits possibles, vous la dupliquez et multipliez tout ce qui est dupliqué par le nouvel élément:

[1 2 3 4 5]1a\{1$f*+}/
Martin Ender
la source
4

Vérifier si les éléments d'une liste sont tous identiques

Je pense que cela mérite également d'être mentionné. Utilisation:

)-

Retourne la vérité si elle n'est pas identique ou la liste vide si elle est identique. Erreurs si la liste est vide.

Dans le cas où l'élément extrait pourrait être un tableau (ou une chaîne) lui-même:

)a-

Utilisez !ou !!pour obtenir des valeurs booléennes. Dans le cas où l'élément extrait pourrait être un tableau et qu'il y a au plus deux types d'éléments différents, et que vous voulez qu'il soit égal à 1 sinon tout à fait pareil, ceci est plus court:

_|,(
jimmy23013
la source
4

0= pour les cordes

Pour récupérer le premier élément d'un tableau, vous devez utiliser 0=(ou (, si cela ne vous dérange pas de laisser le reste du tableau sur la pile).

Cependant, si ce tableau est une chaîne, la conversion en caractère est suffisante.

Exemple

"xyz"c e# Pushes 'x.
Dennis
la source
Je ne vois pas pourquoi CJam ne laisse pas simplement cextraire le premier élément d'un tableau, ce qui serait plus utile et cohérent.
Esolanging Fruit
4

Faire pivoter un tableau (ou la pile) d'une unité vers la gauche

CJam a l’ opérateur de rotation à gauchem< , ce qui est normalement ce que vous devriez utiliser pour faire pivoter un tableau d’un nombre arbitraire d’unités vers la gauche.

Dans certains cas, vous pouvez également utiliser (+pour déplacer et ajouter:

[1 2 3]       (+ e# Pushes [2 3 1].
[[1] [2] [3]] (+ e# Pushes [[2] [3] 1].

Le deuxième exemple n'a pas fonctionné car le premier élément de tableaux est également un élément itérable, donc +concaténé au lieu d'être ajouté.

En outre, si vous souhaitez vider le tableau pivoté sur la pile, vous pouvez utiliser :\(réduire en permutant) de manière inconditionnelle:

[1 2 3]       :\ e# Pushes 2 3 1.
[[1] [2] [3]] :\ e# Pushes [2] [3] [1].

Tant que vous n'avez pas d'ouvert [, cette astuce peut également être utilisée pour faire pivoter la pile entière, c'est-à-dire pour amener l'élément de pile le plus bas en haut:

]:\
Dennis
la source
3

Imprimer une liste et vider la pile

Disons que votre pile contient une liste de chaînes / nombres / etc. sur le dessus et quelques autres articles supplémentaires en dessous. c'est à dire

123 "waste" ["a" "b" "rty" "print" "me" "please"]

Maintenant, vous êtes intéressé à imprimer la dernière liste seulement, alors vous faites

S*]W=

qui sort

a b rty print me please

Ce qui semble très intelligent alors que nous utilisons l’astuce consistant à vider la pile de la pile et à n’imprimer que la liste jointe avec des espaces (ce qui peut ne pas être le moyen souhaité d’imprimer une liste à la fois).

Cela peut être joué au golf plus loin!

p];

C'est 2 octets plus court !

et si vous n'avez qu'un seul élément sur la pile autre que la liste, c'est encore plus court!

p;

L' pintérêt de ce logiciel est de supprimer la plupart des éléments de la pile, de les hiérarchiser (et d'ajouter une nouvelle ligne à la fin) et de les imprimer instantanément sur STDOUT, sans attendre la fin du code.

Donc, le code ci-dessus va sortir

["a" "b" "rty" "print" "me" "please"]

qui est la représentation exacte d'une liste quand elle était en pile!

Optimiseur
la source
3

Produits cartésiens ou toutes les combinaisons possibles de deux ou plusieurs ensembles

CJam a un calculateur de produits cartésien intégré m*qui prend les deux premiers arraylists / strings sur la pile et crée toutes les paires possibles à partir de celui-ci. Par exemple

[1 2 3 4]"abc"m*

feuilles

[[1 'a] [1 'b] [1 'c] [2 'a] [2 'b] [2 'c] [3 'a] [3 'b] [3 'c] [4 'a] [4 'b] [4 'c]]

comme la pile

Mais que se passe-t-il si vous voulez toutes les combinaisons possibles de plus de 2 listes / chaînes. Vous utilisez m*cela plusieurs fois? Par exemple

[1 2 3 4][5 6]"abc"m*m*

laissera le suivant sur la pile

[[1 [5 'a]] [1 [5 'b]] [1 [5 'c]] [1 [6 'a]] [1 [6 'b]] [1 [6 'c]] [2 [5 'a]] [2 [5 'b]] [2 [5 'c]] [2 [6 'a]] [2 [6 'b]] [2 [6 'c]] [3 [5 'a]] [3 [5 'b]] [3 [5 'c]] [3 [6 'a]] [3 [6 'b]] [3 [6 'c]] [4 [5 'a]] [4 [5 'b]] [4 [5 'c]] [4 [6 'a]] [4 [6 'b]] [4 [6 'c]]]

Notez que les produits sont toujours des paires, l'un des éléments étant une paire elle-même. Ce n'est pas prévu et nous voulons des combinaisons aplaties.

Il y a un moyen facile de le faire. Il vous suffit d’envelopper chaque liste que vous voulez pour votre produit cartésien dans un tableau, de créer des produits cartésiens deux à deux et de l’aplatir à chaque fois:

[1 2 3 4][5 6]"abc"]{m*{(+}%}*

Cela laisse

[['a 5 1] ['b 5 1] ['c 5 1] ['a 6 1] ['b 6 1] ['c 6 1] ['a 5 2] ['b 5 2] ['c 5 2] ['a 6 2] ['b 6 2] ['c 6 2] ['a 5 3] ['b 5 3] ['c 5 3] ['a 6 3] ['b 6 3] ['c 6 3] ['a 5 4] ['b 5 4] ['c 5 4] ['a 6 4] ['b 6 4] ['c 6 4]]

sur la pile.

Voulez-vous que l'ordre soit maintenu? , échangez simplement le avant d'ajouter l'élément sauté dans le tableau. c'est à dire

{m*{(\+}%}*

Vous voulez seulement des permutations?

{m*{(+$}%_&}*

Vous voulez seulement des éléments uniques dans les combinaisons?

{m*{(+_&}%}*

C'est tous les gens. pour l'instant .

Optimiseur
la source
1
Maintenant, vous pouvez aussi faire ]:m*:e_, avec n'importe quel nombre de tableaux
Aditsu
3

Opérant sur des cordes

Parfois, si vous travaillez avec une structure de données complexe, alors que les éléments qu’elle contient sont simples, la conversion en chaînes peut être utile.

Par exemple, si vous souhaitez obtenir le premier ou les derniers éléments dans un tableau de bits 2D, sans vous soucier du type renvoyé, sA<enregistrez un octet à partir de 0=A<ou :+A<.

Ou si vous souhaitez modifier certains bits de l'entrée, vous pouvez modifier la chaîne avant de l'évaluer.

Ou si vous avez cette structure et que vous voulez la convertir en une simple liste:

[[[[[[[[[1]2]3]4]5]6]7]8]9]

Vous pouvez le faire avec plusieurs personnages de différentes manières:

[a{~)\}h;]W%

Mais cela peut être beaucoup plus court avec des chaînes:

s:~

C'est plus court même s'il peut avoir des nombres avec plus d'un chiffre:

[`La`-~]

Ou:

`']-~]

Si vous n'avez pas besoin d'un autre tableau contenant plusieurs de ces tableaux.

jimmy23013
la source
Il y a e_maintenant
Aditsu
@aditsu Voir cette réponse et ce commentaire . Parfois sça marche encore mieux.
jimmy23013
Bien sûr, lorsque vous pouvez travailler directement avec une chaîne, c'est plus court.
Aditsu
3

Utiliser Nau lieu deLa

Dans de nombreux cas, vous avez besoin de quelque chose d'initialisée dans un tableau contenant un tableau vide comme élément unique, ce qui est Laapparemment inutile d'un octet de plus.

Dans de nombreux cas, vous devez également ajouter une nouvelle ligne après chaque élément avant l'impression, ce qui pourrait ressembler à Noou N*.

Mais si les deux sont vrais, vous pouvez parfois découvrir que vous pouvez simplement initialiser le tableau N, dont le seul caractère est le caractère de nouvelle ligne. Assurez-vous de ne prémunir que les éléments du reste de votre code, et la première chose à ajouter est toujours un caractère ou un tableau. Ou seulement ajouter, si une nouvelle ligne de premier plan est acceptable et que cela le raccourcit.

Parfois, Sfonctionne également si vous devez séparer la sortie avec des espaces.

Dans des cas plus rares, l'élément initial doit être une chaîne. Mais vous pouvez toujours utiliser Nace qui pourrait être plus court que d'ajouter la nouvelle ligne par la suite.

jimmy23013
la source
2

Fractionnement sur une ou plusieurs occurrences

Disons que vous avez une chaîne "abbcdbbfghbdbb"et que vous voulez la séparerb

"abbcdbbfghbdbb"'b/

Cela laisse sur la pile:

["a" "" "cd" "" "fgh" "d" "" ""]

Remarquez les chaînes vides? Celles-ci sont là parce que deux bétaient ensemble et que rien ne les séparait. Parfois, vous voulez éviter cela. Vous pouvez le faire en

"abbcdbbfghbdbb"'b/La-

ou filtrer les chaînes vides

"abbcdbbfghbdbb"'b/{},

mais c'est 3 octets supplémentaires.

Un opérateur un peu moins connu pour ce cas d'utilisation particulier est %. En plus de mod, mapper et diviser en fonction du nombre ( "abcd"2%= "ac"), vous %pouvez également diviser des chaînes / tableaux. Donc, pour le cas d'utilisation ci-dessus:

"abbcdbbfghbdbb"'b%

va partir

["a" "cd" "fgh" "d"]

sur la pile.

Merci pour @ user23013 de l'avoir souligné dans l'une de mes réponses aujourd'hui.

Optimiseur
la source
Je pense que cela devrait être nommé "also learn GolfScript", qui a de meilleurs exemples dans la documentation.
jimmy23013
@ user23013 mais nous ne sommes jamais sûrs de savoir si tout est similaire à GS et ce qui ne l’est pas.
Optimiseur
2

Utilisez fold / réduire comme infixe poureach

Nous avons :xcomme raccourci pour {x}%et ou {x}*(selon que ce xsoit unaire ou binaire). Malheureusement, il n’existe aucun opérateur infixe équivalent à raccourcir {x}/. Cependant, très souvent lorsque nous le faisons {x}/, il xs’agit en fait d’un opérateur binaire qui modifie de façon répétée l’élément se trouvant en dessous de la pile. Si tel est le cas et que cet élément n'est pas un tableau, nous pouvons enregistrer un octet en abusant de fold / red comme suit:

5 [1 2 3 4]{-}/  e# Gives -5
5 [1 2 3 4]+:-

Cela fonctionne parce que fold laisse toujours le premier élément intact. Malheureusement, il n'enregistre pas d'octet, lorsque l'élément modifié est un tableau, car son ajout le décompresserait. Cependant, vous avez parfois la chance que votre tableau contienne déjà cet élément à l'avant, auquel cas réduire devrait être pris en compte (au lieu de supprimer manuellement l'élément avant de l'utiliser {}/sur le reste).

Martin Ender
la source
2

imprimer et imprimer

CJAM a l' printopérateur: o. Cela fonctionne, mais stack imprime immédiatement après que tout le code ait été exécuté. Vous pouvez l'arrêter si vous videz la pile à la fin du programme. Il suffit de mettre ceci à la fin:

];

Pour imprimer, vous pouvez utiliser oNoou p(fonctionne comme `oNo)

nom d'utilisateur.ak
la source
3
Il y a une plus grande différence entre oet p. pcommence par convertir l'élément à imprimer en une représentation sous forme de chaîne non ambiguë. pest équivalent à l'exécution ​`oNo.
Dennis