Số lượng byte giả định mã hóa ISO 8859-1.
O$#`.(?<=(.+))|¶
$.1
!`(?<=(¶)+.*)(?<-1>.)+
Các nguồn cấp dữ liệu hàng đầu là đáng kể. Đầu vào và đầu ra là các danh sách kết thúc chuỗi nguồn có thể in của chuỗi ASCII (lưu ý rằng cả hai đều có một dòng cấp dữ liệu duy nhất).
Hãy thử trực tuyến!
Trong một thời gian, tôi biết rằng các khối hình chữ nhật hoán vị sẽ là một nỗi đau ở Retina (trong khi các hình vuông chuyển vị không quá tệ), nhưng thực sự chưa bao giờ thử. Giải pháp đầu tiên thực sự là một con số khổng lồ dài 110 byte, nhưng sau một vài thay đổi đáng kể trong cách tiếp cận, 45 byte kết quả cho đến nay không tệ như tôi nghi ngờ (nhưng vẫn ...). Giải thích sẽ theo ngày mai.
Giải trình
Giai đoạn 1: Sắp xếp
O$#`.(?<=(.+))|¶
$.1
Điều này thực hiện công việc chính là sắp xếp lại các ký tự trong đầu vào, nhưng cuối cùng nó làm rối tung sự phân tách thành các dòng. Thật thú vị, nếu chúng ta loại bỏ |¶
, chúng ta sẽ nhận được mã cần thiết để chuyển đổi một đầu vào vuông.
Các giai đoạn sắp xếp (được biểu thị bởi O
) hoạt động như thế này: họ tìm thấy tất cả các trận đấu của regex đã cho (điều sau `
), sau đó sắp xếp các trận đấu đó và đặt lại chúng vào những nơi tìm thấy các trận đấu. Khi điều đó xảy ra, regex này khớp với mọi ký tự đơn: không phải là dòng thông qua .(?<=(.*))
thay thế và nguồn cấp dữ liệu thông qua ¶
. Do đó, nó sắp xếp tất cả các ký tự trong đầu vào. Phần thú vị hơn là những gì chúng được sắp xếp theo .
Các $
tùy chọn kích hoạt một "loại theo" chế độ, trong đó mỗi trận đấu được thay thế bằng mẫu thay thế trên dòng thứ hai, sau đó được sử dụng để so sánh các trận đấu. Hơn nữa,#
yêu cầu Retina chuyển đổi kết quả của sự thay thế thành một số nguyên và so sánh các số nguyên đó (thay vì coi chúng là các chuỗi).
Vì vậy, cuối cùng, chúng ta cần xem xét regex và sự thay thế. Nếu sự thay thế đầu tiên khớp (nghĩa là chúng ta đã khớp bất kỳ ký tự nào trong một trong các dòng), thì nó sẽ (?<=(.*))
bắt mọi thứ theo ký tự đó trên dòng đó thành nhóm 1
. Các $.1
trong mẫu thay thế thay thế này với chiều dài của nhóm 1
. Do đó, ký tự đầu tiên trong mỗi chuỗi trở thành 1
, ký tự thứ hai trở thành 2
, ký tự thứ ba trở thành 3
vân vân. Bây giờ, rõ ràng làm thế nào điều này chuyển đổi một đầu vào vuông: tất cả các ký tự đầu tiên của dòng đến trước và tất cả kết thúc ở dòng trên cùng, sau đó tất cả các ký tự thứ hai kết thúc trong dòng thứ hai, v.v. Nhưng đối với các đầu vào hình chữ nhật này, chúng tôi cũng phù hợp với các nguồn cấp dữ liệu. Kể từ khi nhóm1
không được sử dụng trong trường hợp này, sự thay thế là trống rỗng, nhưng với mục đích của #
tùy chọn, điều này được xem xét 0
. Điều đó có nghĩa là, tất cả các nguồn cấp dữ liệu được sắp xếp ở phía trước.
Vì vậy, bây giờ chúng ta có các ký tự theo thứ tự đầu tiên (ký tự đầu tiên của mỗi chuỗi, ký tự thứ hai của mỗi chuỗi, v.v.) và tất cả các nguồn cấp dữ liệu khi bắt đầu.
Giai đoạn 2: Trận đấu
!`(?<=(¶)+.*)(?<-1>.)+
Bây giờ chúng ta cần chia các ký tự thành các dòng có độ dài chính xác. Độ dài này tương ứng với số lượng dòng trong đầu vào ban đầu, tương ứng với số lượng dòng chúng ta có ở đầu chuỗi.
Việc chia tách được thực hiện ở đây với sự trợ giúp của giai đoạn khớp, đơn giản là tìm tất cả các kết quả khớp của biểu thức đã cho và sử dụng !
tùy chọn để in các kết quả khớp đó (mặc định sẽ là đếm chúng thay thế). Vì vậy, mục tiêu của regex là khớp một dòng tại một thời điểm.
Chúng tôi bắt đầu bằng cách "đếm" số với cái nhìn (?<=(¶)*.*)
. Nó tạo ra một bản chụp trong nhóm 1
cho mỗi nguồn cấp dữ liệu ở phía trước.
Sau đó, với mỗi lần chụp đó, chúng tôi khớp với một nhân vật (?<-1>.)+
.