Saya pikir saya akan menggunakan kesempatan ini untuk memamerkan fitur Retina baru: loop multi-tahap. Ini harus mempersingkat banyak tugas (terutama penggantian bersyarat).
ii
-
+`(.)\1|0
(.)-|(\d)(\d)
-$1$3$2
12
i3
23
i1
31
i2
)`(\d)i
i$1
^\D*$
$&0
Retina adalah bahasa pemrograman berbasis regex saya sendiri. Kode sumber dapat dikelompokkan menjadi beberapa tahap: setiap tahap terdiri dari dua baris di mana yang pertama berisi regex (dan berpotensi beberapa konfigurasi) dan baris kedua adalah string pengganti. Tahapan-tahapan tersebut kemudian diterapkan pada STDIN secara berurutan dan hasil akhirnya dicetak ke STDOUT.
Anda dapat menggunakan di atas secara langsung sebagai file sumber dengan -s
saklar baris perintah. Namun, saya tidak menghitung tombolnya, karena Anda juga bisa meletakkan setiap baris dalam file yang terpisah (maka Anda kehilangan 15 byte untuk baris baru, tetapi tambahkan +15 untuk file tambahan).
Penjelasan
Hal baru tentang solusi ini adalah )
pada tahap kedua dari belakang. Ini menutup loop multi-tahap. Tidak ada yang cocok (
, yang berarti bahwa loop secara implisit dimulai pada tahap pertama. Oleh karena itu, 7 tahap pertama diulangi sampai lulus penuh semua 7 dari mereka berhenti mengubah hasilnya. 7 tahap ini hanya melakukan berbagai transformasi yang secara bertahap mengurangi jumlah matriks dalam string dan menggabungkan fase. Setelah kami mencapai hasil akhir, tidak ada dari tujuh pola yang cocok lagi dan loop berakhir. Setelah itu, kami menambahkan 0 jika belum ada angka di hasilnya (karena tahap di atas cukup lepaskan semua identitas, termasuk hasilnya).
Inilah yang dilakukan masing-masing tahapan:
ii
-
Menggabungkan semua pasangan i
ke dalam -
untuk mengurangi karakter fase.
+`(.)\1|0
<empty>
Sekarang jika ada dua karakter identik berturut-turut yang tersisa, itu salah satu --
atau dua matriks identik. Dalam kedua kasus itu, mengalikannya memberi identitas. Tapi kami tidak membutuhkan identitas, jadi kami hanya menghapus semuanya, dan identitas eksplisit 0
juga. Tahap ini diulang dengan sendirinya +
sampai hasilnya berhenti berubah. Ini memastikan bahwa hal-hal seperti 123321
diselesaikan sepenuhnya, sehingga langkah selanjutnya dapat mengasumsikan bahwa semua pasangan digit berbeda.
(.)-|(\d)(\d)
-$1$3$2
Ini sebenarnya dua transformasi terpisah dalam satu (untuk golfitude). Perhatikan bahwa jika alternatif pertama cocok, $2
dan $3
kosong, dan jika yang kedua cocok, $1
kosong. Jadi ini dapat diuraikan menjadi dua langkah ini:
(\d)(\d)
-$2$1
Ini hanya menukar semua pasangan digit dan menambahkan tanda minus. Karena kita dihapus semua 0
dan semua pasangan identik, ini hanya akan cocok 12
, 23
, 31
, 21
, 32
, 13
. Langkah ini mungkin tampak aneh, tetapi ini memungkinkan saya untuk hanya memeriksa setengah dari kasus-kasus ini nanti, karena yang saya tidak bisa proses kemudian akan ditukar di sini di iterasi berikutnya.
Bagian lain dari tahap di atas adalah:
(.)-
-$1
Ini secara bertahap memindahkan -
tanda-tanda sampai ke kiri (satu posisi per iterasi). Saya melakukan ini sehingga pada akhirnya mereka semua bersebelahan dan diselesaikan pada langkah sebelumnya.
12
i3
23
i1
31
i2
Tiga tahap ini sekarang hanya menyelesaikan tiga pasang produk. Seperti yang saya katakan di atas, ini hanya akan menangkap setengah dari kasus yang relevan, tetapi setengah lainnya akan diurus dalam iterasi berikutnya, setelah langkah sebelumnya bertukar semua pasangan.
)`(\d)i
i$1
Ini adalah tahap terakhir dari loop. Ini mirip dengan yang bergeser -
ke kiri, kecuali untuk i
. Perbedaan utama adalah bahwa ini i
hanya bertukar dengan angka. Jika saya menggunakan (.)i
maka dalam kasus di mana saya mendapatkan -i
atau i-
keduanya akan ditukar tanpa batas waktu dan program tidak akan berakhir. Jadi ini hanya menukar mereka ke kanan -
tanda. Ini cukup - selama semua -
dan i
muncul bersama di beberapa titik, mereka dapat diselesaikan dengan benar.
^\D*$
$&0
Langkah terakhir (di luar loop). Ingat bahwa kami selalu menghapus semua identitas, jadi jika hasilnya sebenarnya adalah identitas (kali fase), maka kami tidak akan memiliki angka yang diperlukan dalam output lagi, jadi kami menambahkannya kembali.
Sebagai contoh, berikut adalah semua bentuk peralihan 0223202330203313021301011023230323
(melewatkan tahapan yang tidak melakukan perubahan apa pun):
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.