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.
Réponses:
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-2
au lieu de1
. Le plus souvent, vous voulez ce dernier. La solution naïve consiste à appliquer modulo, à ajouter le diviseur une fois et à appliquer à nouveau modulo: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 à:
Appliqué à
-5
, cela donne1
comme 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:
Pour le cas particulier d’
65536 == 2^16
un autre octet, vous pouvez enregistrer en utilisant le comportement d’emballage du type de caractère:la source
Pousser des plages de caractères concaténés
La chaîne contenant tous les chiffres
"0123456789"
peut être écrite commeLes lettres ASCII majuscules (
A-Z
) peuvent être insérées commequi 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 commequi 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:'[,
crée la plage de tous les caractères ASCII jusqu'à Z ,_el
cré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:Une façon tout aussi courte de pousser cette chaîne utilise uniquement des différences symétriques:
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
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: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
qui imprimera ( permalien ) les éléments suivants:
Cela signifie que
a le même effet que
qui ne peut être utilisé qu'avec une pile vide sans préfixe a
[
.la source
É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:
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:C'est un octet plus court.
Bloc-? avec une instruction if vide est toujours un no-go. Par exemple,
est deux octets plus long que
Si vous avez plutôt
et la chose que vous vérifiez est un entier non négatif, vous pouvez le faire
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:
la source
!)/
etg)/
sont plus courts dans les exemples.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
code0
si l’entier de la pile est 0 ,code1
s’il s’agit de 1 , etcode2
s’il est 2 , nous pouvons soit utiliserou
ou
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
,code1
etcode2
avoir des longueurs L 0 , L 1 et L 2 , respectivement.Si L 0 = L 1 ≥ L 2
peut être utilisé à la place, où
L
est 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 ,
peut être utilisé à la place.
>
supprime 0, 1 ou 2 éléments du début de la chaîne et3%
extrait tous les trois éléments (en commençant par le premier).la source
"code0code1code2"5/=~
? Cela me semble beaucoup plus simple et c'est la même longueur.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 comme2,
.[1 0]
peut être écrit commeYYb
(c'est-à-dire 2 en binaire).[1 1]
peut être écrit commeZYb
(c'est-à-dire 3 en binaire).[[0 1] [1 0]]
peut être écrite comme2e!
.[LL]
peut être écrit commeSS/
(divisant un seul espace par des espaces)."\"\""
peut être écrit commeL`
."{}"
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]
seraitE4b
(14 en base 4).Dans des cas encore plus rares, vous pouvez même trouver
mf
utile l' opérateur de factorisation . Eg[2 7]
estEmf
.N'hésitez pas à étendre cette liste si vous rencontrez d'autres exemples.
la source
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:
(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.la source
\;
ne ferait apparaître que l'élément en dessous du TOS. Vouliez-vous dire;;
?e
et des pouvoirs de dixComme dans beaucoup d'autres langues, vous pouvez écrire à la
1e3
place de1000
CJam.Cela fonctionne pour les bases non entières et même pour les exposants non entiers. Par exemple,
1.23e2
appuie sur 123.0 et1e.5
sur 3.1622776601683795 (racine carrée de 10 ).Ce qui est pas évident immédiatement que
1e3
est en fait deux jetons:1
pousse le nombre entier 1 sur la pile.e3
le multiplie par 1000 .Pourquoi est-ce important?
Vous pouvez faire appel
e<numeric literal>
à quelque chose qui est déjà sur la pile.Vous pouvez mapper
e<numeric literal>
sur un tableau.la source
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:
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
mh
sont exécutés en laissant sqrt (x 1 2 + x 2 2 ) sur la pile.Ensuite, x 3 est poussé et
mh
est exécuté à nouveau, laissantsqrt (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.
:mhz
fonctionne sans condition. (Merci à @ MartinBüttner pour l'avoir signalé.)J'ai utilisé cette astuce pour la première fois dans cette réponse .
la source
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
).n
est la base etl
est 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:
0b
extrait le dernier élément et le convertit en entier. Fonctionne commeW=i
et 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.1b
renvoie 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%:c
convertit un caractère en une chaîne de fins de ligne et de tabulations, qui peut être reconvertie avec2bc
. 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.)La méthode similaire fonctionne avec n'importe quel ensemble d'
n
entiers ayant des valeurs différentes modn
, si vous pouvez trouver un moyen de vous débarrasser du chiffre le plus significatif.la source
Utiliser
$
comme ternaire siLorsque 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 C
sur la pile, vous pouvez exécuterau lieu de
copier
B
siC
est la vérité etA
autrement.Si
C
est un booléen réel (0
ou1
), vous pouvez exécuterau lieu de
copier
A
siC
est la vérité etB
autrement.la source
Carte pour les listes imbriquées
Disons que vous avez une liste imbriquée, comme une matrice:
Ou un tableau de chaînes:
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%
.f
est "mapper avec un paramètre supplémentaire", donc il mappera%
sur la liste externe, en utilisant le bloc comme second paramètre:Enregistre deux octets.
Une autre astuce pour faire quelque chose
for (i=0; i<5; ++i) for (j=0; j<5; ++j) {...}
est commeL'extérieur
f
mappera sur la première plage, fournissant la deuxième plage comme paramètre supplémentaire. Mais maintenant, si vous utilisez àf
nouveau, seul l'élément de pile supérieur est un tableau. Vous pouvez doncf
mapper 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é aveci
etj
sur 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):
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
f
gé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
f
et:
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: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:
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:
Ou un bloc avec quelques ruses:
la source
f~
...f
attend un opérateur binaire,~
est unaire; est-ce que tu voulais peut-être:~
? En outre, nous pouvons en discuter en chatUnhandled char after ':': :
( lien )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é: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: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:
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é:la source
Utiliser
&
pour vérifier si un élément est dans une listePour
Vous pouvez utiliser
au lieu de cela, qui renvoie 0/1 et vérité / falsey respectivement.
la source
z
et tableaux non rectangulairesL'opérateur zip
z
transpose 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
zip
fonctions intégrées de, par exemple, Python (tronque les lignes à la même longueur) ou Ruby (complète les lignes avecnil
) - CJam convertit simplement les colonnes du tableau en lignes, en ignorant leur longueur et les lacunes.Par exemple, zipper le tableau
est équivalent à zipper le tableau
ou le tableau
comme les trois actions poussent
sur la pile.
Bien que cela ne signifie pas qu'il
z
ne 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:
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é:
Avec un tableau de chaînes, nous pouvons calculer la longueur de la plus longue chaîne comme ceci:
Cependant, en compressant et en calculant le nombre de lignes du résultat, nous pouvons économiser trois octets:
1 Si l'une des "lignes" de A n'est pas itérable, traitez-
z
les comme des singletons, afin que la compression fonctionne pour des tableaux arbitraires.la source
z
convertir 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.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,
b
fonctionne 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,
t
fonctionne 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 etew
échouera pour les chaînes de longueur 0 ou 1.Voir en action ici .
la source
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
est le maximum et
est le minimum.
Obtenir les deux en même temps est également possible
Cela peut sembler évident après la lecture, mais la première tentative de quiconque a tendance à aller vers l'utilisation de
e<
oue>
via une itération à travers le tableau, ce qui ressemble àqui est 2 octets plus long, et même plus si vous voulez à la fois max et min.
la source
(
et)
au lieu de0=
etW=
.:e<
et:e>
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,
9e9
ou éleverez l'une des grandes variables intégrées à un pouvoir similaire, commeKK#
. 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 utilisantau lieu. Cela donne l'horodatage actuel en millisecondes et est de l'ordre de 10 12
la source
e9
.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 donnera0
, ce qui est faux. Mais si le second tableau ne peut pas être trouvé, il donnera la-1
vé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:
donne
0
bien 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.la source
c
et entiers 16 bitsPour ajouter (ou soustraire) des entiers 16 bits non signés avec un retour à la ligne approprié, vous pouvez utiliser
+65536%
ou+2G#%
.cependant,
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 :
la source
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:
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:la source
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:
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:la source
0=
pour les cordesPour 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
la source
c
extraire le premier élément d'un tableau, ce qui serait plus utile et cohérent.Faire pivoter un tableau (ou la pile) d'une unité vers la gauche
CJam a l’ opérateur de rotation à gauche
m<
, 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: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: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:la source
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
Maintenant, vous êtes intéressé à imprimer la dernière liste seulement, alors vous faites
qui sort
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!
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!
L'
p
inté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
qui est la représentation exacte d'une liste quand elle était en pile!
la source
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 exemplefeuilles
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 exemplelaissera le suivant sur la pile
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:
Cela laisse
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
Vous voulez seulement des permutations?
Vous voulez seulement des éléments uniques dans les combinaisons?
C'est tous les gens. pour l'instant .
la source
]:m*:e_
, avec n'importe quel nombre de tableauxOpé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 de0=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:
Vous pouvez le faire avec plusieurs personnages de différentes manières:
Mais cela peut être beaucoup plus court avec des chaînes:
C'est plus court même s'il peut avoir des nombres avec plus d'un chiffre:
Ou:
Si vous n'avez pas besoin d'un autre tableau contenant plusieurs de ces tableaux.
la source
e_
maintenants
ça marche encore mieux.Utiliser
N
au 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
La
apparemment 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 à
No
ouN*
.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,
S
fonctionne é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
Na
ce qui pourrait être plus court que d'ajouter la nouvelle ligne par la suite.la source
Fractionnement sur une ou plusieurs occurrences
Disons que vous avez une chaîne
"abbcdbbfghbdbb"
et que vous voulez la séparerb
Cela laisse sur la pile:
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 enou filtrer les chaînes vides
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:va partir
sur la pile.
Merci pour @ user23013 de l'avoir souligné dans l'une de mes réponses aujourd'hui.
la source
Utilisez fold / réduire comme infixe poureach
Nous avons
:x
comme raccourci pour{x}%
et ou{x}*
(selon que cex
soit unaire ou binaire). Malheureusement, il n’existe aucun opérateur infixe équivalent à raccourcir{x}/
. Cependant, très souvent lorsque nous le faisons{x}/
, ilx
s’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: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).la source
imprimer et imprimer
CJAM a l'
print
opé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
oNo
oup
(fonctionne comme`oNo
)la source
o
etp
.p
commence par convertir l'élément à imprimer en une représentation sous forme de chaîne non ambiguë.p
est équivalent à l'exécution`oNo
.