Bu fırsatı yeni bir Retina özelliğini göstermek için kullanacağımı düşündüm: çok aşamalı döngüler. Bu, birçok görevi önemli ölçüde kısaltmalıdır (özellikle koşullu değiştirme).
ii
-
+`(.)\1|0
(.)-|(\d)(\d)
-$1$3$2
12
i3
23
i1
31
i2
)`(\d)i
i$1
^\D*$
$&0
Retina benim kendi regex tabanlı programlama dilim. Kaynak kodu aşamalar halinde gruplandırılabilir: her aşama, birincisinin normal ifadeyi (ve potansiyel olarak bazı yapılandırmayı) içerdiği ve ikinci satırın yerine geçen dize olduğu iki satırdan oluşur. Daha sonra aşamalar sırayla STDIN'e uygulanır ve nihai sonuç STDOUT'a yazdırılır.
Yukarıdakileri doğrudan bir kaynak dosyası olarak -s
komut satırı anahtarıyla . Ancak, anahtarı saymıyorum, çünkü her satırı ayrı bir dosyaya da koyabilirsiniz (daha sonra yeni satırlar için 15 bayt kaybedersiniz, ancak ek dosyalar için +15 ekleyin).
açıklama
Bu çözümle ilgili yeni şey )
, sondan bir önceki aşamada. Bu, çok aşamalı bir döngüyü kapatır. Eşleşme yok(
, yani döngü ilk aşamada dolaylı olarak başlar. Bu nedenle, ilk 7 aşama bunların 7'sinden tam geçiş sonucu değiştirmeyi durdurana kadar tekrarlanır. Bu 7 aşama basitçe ipdeki matris sayısını yavaş yavaş azaltan ve fazları birleştiren çeşitli dönüşümler gerçekleştirir. Nihai sonuca ulaştığımızda, yedi desenin hiçbiri artık eşleşmez ve döngü sona erer. Daha sonra, sonuçta henüz bir rakam yoksa 0 ekleriz (yukarıdaki aşamalar sonuç dahil tüm kimlikleri düşürür).
Bireysel aşamalar şunları yapar:
ii
-
Tüm çiftleri birleştirir i
içine -
faz karakterleri azaltmak için.
+`(.)\1|0
<empty>
Şimdi iki ardışık özdeş karakter kaldıysa, ya bir ya --
da iki özdeş matristir. Her iki durumda da, onları çoğaltmak kimliği verir. Fakat kimliklere ihtiyacımız yok, bu yüzden hepsini ve açık kimlikleri de kaldırıyoruz 0
. +
Sonuç aşaması durana kadar bu aşama kendi içinde tekrarlanır . Bu 123321
, bir sonraki adımın tüm basamak çiftlerinin farklı olduğunu varsayabileceği gibi tamamen çözülmesini sağlar .
(.)-|(\d)(\d)
-$1$3$2
Bu aslında birde iki ayrı dönüşümdür (golfitude için). İlk alternatifin $2
ve $3
ile eşleşmesi ve ikincisinin eşleşmesinin $1
boş olması gerektiğini unutmayın. Yani bu şu iki adıma ayrılabilir:
(\d)(\d)
-$2$1
Bu, tüm basamak çiftlerini değiştirir ve eksi işareti ekler. Hepimizin kaldırıldı yana 0
s ve tüm özdeş çiftleri, bu sadece maç olacak 12
, 23
, 31
, 21
, 32
, 13
. Bu adım tuhaf görünebilir, ancak daha sonra bu davaların sadece yarısını kontrol etmeme izin veriyor, çünkü işleyemediğim kişiler bir sonraki yinelemede değiştirilecek.
Yukarıdaki aşamanın diğer kısmı:
(.)-
-$1
Bu, -
işaretleri yavaşça sola doğru hareket ettirir (her yineleme için bir konum). Bunu, sonuçta hepsi yan yana olacak ve önceki adımda çözülecek şekilde yaparım.
12
i3
23
i1
31
i2
Bu üç aşama şimdi üç çift ürünü çözmektedir. Yukarıda söylediğim gibi, bu ilgili davaların sadece yarısını yakalayacaktır, ancak diğer adım, bir önceki adımda tüm çiftleri değiştirdikten sonra bir sonraki yinelemede ele alınacaktır.
)`(\d)i
i$1
Bu, döngünün son aşamasıdır. Bunun -
haricinde sola kaymaya benzer i
. Temel fark, bunun i
sadece rakamlarla değişmesidir. Eğer (.)i
o zaman bir -i
ya i-
da iki tane aldığım durumlarda süresiz olarak değiştirilir ve program sona ermez. Bu sadece onları -
işaretlerin sağına değiştirir . Bu yeterlidir - boyu kadar -
ve i
bir noktada birlikte görünür, bunların doğru çözülebilir.
^\D*$
$&0
Son adım (döngünün dışında). Tüm kimlikleri her zaman sildiğimizi unutmayın, bu nedenle sonuç aslında kimlikse (bir faz), çıktıda gerekli basamağa artık sahip olmayacağız, bu yüzden geri ekliyoruz.
Örnek olarak, tüm ara formları 0223202330203313021301011023230323
(herhangi bir değişiklik yapmayan aşamaları atlamak):
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.