Retina , 45 43 byte
Hitungan byte mengasumsikan penyandian ISO 8859-1.
O$#`.(?<=(.+))|¶
$.1
!`(?<=(¶)+.*)(?<-1>.)+
Linefeed terkemuka sangat penting. Input dan output adalah daftar string ASCII yang dapat diakhiri linefeed (catat bahwa keduanya memiliki satu linefeeding trailing tunggal)
Cobalah online!
Saya tahu untuk sementara waktu bahwa memindahkan blok persegi panjang akan menyusahkan di Retina (padahal mentransposisikan kotak tidak terlalu buruk), tetapi tidak pernah benar-benar mencoba. Solusi pertama memang panjang 110 byte kekalahan, tetapi setelah beberapa perubahan substansial dalam pendekatan, yang dihasilkan 45 byte sejauh ini tidak seburuk yang saya duga (tapi masih ...). Penjelasan akan mengikuti besok.
Penjelasan
Tahap 1: Sortir
O$#`.(?<=(.+))|¶
$.1
Ini melakukan tugas utama menyusun ulang karakter dalam input, tetapi akhirnya mengacaukan pemisahan menjadi beberapa baris. Menariknya, jika kita menghapus |¶
, kita mendapatkan kode yang diperlukan untuk mengubah input persegi.
Tahap sortir (dilambangkan oleh O
) bekerja seperti ini: mereka menemukan semua kecocokan dari regex yang diberikan (hal setelah `
), dan kemudian mengurutkan kecocokan itu dan memasukkan kembali mereka ke tempat-tempat di mana kecocokan ditemukan. Seperti yang terjadi, regex ini cocok dengan setiap karakter tunggal: umpan tidak-line melalui .(?<=(.*))
alternatif dan umpan baris melalui ¶
. Oleh karena itu, semua karakter di input. Bagian yang lebih menarik adalah apa yang mereka diurutkan oleh .
The $
pilihan mengaktifkan "sort-by" mode, di mana setiap pertandingan diganti dengan pola substitusi pada baris kedua, yang kemudian digunakan untuk membandingkan pertandingan. Selanjutnya,#
Retina memberitahu untuk mengubah hasil substitusi menjadi bilangan bulat, dan membandingkan bilangan bulat tersebut (alih-alih memperlakukannya sebagai string).
Jadi akhirnya, kita perlu melihat regex dan substitusi. Jika alternatif pertama cocok (yaitu, kami telah mencocokkan karakter apa pun dalam salah satu baris), maka (?<=(.*))
menangkap semuanya hingga karakter itu pada baris itu ke dalam grup 1
. The $.1
dalam pola substitusi menggantikan ini dengan panjang kelompok 1
. Oleh karena itu, karakter pertama dalam setiap string menjadi 1
, yang kedua menjadi tidak digunakan dalam kasus ini, substitusi kosong, tetapi untuk keperluan opsi, ini dipertimbangkan . Itu berarti, semua umpan garis diurutkan ke depan.2
, yang ketiga menjadi 3
dan seterusnya. Seharusnya jelas sekarang bagaimana ini mentransposisi input kuadrat: semua karakter pertama dari baris datang pertama dan semua berakhir di baris paling atas, kemudian semua karakter kedua berakhir di baris kedua dan seterusnya. Tetapi untuk input persegi panjang ini, kami juga mencocokkan umpan baris. Sejak kelompok1
#
0
Jadi sekarang kita memiliki karakter dalam urutan pertama (karakter pertama dari setiap string, karakter kedua dari setiap string, dll.) Dan semua umpan baris di awal.
Tahap 2: Cocokkan
!`(?<=(¶)+.*)(?<-1>.)+
Kita sekarang perlu membagi karakter menjadi garis dengan panjang yang benar. Panjang ini sesuai dengan jumlah baris dalam input asli, yang sesuai dengan jumlah baris yang kita miliki di awal string.
Pemisahan dilakukan di sini dengan bantuan tahap pertandingan, yang hanya menemukan semua pertandingan dari regex yang diberikan dan menggunakan !
opsi untuk mencetak pertandingan tersebut (standarnya adalah menghitungnya). Jadi tujuan dari regex adalah untuk mencocokkan satu baris sekaligus.
Kita mulai dengan "menghitung" angka dengan tampilan di belakang (?<=(¶)*.*)
. Ini menghasilkan satu tangkapan dalam grup 1
untuk setiap linefeed di depan.
Kemudian, untuk setiap tangkapan itu, kami mencocokkan satu karakter dengan (?<-1>.)+
.