Martin Ender baru-baru ini mencapai 100K, dan telah menghasilkan beberapa bahasa yang cukup mengagumkan . Kita akan bersenang-senang dengan salah satu dari mereka, Hexagony (dan sedikit regex untuk Retina )
Sebagai gambaran umum singkat, Anda perlu menulis sebuah program yang memasukkan kisi Hexagony dan menentukan apakah ada jalur di kisi itu yang cocok dengan string teks
Menghasilkan
Hexagony menghasilkan hexagon dari string teks menggunakan langkah-langkah berikut:
- Hitung ukuran segi enam minimum (ambil panjang string dan bulatkan ke nomor hex terdekat )
- Membungkus teks menjadi segi enam dengan ukuran di atas
- Mengisi lokasi yang tersisa dengan
.
.
Misalnya, string teks abcdefghijklm
memerlukan segi enam sisi-panjang 3, dan karenanya menjadi:
a b c
d e f g
h i j k l
m . . .
. . .
Sekarang, perhatikan bahwa ada 6 kemungkinan arah yang bisa Anda tempuh dalam segi enam. Misalnya, dalam segi enam di atas, e
berbatasan dengan abfjid
.
Pembungkus
Selanjutnya, dalam Hexagony, hexagon membungkus:
. . . . . a . . . . f . . a . .
a b c d e . . b . . . . g . . . b . . f
. . . . . . g . . c . . . . h . . a . c . . g .
. . . . . . . . h . . d . . . . u . . b . . d . . h . .
f g h i j k . i . . e . . j . . c . e . . i . .
. . . . . . j . . f k . . d . . . j . .
. . . . . k . . . . e . . k . .
Jika Anda melihat contoh ke-2 dan ke-4, perhatikan bagaimana a
dan k
berada di tempat yang sama, meskipun Anda membungkus ke arah yang berbeda. Karena kenyataan ini, tempat-tempat ini hanya berdekatan dengan 5 lokasi lainnya .
Untuk memperjelas ini:
a b c d
e f g h i
j k l m n o
p q r s t u v
w x y z A B
C D E F G
H I J K
- Tepi membungkus tetangga yang berlawanan (
b->I
danG->j
). - Sudut atas / bawah membungkus ke sudut tengah yang berlawanan dan atas / bawah (
d->K,p
danH->a,v
). - Sudut tengah membungkus ke sudut atas dan bawah (
v->a,H
)
Jalan
Sebuah jalan menjadi urutan lokasi yang berdekatan tanpa kembali ke lokasi yang sama.
a b c
d e f g
h i f k l
m . . .
. . .
Dalam segi enam di atas, aefkgm
adalah jalur yang valid. Namun, abfd
ini bukan jalur yang valid ( f
dan d
tidak berdekatan), dan abea
tidak valid (kembali ke a
lokasi).
Kita dapat menggunakan jalur ini untuk mencocokkan teks (seperti regex) . Karakter alfa-numerik cocok dengan dirinya sendiri (dan hanya dirinya sendiri), dan .
cocok dengan karakter apa pun. Misalnya, jalan aej..lgm
akan cocok aej..lgm
, aejAAlgm
, aeja.lgm
, atau aej^%gm
.
Input output
Program Anda harus mengambil dua string (dalam urutan apa pun). String pertama tidak akan kosong, dan hanya terdiri dari karakter alfanumerik [a-zA-Z0-9]
. Ini akan mewakili segi enam tempat Anda beroperasi. String kedua akan terdiri dari karakter yang dapat dicetak.
Anda harus mengembalikan nilai kebenaran jika ada jalur di segi enam yang cocok dengan string teks yang diberikan, jika tidak nilai salah.
Uji kasus
Benar:
"a","a"
"ab","a"
"ab","b"
"ab","ba"
"ab","aba"
"ab","&"
"ab","#7.J!"
"ab","aaaaaa"
"ab","bgjneta"
"ab","cebtmaa"
"abcdefg","dfabcg"
"AbCDeFG","GCbAeFD"
"aaaabbb","aaababb"
"abcdefghijklmnopqrs","alq"
"abcdefghijklmnopqrs","aqnmiedh"
"abcdefghijklmnopqrs","adhcgkorbefjimnqlps"
"11122233344455","12341345123245"
"abcdefgh","h%a"
"abcdefghijklm","a)(@#.*b"
"abcdefghijklm","a)(@#.*i"
"abcdefghij","ja"
"abcdefghijklmno","kgfeia"
"abcdefghijklmno","mmmmmiea"
"abcdefghijklmno","mmmmmlae"
"abcdefghijklmno","ja"
"abcdefghijklmnopqrs","eijfbadhmnokgcsrql"
Falsy:
"a","b"
"a","%"
"a","."
"a","aa"
"a","a."
"ab","#7.J!*"
"ab","aaaaaaa"
"ab","aaaabaaa"
"ab","123456"
"abcdefg","bfgedac"
"abcdefg","gecafdb"
"abcdefg","GCbaeFD"
"aaaabbb","aaaaabb"
"abcdefghijklmnopqrs","aqrcgf"
"abcdefghijklmnopqrs","adhlcgknbeifjm"
"abcdefghijklmnopqrs","ja"
"abcdefghijklm","a)(@#.*&"
"abcdefghijklmno","a)(@bfeijk"
"abcdefghijklmno","kgfeic"
"abcdefghijklmno","mmmmmmiea"
Ini adalah kode-golf , jadi buat jawaban Anda sesingkat mungkin dalam bahasa favorit Anda.
sumber
Jawaban:
Retina , 744 byte
Maaf teman, tidak ada Hexagony saat ini ...
Hitungan byte mengasumsikan penyandian ISO 8859-1.
Mengharapkan string target pada baris pertama dan segi enam pada baris kedua input. Cetakan
0
atau1
sesuai.Cobalah online! (Baris pertama memungkinkan suite uji, di mana setiap baris adalah kasus uji, menggunakan
¦
untuk pemisahan dan bukan linefeed.)Cara yang tepat untuk mengatasi tantangan ini adalah dengan regex tentunya. ;) Dan jika bukan karena fakta bahwa tantangan ini juga melibatkan prosedur membuka segi enam , jawaban ini sebenarnya hanya terdiri dari satu regex panjang ~ 600 byte.
Ini belum cukup optimal bermain golf, tapi saya cukup senang dengan hasilnya (versi kerja pertama saya, setelah menghapus grup bernama dan hal-hal lain yang diperlukan untuk kewarasan, sekitar 1000 byte). Saya pikir saya bisa menghemat sekitar 10 byte dengan menukar urutan string dan hexagon tetapi akan membutuhkan penulisan ulang lengkap regex pada akhirnya, yang saya tidak rasakan saat ini. Ada juga penghematan 2-byte dengan menghilangkan
G
panggung, tetapi itu sangat memperlambat solusinya, jadi saya akan menunggu dengan membuat perubahan itu sampai saya yakin saya telah bermain golf ini sebaik yang saya bisa.Penjelasan
Bagian utama dari solusi ini membuat penggunaan ekstensif kelompok penyeimbang , jadi saya sarankan membaca mereka, jika Anda ingin memahami bagaimana ini bekerja secara rinci (saya tidak akan menyalahkan Anda jika Anda tidak ...).
Bagian pertama dari solusi (yaitu semuanya kecuali dua baris terakhir) adalah versi modifikasi dari jawaban saya untuk Unfolding the Hexagony source code . Itu membangun hexagon, sambil membiarkan string target tidak tersentuh (dan itu sebenarnya membangun hexagon sebelum string target). Saya telah membuat beberapa perubahan pada kode sebelumnya untuk menghemat byte:
×
bukannya spasi sehingga tidak bertentangan dengan ruang potensial dalam input._
bukan.
, sehingga sel-sel jaringan dapat diidentifikasi andal sebagai karakter kata.Berikut ini sebuah contoh. Untuk test case berikut:
Kita mendapatkan:
Bandingkan ini dengan tata letak hexagon yang biasa:
Kita bisa melihat bahwa para tetangga sekarang semua tetangga Moore-8 yang biasa, kecuali tetangga barat laut dan tenggara. Jadi kita perlu memeriksa adjacency horisontal, vertikal dan barat daya / timur laut (baik dan kemudian ada tepi pembungkus). Menggunakan tata letak yang lebih ringkas ini juga memiliki bonus bahwa kita akan dapat menggunakannya
××
pada akhirnya untuk menentukan ukuran segi enam saat kita membutuhkannya.Setelah formulir ini dibuat, kami membuat satu lagi perubahan pada seluruh string:
Ini menggantikan digit dengan huruf ASCII yang diperluas
Karena mereka diganti baik di hexagon dan di string target, ini tidak akan mempengaruhi apakah string cocok atau tidak. Juga, karena mereka adalah huruf
\w
dan\b
masih mengidentifikasi mereka sebagai sel segi enam. Manfaat melakukan substitusi ini adalah bahwa kita sekarang dapat menggunakan\D
dalam regex yang akan datang untuk mencocokkan karakter apa pun (khususnya, umpan baris serta karakter non-umpan baris). Kami tidak dapat menggunakans
opsi untuk mencapai itu, karena kami harus.
mencocokkan karakter non-linefeed di beberapa tempat.Sekarang bit terakhir: menentukan apakah ada jalur yang cocok dengan string kami. Ini dilakukan dengan regex raksasa tunggal. Anda mungkin bertanya pada diri sendiri mengapa?!?! Nah, ini pada dasarnya masalah penelusuran mundur: Anda memulai suatu tempat dan mencoba jalur selama cocok dengan string, dan sekali tidak Anda mundur dan mencoba tetangga yang berbeda dari karakter terakhir yang bekerja. Satu halyang Anda dapatkan secara gratis saat bekerja dengan regex mundur. Itulah satu-satunya hal yang dilakukan mesin regex. Jadi jika kita hanya menemukan cara untuk menggambarkan jalur yang valid (yang cukup rumit untuk masalah seperti ini, tapi pasti mungkin dengan kelompok penyeimbang), maka mesin regex akan memilah menemukan jalan itu di antara semua yang mungkin bagi kita. Tentu akan mungkin untuk mengimplementasikan pencarian secara manual dengan beberapa tahap ( dan saya telah melakukannya di masa lalu ), tapi saya ragu itu akan lebih pendek dalam kasus khusus ini.
Salah satu masalah dengan menerapkan ini dengan regex adalah bahwa kita tidak dapat secara sewenang-wenang mengayunkan kursor mesin regex bolak-balik melalui string selama backtracking (yang kita perlukan karena jalur mungkin naik atau turun). Jadi alih-alih, kami melacak "kursor" kami sendiri dalam grup penangkap dan memutakhirkannya di setiap langkah (kami dapat pindah ke posisi kursor untuk sementara dengan pencarian). Ini juga memungkinkan kita untuk menyimpan semua posisi sebelumnya yang akan kita gunakan untuk memeriksa bahwa kita belum mengunjungi posisi saat ini sebelumnya.
Jadi mari kita mulai. Berikut ini adalah versi regex yang sedikit lebih waras, dengan grup yang diberi nama, indentasi, urutan tetangga yang kurang acak, dan beberapa komentar:
Saya berharap bahwa ide umum kurang lebih jelas dari ini. Sebagai contoh bagaimana salah satu gerakan di sepanjang jalan itu bekerja, mari kita lihat bit yang menggerakkan kursor ke selatan:
Ingatlah bahwa lookbehinds harus dibaca dari kanan ke kiri (atau dari bawah ke atas), karena itulah urutan pelaksanaannya:
Perhatikan bahwa tidak perlu meletakkan jangkar di depan
\k<pos>
untuk memastikan bahwa ini benar-benar mencapai awal string.<pos>
selalu dimulai dengan jumlah×
yang tidak dapat ditemukan di tempat lain, jadi ini sudah bertindak sebagai jangkar implisit.Saya tidak ingin menggembungkan posting ini lebih dari yang diperlukan, jadi saya tidak akan membahas 11 kasus lainnya secara terperinci, tetapi pada prinsipnya semuanya bekerja sama. Kami memeriksa bahwa
<next>
dapat ditemukan dalam beberapa arah tertentu (dapat diterima) dari posisi kursor lama dengan bantuan kelompok penyeimbang, dan kemudian kami menyimpan string hingga cocok dengan posisi kursor baru di<pos>
.sumber
Python 3,
990943770709 byteJawaban pertama, yay!
EDIT: Pembuatan daftar kedekatan golf. Saya sekarang menggunakan formula yang sedikit berbeda
EDIT 2: Menghilangkan bulu yang tidak perlu, lebih banyak bermain golf.
EDIT 3: Mempersingkat kode untuk konversi dari indeks dalam daftar ke koordinat, golf beberapa hal lagi.
Mayoritas byte terkait dengan membuat daftar adjacency (memiliki potensi paling besar untuk golf). Sejak saat itu, ini adalah masalah sederhana yang memaksa solusi (yang mungkin bisa saya lakukan dalam lebih sedikit byte).
Golf:
Tanpa penjelasan bersama:
Begitu dekat dengan Retina! :(Yay, kalahkan Retina!sumber
Javascript (ES6),
511500496 byteTidak diikat dan dikomentari
Uji kasus
Cuplikan di bawah ini akan menelusuri semua kasus uji yang benar dan salah.
Tampilkan cuplikan kode
sumber