-join("$args"-split'\b'|%{(,$(,$_[0]*$n+$_))[!!($n=$($_-1))]})
Спробуйте в Інтернеті!
Зламатися
Який безлад!
Починаючи з $args
, що представляє собою єдиний масив елементів, що містить рядок RLE, я змушую його до фактичного рядка, загортаючи його в лапки.
Потім розділіть його за межею слова ( \b
в регулярному виразі). Це дасть мені масив рядків, де кожен елемент є або числом, або BF-маркерами, які надходять після числа. Таким чином , в прикладі, перші 4 елемента цього масиву є спліт 10
, +]>+>
, 3
,+>
(всі рядки).
Далі я передаю це в ForEach-Object
( %
) для обробки кожного елемента .
Середина - добре відомий гольфізм PowerShell, з поворотом; це, по суті, потрійний оператор DIY, в якому ви створюєте масив з двома елементами, а потім індексуєте його за допомогою булевого виразу, яке ви хочете перевірити, при цьому помилковий результат дає вам елемент 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
щоб дати вихідний рядок.