-join("$args"-split'\b'|%{(,$(,$_[0]*$n+$_))[!!($n=$($_-1))]})
Essayez-le en ligne!
Panne
Quel bordel!
A partir de $args
, qui est un tableau d'éléments unique contenant la chaîne RLE, je force dans une chaîne réelle en l'encapsulant entre guillemets.
Ensuite, divisez-le par limite de mot ( \b
en regex). Cela me donnera un tableau de chaînes, où chaque élément est soit un nombre, soit le ou les jetons BF qui viennent après le nombre. Ainsi , dans l'exemple, les 4 premiers éléments de ce tableau de répartition sont 10
, +]>+>
, 3
,+>
(tous sont string).
Ensuite, je redirige cela dans ForEach-Object
( %
) pour gérer chaque élément .
Le milieu est un golfisme PowerShell bien connu, avec une touche; il s'agit essentiellement d'un opérateur ternaire bricolage, dans lequel vous créez un tableau à 2 éléments, puis l'indexez à l'aide de l'expression booléenne que vous souhaitez tester, un faux résultat vous donnant l'élément 0 et un vrai résultat vous donnant l'élément 1.
Dans ce cas, je crée en fait un tableau à élément unique avec la virgule unaire ,
, car je ne veux pas de sortie dans le vrai cas.
Examinons d'abord l'indexeur, même s'il est exécuté plus tard.
L'idée est que $_
(l'élément actuel) peut être soit un nombre valide, soit une autre chaîne. Si c'est un nombre, je veux $n
être la valeur de ce nombre moins 1 (comme un nombre, pas une chaîne). Si ce n'est pas le cas, je veux $n
être faux-y.
PowerShell essaie généralement de contraindre la valeur de droite au type du côté gauche, mais cela peut dépendre de l'opération. Par ailleurs, "10"+5
vous donnera une nouvelle chaîne "105"
, tandis que 10+"5"
vous donnera un entier ( 15
).
Mais les chaînes ne peuvent pas être soustraites.Par conséquent, PowerShell peut déduire automatiquement la valeur numérique avec une chaîne sur le côté gauche de la soustraction, donc "10"-5
donne5
.
Donc, je commence par $_-1
, ce qui me donnera le nombre que je veux quand $_
c'est en fait un nombre, mais quand ce n'est pas le cas, je ne reçois rien. En surface, "rien" n'est falsey, mais le problème est qu'il arrête l'exécution de cette affectation, il $n
conservera donc sa valeur précédente; pas ce que je veux!
Si je l'enveloppe dans une sous-expression, puis quand il échoue, j'obtiens ma valeur de falsey: $($_-1)
.
Que tout est attribué à $n
et puisque cette affectation est elle-même enveloppée entre parenthèses, la valeur qui a été affectée à$n
également transmise au pipeline.
Étant donné que je l'utilise dans l'indexeur et que je souhaite 1
que la conversion réussisse, j'utilise deux not
expressions booléennes !!
pour convertir cette valeur en booléen. Une conversion de nombre réussie se termine comme vraie, tandis que le néant de falsey nous donne ce doux, doux 0
qui permet de retourner le seul élément de ce faux tableau ternaire.
Pour en revenir à ce tableau, l'élément est le suivant: $("$($_[0])"*$n*$_)
$(,$_[0]*$n+$_)
"$($_[0])"
- c'est un moyen ennuyeusement long d'obtenir le premier caractère de l'élément courant (disons, en +
provenance de +[>+
), mais en tant que chaîne et non en tant [char]
qu'objet. J'ai besoin que ce soit une chaîne car je peux multiplier une chaîne par un nombre pour la dupliquer, mais je ne peux pas le faire avec un caractère.
En fait, j'ai réussi à enregistrer 4 caractères en utilisant un [char]
tableau au lieu d'une chaîne (en utilisant une autre virgule unaire ,
), j'ai donc pu supprimer les guillemets et la sous-expression supplémentaire. Je peux multiplier un tableau pour dupliquer ses éléments. Et puisque le résultat entier de cette itération finit par être un tableau de toute façon et doit être-join
modifié, l'utilisation d'un tableau ici n'entraîne aucun coût supplémentaire.
Ensuite, je multiplie ce tableau de chaînes par $n
, pour le dupliquer $n
fois. Rappelez-vous que cela $n
pourrait être $null
ou ce pourrait être la valeur des chiffres précédents moins un.
+$_
Ajoute ensuite l'élément en cours à la fin du premier caractère dupliqué de cet élément. C'est pourquoi$n
est moins un.
De cette façon, 10+[>+
finit par $n
égal à 9, puis nous faisons 9 +
et ajoutons cela à la+[>+
chaîne pour obtenir les 10 requis, ainsi que les autres éléments individuels le long du trajet.
L'élément est encapsulé dans une sous $()
- expression parce que quand $n
est $null
, l'expression entière échoue, donc la création du tableau échoue, donc l'indexeur ne s'exécute jamais, donc $n
n'est jamais attribué.
La raison pour laquelle j'ai utilisé cette astuce ternaire est due à l'une de ses particularités: contrairement à un véritable opérateur ternaire, les expressions qui définissent les éléments ne s'évaluer si oui ou non ils sont « sélectionnés », et d' abord pour cette question.
Étant donné que je dois attribuer puis utiliser $n
sur des itérations distinctes, cela est utile. La valeur de l'élément de tableau ternaire est évaluée avec la $n
valeur de l'itération précédente , puis l'indexeur est réaffecté $n
pour l'itération en cours.
Ainsi, les ForEach-Object
boucles finissent par produire tout ce qu'elles sont censées (un tas d'erreurs que nous ignorons), mais comme un tableau de nouvelles chaînes.
Donc, tout cela est entouré de parenthèses, puis précédé d'unaire -join
pour donner la chaîne de sortie.