Retina , 108 102 94 87 82 64 63 bayt
Bayt sayısını 108'den 82'ye getiren özgün yaklaşımımı takip etmemi sağladığı için Sp3000'e teşekkürler.
Çok daha zarif bir çözüm bulan Kobi'ye büyük teşekkür, bunun üzerine 19 baytı daha kurtarmamı sağladı.
S_`(?<=^(?<-1>.)*(?:(?<=\G(.)*).)+)
.
$0
m+`^(?=( *)\S.*\n\1)
<space>
Burada <space>
(aksi SE ile sıyrılmıştır olacaktır) tek bir boşluk karakteri temsil eder. Sayma amacıyla, her satır ayrı bir dosyaya gider ve \n
gerçek bir satır besleme karakteri ile değiştirilmelidir. Kolaylık sağlamak için kodu tek bir dosyadan olduğu gibi -s
bayrakla çalıştırabilirsiniz.
Çevrimiçi deneyin.
açıklama
Şey ... her zamanki gibi burada dengeleme gruplarına tam bir giriş yapamam. Bir astar için Yığın Taşması cevabına bakın .
S_`(?<=^(?<-1>.)*(?:(?<=\G(.)*).)+)
İlk aşama, S
girdiyi artan uzunluktaki çizgiler halinde bölen bir plit aşamasıdır. _
Boş parçaları (son konumunda bir maç olacak çünkü sadece, son etkiler) parçalanması sonucunda ihmal edilmesi gerektiğini belirtir. Regex'in kendisi tamamen etrafa bakıyor, bu yüzden karakterlerle eşleşmeyecek, yalnızca konumlarla eşleşecek.
Bu bölüm, Kobi'nin kendimi bulduğum ek büyüklükteki çözümüne dayanıyor. Lookbehind'lerin .NET'te sağdan sola eşleştirildiğini unutmayın; bu nedenle aşağıdaki açıklama en iyi aşağıdan yukarıya okunmalıdır. Ayrıca \G
, desen çalışması için gerekli olmasa da, açıklama için başka bir açıklama ekledim.
(?<=
^ # And we ensure that we can reach the beginning of the stack by doing so.
# The first time this is possible will be exactly when tri(m-1) == tri(n-1),
# i.e. when m == n. Exactly what we want!
(?<-1>.)* # Now we keep matching individual characters while popping from group <1>.
\G # We've now matched m characters, while pushing i-1 captures for each i
# between 1 and m, inclusive. That is, group <1> contains tri(m-1) captures.
(?:
(?<=
\G # The \G anchor matches at the position of the last match.
(.)* # ...push one capture onto group <1> for each character between here
# here and the last match.
) # Then we use a lookahead to...
. # In each iteration we match a single character.
)+ # This group matches all the characters up to the last match (or the beginning
# of the string). Call that number m.
) # If the previous match was at position tri(n-1) then we want this match
# to happen exactly n characters later.
Hala Kobi'nin çalışmalarına burada hayranım. Bu, birinci test regex'inden bile daha zarif. :)
Bir sonraki aşamaya geçelim:
.
$0
Basit: Satır dışı her karakterden sonra bir boşluk bırakın.
m+`^(?=( *)\S.*\n\1)
<space>
Bu son aşama, üçgeni oluşturmak için tüm çizgileri doğru bir şekilde girer. m
Yapmak için sadece olağan satırlı modu ^
, satırın başıyla eşleşir. +
Dize değişen durana kadar bu aşamayı tekrarlamak Retina söyler (ki bu durumda araçlarında olduğu regex artık maçları).
^ # Match the beginning of a line.
(?= # A lookahead which checks if the matched line needs another space.
( *) # Capture the indent on the current line.
\S # Match a non-space character to ensure we've got the entire indent.
.*\n # Match the remainder of the line, as well as the linefeed.
\1 # Check that the next line has at least the same indent as this one.
)
Yani bu, diğerinden daha büyük bir girintiye sahip olmayan herhangi bir satırın başlangıcıyla eşleşir. Böyle bir pozisyonda bir boşluk ekleriz. Bu işlem, çizgiler düzgün bir üçgen şeklinde düzenlendiğinde sona erer, çünkü her çizginin diğerinden daha büyük girintiye sahip olduğu minimum düzen budur.