-join("$args"-split'\b'|%{(,$(,$_[0]*$n+$_))[!!($n=$($_-1))]})
Pruébalo en línea!
Descompostura
¡Que desastre!
A partir de $args
, que es una matriz de un solo elemento que contiene la cadena RLE, estoy forzando una cadena real envolviéndola entre comillas.
Luego divídalo por límite de palabra (\b
en expresiones regulares). Eso me dará una serie de cadenas, donde cada elemento es un número o los tokens BF que vienen después del número. Entonces, en el ejemplo, los primeros 4 elementos de esta matriz dividida son10
, +]>+>
, 3
,+>
(todos son cadena).
Luego, canalizo eso en ForEach-Object
(%
) para tratar con cada elemento .
El centro es un conocido golfismo de PowerShell, con un giro; Es esencialmente un operador ternario de bricolaje, en el que crea una matriz de 2 elementos y luego lo indexa utilizando la expresión booleana que desea probar, por lo que un resultado falso le da el elemento 0 y un resultado verdadero le da el elemento 1.
En este caso, en realidad creo una matriz de un solo elemento con la coma unaria ,
, porque no quiero salida en el caso verdadero.
Primero echemos un vistazo al indexador, aunque se ejecute más tarde.
La idea de esto es que $_
(el elemento actual) podría ser un número válido o alguna otra cadena. Si es un número, quiero $n
ser el valor de ese número menos 1 (como un número, no una cadena). Si no es así, quiero$n
ser falso.
PowerShell generalmente intenta forzar el valor de la mano derecha al tipo del lado izquierdo, pero puede depender de la operación. Además, "10"+5
le daría una nueva cadena "105"
, mientras que 10+"5"
le dará un entero ( 15
).
Pero las cadenas no se pueden restar, por lo que PowerShell puede inferir el valor numérico automáticamente con una cadena en el lado izquierdo de la resta, por lo tanto "10"-5
da5
.
Entonces, empiezo con $_-1
, lo que me dará el número que quiero cuando en $_
realidad es un número, pero cuando no lo es, no obtengo nada. En la superficie, "nada" es falsey, pero el problema es que detiene la ejecución de esa tarea, así que$n
lo que conservará su valor anterior; no es lo que quiero!
Si lo envuelvo en una subexpresión, cuando falla, obtengo mi valor falsey: $($_-1)
.
Todo eso se asigna $n
y dado que esa asignación está envuelta entre paréntesis, el valor que se asignó a$n
también se pasa a la canalización.
Como lo estoy usando en el indexador y quiero que, 1
si la conversión se realizó correctamente, utilizo dos not
expresiones booleanas !!
para convertir este valor en booleano. Una conversión de números exitosa termina siendo cierta, mientras que la nada falsa nos da ese dulce, dulce0
que permite devolver el único elemento en ese falso conjunto ternario.
Volviendo a esa matriz, el elemento es este: $("$($_[0])"*$n*$_)
$(,$_[0]*$n+$_)
"$($_[0])"
- esta es una forma molestamente larga de obtener el primer carácter del elemento actual (digamos, obteniendo +
de +[>+
), pero como una cadena y no como un[char]
objeto. Necesito que sea una cadena porque puedo multiplicar una cadena por un número para duplicarla, pero no puedo hacerlo con un carácter.
En realidad, logré guardar 4 caracteres usando una [char]
matriz en lugar de una cadena (usando otra coma unitaria ,
), por lo que pude eliminar las comillas y la subexpresión adicional. I puedo multiplicar una matriz para duplicar sus elementos. Y dado que el resultado completo de esta iteración termina siendo una matriz de todos modos y debe ser-join
editado, el uso de una matriz aquí no conlleva ningún costo adicional.
Luego, multiplico esa matriz de cadenas por $n
, para duplicarla $n
veces. Recuerde que $n
podría ser $null
o podría ser el valor de los dígitos anteriores menos uno.
Luego +$_
agrega el elemento actual al final del primer carácter duplicado de ese elemento. Por eso $n
es menos uno.
De esta manera, 10+[>+
termina $n
igual a 9, luego hacemos 9 +
y agregamos eso de nuevo a la+[>+
cadena para obtener el 10 requerido, más los otros elementos individuales a lo largo del recorrido.
El elemento está envuelto en una subexpresión $()
porque cuando $n
es así $null
, la expresión completa falla, por lo que la creación de la matriz falla, por lo que el indexador nunca se ejecuta, por lo que $n
nunca se asigna.
La razón por la que este truco utilizado ternario es debido a una de sus peculiaridades: a diferencia de un operador ternario reales, las expresiones que definen los elementos no se evalúan si son o no son "seleccionados", y la primera para el caso.
Como necesito asignar y luego usar $n
en iteraciones separadas, esto es útil. El valor del elemento de matriz ternario se evalúa con el $n
valor de la iteración anterior , luego el indexador vuelve a asignar$n
para la iteración actual.
Entonces, los ForEach-Object
bucles terminan generando todo lo que se supone que debe hacer (un montón de errores que ignoramos), pero como una serie de nuevas cadenas.
De modo que todo está entre paréntesis y luego precedido por unario -join
para dar la cadena de salida.