-join("$args"-split'\b'|%{(,$(,$_[0]*$n+$_))[!!($n=$($_-1))]})
Попробуйте онлайн!
Сломать
Какой беспорядок!
Начиная с $args
, который является массивом из одного элемента, содержащего строку RLE, я добавляю фактическую строку, заключая ее в кавычки.
Затем разделите его по границе слова ( \b
в регулярном выражении). Это даст мне массив строк, где каждый элемент является либо номером, либо токеном (ами) BF, которые идут после числа. Таким образом , в примере, первые 4 элемента этого массива являются сплит 10
, +]>+>
, 3
,+>
(все строки).
Затем я передаю это в ForEach-Object
( %
) для работы с каждым элементом .
Середина - хорошо известный гольфизм PowerShell с изюминкой; по сути это троичный оператор DIY, в котором вы создаете массив из 2 элементов, а затем индексируете его, используя логическое выражение, которое вы хотите проверить, в результате чего ложный результат дает вам элемент 0, а истинный результат дает вам элемент 1.
В этом случае я фактически создаю массив из одного элемента с унарным ,
оператором запятой , потому что я не хочу выводить в истинном случае.
Сначала давайте посмотрим на индексатор, хотя он будет выполнен позже.
Идея этого в том, что $_
(текущий элемент) может быть допустимым числом или какой-либо другой строкой. Если это число, я хочу $n
быть значением этого числа минус 1 (как число, а не строка). Если это не так, я хочу $n
быть ложным.
PowerShell обычно пытается привести правое значение к типу левой стороны, но это может зависеть от операции. Кроме того, "10"+5
даст вам новую строку "105"
, тогда как 10+"5"
даст вам целое число (15
).
Но строки не могут быть вычтены, поэтому вместо этого PowerShell может автоматически вывести числовое значение со строкой в левой части вычитания, поэтому "10"-5
дает5
.
Итак, я начинаю с того $_-1
, что $_
я получу желаемое число, когда на самом деле это число, но когда это не так, я ничего не получаю. На первый взгляд «ничто» не является ложным, но проблема в том, что он останавливает выполнение этого присваивания, поэтому $n
сохраняет свое прежнее значение; не то, что я хочу!
Если я обернуть его в подвыражения, а затем , когда это не удается, я получаю свою ценность falsey: $($_-1)
.
Все это присваивается, $n
и поскольку это присваивание само заключено в круглые скобки, значение, которое было присвоено, $n
также передается в конвейер.
Поскольку я использую его в индексаторе и хочу, 1
чтобы преобразование прошло успешно, я использую два логических not
выражения !!
для преобразования этого значения в логическое. Успешное преобразование чисел заканчивается как истина, в то время как ничтожность не дает нам того сладкого, сладкого, 0
что позволяет вернуть единственный элемент в этом поддельном троичном массиве.
Возвращаясь к этому массиву, элемент выглядит так: $("$($_[0])"*$n*$_)
$(,$_[0]*$n+$_)
"$($_[0])"
- это надоедливо долгий способ получить первый символ текущего элемента (скажем, получить +
из +[>+
), но как строку, а не как [char]
объект. Мне нужно, чтобы это была строка, потому что я могу умножить строку на число, чтобы дублировать ее, но я не могу сделать это с символом.
На самом деле мне удалось сохранить 4 символа, используя [char]
массив вместо строки (используя другую унарную запятую ,
), поэтому я смог удалить кавычки и дополнительное подвыражение. Я могу умножить массив, чтобы дублировать его элементы. И поскольку весь результат этой итерации в любом случае оказывается массивом, и его необходимо-join
редактировать, использование массива здесь не требует дополнительных затрат.
Затем я умножаю этот массив строк на $n
, чтобы дублировать его $n
раз. Напомним, что это $n
может быть $null
или это может быть значение предыдущих цифр минус один.
Затем +$_
добавляет текущий элемент в конец дублированного первого символа этого элемента. Вот почему $n
минус один.
Таким образом, в 10+[>+
итоге получается $n
равным 9, затем мы делаем 9 +
и добавляем это обратно в +[>+
строку, чтобы получить необходимые 10, а также другие отдельные элементы для поездки.
Элемент обернут в подвыражение, $()
потому что, когда $n
есть $null
, все выражение терпит неудачу, таким образом создание массива терпит неудачу, таким образом, индексатор никогда не выполняется, поэтому $n
никогда не назначается.
Причина, по которой я использовал этот троичный трюк, заключается в одной из его особенностей: в отличие от реального троичного оператора, выражения, определяющие элементы , оцениваются независимо от того, «выбраны» они или нет, и сначала в этом отношении.
Поскольку мне нужно назначить, а затем использовать $n
на отдельных итерациях, это полезно. Значение элемента троичного массива оценивается с использованием значения предыдущей итерации $n
, затем индексатор переназначает$n
для текущей итерации.
Таким образом, ForEach-Object
циклы в итоге выводят все, что должны (куча ошибок, которые мы игнорируем), но в виде массива новых строк.
Так что все это заключено в круглые скобки, а затем предшествует унарный, -join
чтобы получить строку вывода.