-join("$args"-split'\b'|%{(,$(,$_[0]*$n+$_))[!!($n=$($_-1))]})
Hãy thử trực tuyến!
Phá vỡ
Thật là một mớ hỗn độn!
Bắt đầu từ $args
, đó là một mảng phần tử duy nhất chứa chuỗi RLE, tôi buộc vào một chuỗi thực tế bằng cách gói dấu ngoặc kép.
Sau đó phân chia nó theo ranh giới từ ( \b
trong regex). Điều đó sẽ cho tôi một chuỗi các chuỗi, trong đó mỗi phần tử là một số hoặc mã thông báo BF nằm sau số đó. Vì vậy, trong ví dụ này, 4 yếu tố đầu tiên của mảng phân chia này là 10
, +]>+>
, 3
,+>
(tất cả đều string).
Tiếp theo, tôi chuyển nó thành ForEach-Object
( %
) để xử lý từng phần tử .
Giữa là một sân golf PowerShell nổi tiếng, với một twist; về cơ bản, nó là một toán tử ternary DIY, trong đó bạn tạo một mảng 2 phần tử rồi lập chỉ mục cho nó bằng biểu thức boolean mà bạn muốn kiểm tra, theo đó một kết quả sai cung cấp cho bạn phần tử 0 và kết quả đúng cung cấp cho bạn phần tử 1.
Trong trường hợp này, tôi thực sự tạo một mảng phần tử duy nhất với toán tử dấu phẩy đơn ,
, vì tôi không muốn đầu ra trong trường hợp thực.
Trước tiên, hãy nhìn vào bộ chỉ mục, mặc dù nó được thực hiện sau.
Ý tưởng của điều này là $_
(phần tử hiện tại) có thể là một số hợp lệ hoặc một số chuỗi khác. Nếu đó là một số, tôi muốn $n
là giá trị của số đó trừ đi 1 (dưới dạng một số, không phải là một chuỗi). Nếu không, tôi muốn$n
là false-y.
PowerShell thường cố gắng ép giá trị bên phải vào loại bên trái, nhưng nó có thể phụ thuộc vào hoạt động. Ngoài ra, "10"+5
sẽ cung cấp cho bạn một chuỗi mới "105"
, trong khi đó 10+"5"
sẽ cung cấp cho bạn một số nguyên ( 15
).
Nhưng các chuỗi không thể được trừ để thay vào đó PowerShell có thể tự động suy ra giá trị số bằng một chuỗi ở phía bên trái của phép trừ, do đó "10"-5
sẽ cho 5
.
VÌ VẬY, tôi bắt đầu với $_-1
, nó sẽ cho tôi con số tôi muốn khi $_
thực sự là một con số, nhưng khi nó không nhận được gì. Nhìn bề ngoài, "không có gì" là falsey, nhưng vấn đề là dừng thực thi nhiệm vụ đó, vì vậy $n
sẽ giữ lại giá trị trước đó của nó; không phải những gì tôi muốn!
Nếu tôi gói nó trong một biểu hiện phụ, thì khi nó thất bại, tôi nhận được giá trị falsey của mình: $($_-1)
.
Tất cả được gán cho $n
và vì chính nhiệm vụ đó được gói trong ngoặc đơn, giá trị được gán $n
cũng được chuyển qua đường ống dẫn.
Vì tôi đang sử dụng nó trong trình lập chỉ mục và tôi muốn 1
nếu việc chuyển đổi thành công, tôi sử dụng hai not
biểu thức boolean !!
để chuyển đổi giá trị này thành boolean. Một chuyển đổi số thành công kết thúc là đúng, trong khi hư vô chim ưng cho chúng ta sự ngọt ngào, ngọt ngào0
đó cho phép trả lại yếu tố duy nhất trong mảng ternary giả đó.
Quay trở lại mảng đó, phần tử là thế này: $("$($_[0])"*$n*$_)
$(,$_[0]*$n+$_)
"$($_[0])"
- đây là một cách dài khó chịu để có được ký tự đầu tiên của phần tử hiện tại (giả sử, lấy +
từ +[>+
), nhưng là một chuỗi chứ không phải là một [char]
đối tượng. Tôi cần nó là một chuỗi bởi vì tôi có thể nhân một chuỗi với một số để nhân đôi chuỗi đó, nhưng tôi không thể làm điều đó với một ký tự.
Trên thực tế, tôi đã quản lý để lưu 4 ký tự bằng cách sử dụng một [char]
mảng thay vì một chuỗi (bằng cách sử dụng một dấu phẩy đơn nguyên khác ,
), vì vậy tôi có thể xóa các trích dẫn và biểu thức phụ thêm. Tôi có thể nhân một mảng để nhân đôi các phần tử của nó. Và vì toàn bộ kết quả của lần lặp này cuối cùng vẫn là một mảng và cần phải được chỉnh sửa -join
, sử dụng một mảng ở đây không phải trả thêm chi phí.
Sau đó, tôi nhân mảng chuỗi$n
đó với số $n
lần nhân đôi . Nhớ lại rằng $n
có thể$null
hoặc nó có thể là giá trị của các chữ số trước trừ đi một chữ số.
Sau đó +$_
thêm phần tử hiện tại vào phần cuối của ký tự đầu tiên được sao chép của phần tử đó. Đó là lý do tại sao $n
trừ đi một.
Bằng cách này, 10+[>+
kết thúc $n
bằng 9, sau đó chúng tôi tạo 9 +
và thêm +[>+
chuỗi đó trở lại chuỗi để có được số 10 cần thiết, cộng với các yếu tố đơn lẻ khác cho chuyến đi.
Nguyên tố này được bọc trong một subexpression $()
vì khi $n
là $null
, toàn bộ biểu hiện thất bại, do đó tạo ra mảng thất bại, vì thế indexer không bao giờ chạy, vì vậy $n
không bao giờ được giao.
Lý do tôi sử dụng thủ thuật ternary này là vì một trong những đặc thù của nó: không giống như một toán tử ternary thực sự, các biểu thức xác định các phần tử làm được đánh giá hay không mà họ đang "được chọn", và lần đầu tiên cho rằng vấn đề.
Vì tôi cần gán và sau đó sử dụng $n
trên các lần lặp riêng biệt, điều này rất hữu ích. Giá trị phần tử mảng ternary được đánh giá bằng $n
giá trị của lần lặp trước , sau đó bộ chỉ mục gán lại $n
cho lần lặp hiện tại.
Nên ForEach-Object
vòng lặp kết thúc với tất cả mọi thứ mà nó được cho là (một loạt các lỗi chúng ta bỏ qua), nhưng là một chuỗi các chuỗi mới.
Vì vậy, toàn bộ điều được gói trong ngoặc đơn và trước đó là unary -join
để đưa ra chuỗi đầu ra.