Retina , 45 43 bayt
Bayt sayımı ISO 8859-1 kodlamasını varsayar.
O$#`.(?<=(.+))|¶
$.1
!`(?<=(¶)+.*)(?<-1>.)+
Baştaki satır besleme önemlidir. Giriş ve çıkış yazdırılabilir ASCII dizelerinin satır beslemeli sonlandırılmış listeleridir (her ikisinin de tek bir satır besleme beslemesi olduğunu unutmayın).
Çevrimiçi deneyin!
Bir süredir dikdörtgen blokların transpozasyonunun Retina'da bir ağrı olacağını biliyordum (oysa transpozisyonlar çok kötü değil), ama aslında hiç denemedim. İlk çözüm gerçekten 110 bayt uzunluğundaydı, ancak yaklaşımdaki bazı önemli değişikliklerden sonra, ortaya çıkan 45 bayt, şüphelendiğim kadar kötü değil (ama yine de ...). Açıklama yarın takip edecek.
açıklama
Aşama 1: Sırala
O$#`.(?<=(.+))|¶
$.1
Bu, girişteki karakterleri yeniden sıralamanın ana işini yapar, ancak satırlara ayırmayı karıştırır. İlginç bir şekilde, 'i kaldırırsak, |¶
kare bir girişi aktarmak için gerekli kodu alırız.
Sıralama aşamaları (ile gösterilir O
) şu şekilde çalışır: verilen normal ifadenin tüm maçlarını bulurlar (sonrasındaki `
) ve daha sonra bu maçları sıralar ve maçların bulunduğu yerlere yeniden yerleştirirler. Olduğu gibi, bu normal ifade her bir karakterle eşleşir: .(?<=(.*))
alternatif üzerinden satır beslemeleri ve ¶
. Bu nedenle, girişteki tüm karakterleri sıralar. Daha ilginç olan kısmı, sıralamalarına göre sıralanıyor .
$
Seçenek aktive eden "sort-by", her bir maç sonra sonuç karşılaştırılması için kullanılan ikinci hat, üzerindeki ikame modeli ile değiştirilir modunda. Ayrıca #
Retina'ya, ikame sonucunu bir tamsayıya dönüştürmesini ve bu tamsayıları karşılaştırmasını (onlara dize olarak işlemek yerine) söyler.
Son olarak, normal ifadeye ve ikamesine bakmamız gerekiyor. İlk alternatif eşleşirse (yani, satırlardan birinde herhangi bir karakteri eşleştirdiysek), o (?<=(.*))
satırdaki o karaktere kadar olan her şeyi grup olarak yakalar 1
. $.1
İkame desen ile değiştirir uzunluğu grubunun 1
. Böylece, her dizgideki ilk karakter olur 1
, ikincisi olur 2
, üçüncüsü olur 3
. Şimdi bunun bir kare girdiyi nasıl dönüştürdüğü açık olmalıdır: satırların tüm ilk karakterleri önce gelir ve hepsi en üst satırda sona erer, daha sonra tüm ikinci karakterler ikinci satırda sona erer vb. Ancak bu dikdörtgen girdiler için satır beslemelerini de eşleştiriyoruz. Gruptan beri1
bu durumda kullanılmamışsa, ikame boştur, ancak #
opsiyonun amaçları için bu dikkate alınır 0
. Bu, tüm hat beslemelerinin öne doğru sıralandığı anlamına gelir.
Şimdi ilk sırada karakterler var (her dizenin ilk karakteri, her dizenin ikinci karakteri, vb.) Ve başlangıçtaki tüm satır beslemeleri var.
Aşama 2: Maç
!`(?<=(¶)+.*)(?<-1>.)+
Şimdi karakterleri doğru uzunlukta satırlara ayırmamız gerekiyor. Bu uzunluk, orijinal girdideki satır sayısına, yani dizenin başında sahip olduğumuz satır besleme sayısına karşılık gelir.
Bölme burada verilen regex'in tüm eşleşmelerini bulan ve !
bu eşleşmeleri yazdırma seçeneğini kullanan bir eşleştirme aşaması yardımıyla yapılır (varsayılan, onları saymak olacaktır). Normal ifadenin amacı, her seferinde bir satırla eşleşmektir.
İşe baktığımızda sayıyı "sayarak" başlıyoruz (?<=(¶)*.*)
. 1
Öndeki her hat beslemesi için grup halinde bir yakalama oluşturur .
Ardından, bu yakalamaların her biri için tek bir karakterle eşleşiriz (?<-1>.)+
.