Tôi nghĩ rằng tôi sẽ sử dụng cơ hội này để thể hiện một tính năng Retina mới: các vòng lặp nhiều giai đoạn. Điều này sẽ rút ngắn nhiều nhiệm vụ đáng kể (đặc biệt là thay thế có điều kiện).
ii
-
+`(.)\1|0
(.)-|(\d)(\d)
-$1$3$2
12
i3
23
i1
31
i2
)`(\d)i
i$1
^\D*$
$&0
Retina là ngôn ngữ lập trình dựa trên regex của riêng tôi. Mã nguồn có thể được nhóm thành các giai đoạn: mỗi giai đoạn bao gồm hai dòng trong đó dòng đầu tiên chứa regex (và có khả năng một số cấu hình) và dòng thứ hai là chuỗi thay thế. Các giai đoạn sau đó được áp dụng cho STDIN theo thứ tự và kết quả cuối cùng được in thành STDOUT.
Bạn có thể sử dụng trực tiếp ở trên dưới dạng tệp nguồn với -s
công tắc dòng lệnh. Tuy nhiên, tôi không tính công tắc, vì bạn cũng có thể chỉ đặt mỗi dòng vào một tệp riêng biệt (sau đó bạn mất 15 byte cho dòng mới, nhưng thêm +15 cho các tệp bổ sung).
Giải trình
Điều mới về giải pháp này là )
trong giai đoạn áp chót. Điều này đóng một vòng lặp nhiều giai đoạn. Không có kết quả khớp (
, có nghĩa là vòng lặp ngầm bắt đầu ở giai đoạn đầu tiên. Do đó, 7 giai đoạn đầu tiên được lặp lại cho đến khi vượt qua tất cả 7 giai đoạn dừng thay đổi kết quả. 7 giai đoạn này chỉ đơn giản là thực hiện các phép biến đổi khác nhau làm giảm dần số lượng ma trận trong chuỗi và kết hợp các pha. Khi chúng tôi đạt được kết quả cuối cùng, không có mẫu nào trong bảy mẫu phù hợp nữa và vòng lặp kết thúc. Sau đó, chúng tôi sẽ thêm 0 nếu không có chữ số nào trong kết quả (vì các giai đoạn trên chỉ đơn giản là bỏ tất cả các danh tính, bao gồm cả kết quả).
Đây là những gì các giai đoạn cá nhân làm:
ii
-
Kết hợp tất cả các cặp i
vào -
để giảm các ký tự pha.
+`(.)\1|0
<empty>
Bây giờ nếu còn lại hai ký tự giống hệt nhau, thì đó là một --
hoặc hai ma trận giống hệt nhau. Trong cả hai trường hợp, nhân chúng cho danh tính. Nhưng chúng tôi không cần danh tính, vì vậy chúng tôi chỉ cần xóa tất cả chúng, và cả danh tính rõ ràng 0
. Giai đoạn này được lặp lại trong chính nó +
cho đến khi kết quả ngừng thay đổi. Điều này đảm bảo rằng những thứ như 123321
được giải quyết hoàn toàn, sao cho bước tiếp theo có thể giả định rằng tất cả các cặp chữ số là khác biệt.
(.)-|(\d)(\d)
-$1$3$2
Đây thực sự là hai biến đổi riêng biệt trong một (đối với sân gôn). Lưu ý rằng nếu trận đấu thay thế đầu tiên $2
và $3
trống, và nếu trận đấu thứ hai $1
trống. Vì vậy, điều này có thể được phân tách thành hai bước sau:
(\d)(\d)
-$2$1
Điều này chỉ hoán đổi tất cả các cặp chữ số và thêm một dấu trừ. Kể từ khi chúng tôi loại bỏ tất cả 0
s và tất cả các cặp giống hệt nhau, điều này sẽ chỉ phù hợp với 12
, 23
, 31
, 21
, 32
, 13
. Bước này có vẻ kỳ lạ, nhưng nó cho phép tôi chỉ kiểm tra một nửa các trường hợp này sau đó, vì những trường hợp tôi không thể xử lý sau đó sẽ được hoán đổi ở đây trong lần lặp tiếp theo.
Phần khác của giai đoạn trên là:
(.)-
-$1
Điều này dần dần di chuyển -
các dấu hiệu cho đến bên trái (một vị trí trên mỗi lần lặp). Tôi làm điều này sao cho cuối cùng tất cả chúng nằm cạnh nhau và được giải quyết ở bước trước.
12
i3
23
i1
31
i2
Ba giai đoạn này bây giờ chỉ đơn giản là giải quyết ba cặp sản phẩm. Như tôi đã nói ở trên, điều này sẽ chỉ bắt được một nửa các trường hợp có liên quan, nhưng nửa còn lại sẽ được xử lý trong lần lặp tiếp theo, sau bước trước đó đã hoán đổi tất cả các cặp.
)`(\d)i
i$1
Đây là giai đoạn cuối cùng của vòng lặp. Nó tương tự như cái dịch chuyển -
sang trái, ngoại trừ i
. Sự khác biệt chính là cái này i
chỉ hoán đổi với các chữ số. Nếu tôi sử dụng (.)i
thì trong trường hợp tôi nhận được một -i
hoặc i-
hai cái sẽ bị tráo đổi vô thời hạn và chương trình sẽ không chấm dứt. Vì vậy, điều này chỉ hoán đổi họ ở bên phải của các -
dấu hiệu. Điều này là đủ - miễn là tất cả -
và i
xuất hiện cùng nhau tại một số điểm, chúng có thể được giải quyết chính xác.
^\D*$
$&0
Bước cuối cùng (bên ngoài vòng lặp). Hãy nhớ rằng chúng tôi luôn xóa tất cả các danh tính, vì vậy nếu kết quả thực sự là danh tính (lần một pha), thì chúng tôi sẽ không có chữ số bắt buộc trong đầu ra nữa, vì vậy chúng tôi sẽ thêm lại.
Ví dụ, đây là tất cả các hình thức trung gian của 0223202330203313021301011023230323
(bỏ qua các giai đoạn không thực hiện bất kỳ thay đổi nào):
0223202330203313021301011023230323
321321312 # Remove identities
-23-31-12-132 # Swap all pairs
-23-31-i3-132 # Resolve 12
-i1-31-i3-132 # Resolve 23
-i1-i2-i3-132 # Resolve 31
-i-1i-2i-3-312 # Move - to the left and swap pairs
-i-1i-2i-3-3i3 # Resolve 12
-i-i1-i2-3-i33 # Move i to the left
-i-i1-i2-3-i # Remove identities
--ii-1i-2-3i # Move - to the left
--ii-i1-2-i3 # Move i to the left
----i1-2-i3 # Resolve ii
i1-2-i3 # Remove identities
i-1-2i3 # Move - to the left
i-1-i23 # Move i to the left
-i-1i-32 # Move - to the left and swap pairs
-i-i1-32 # Move i to the left
--ii-1-23 # Move - to the left and swap pairs
--ii-1-i1 # Resolve 23
----1-i1 # Resolve ii
1-i1 # Remove identities
-1i1 # Move - to the left
-i11 # Move i to the left
-i # Remove identities. Now the loop can't change this any longer.
-i0 # Fix the result by adding in the 0.