Số lượng byte giả định mã hóa ISO 8859-1.
+%`\B
¶$`:
1
Hãy thử trực tuyến!
Giải pháp thay thế:
+1`\B
:$`:
1
Giải trình
Điều này có lẽ sẽ dễ giải thích hơn dựa trên phiên bản cũ, ít chơi gôn của tôi và sau đó cho thấy cách tôi rút ngắn nó. Tôi đã sử dụng để chuyển đổi nhị phân thành thập phân như thế này:
^
,
+`,(.)
$`$1,
1
Cách hợp lý duy nhất để xây dựng một số thập phân trong Retina là bằng cách đếm các thứ (vì Retina có một vài tính năng cho phép nó in một số thập phân đại diện cho một số tiền). Vì vậy, thực sự cách tiếp cận duy nhất có thể là chuyển đổi nhị phân thành đơn nguyên, và sau đó đếm số chữ số đơn nguyên. Dòng cuối cùng thực hiện đếm, vì vậy bốn dòng đầu tiên chuyển đổi nhị phân thành đơn nguyên.
làm sao chúng ta làm việc đó bây giờ? Nói chung, để chuyển đổi từ danh sách các bit thành số nguyên, chúng tôi khởi tạo kết quả 0
và sau đó đi qua các bit từ hầu hết đến đáng kể nhất, nhân đôi giá trị chúng tôi đã có và thêm bit hiện tại. Ví dụ: nếu số nhị phân là 1011
, chúng tôi thực sự sẽ tính toán:
(((0 * 2 + 1) * 2 + 0) * 2 + 1) * 2 + 1 = 11
^ ^ ^ ^
Nơi tôi đã đánh dấu các bit riêng lẻ cho rõ ràng.
Bí quyết để thực hiện điều này một cách đơn giản là a) nhân đôi đơn giản có nghĩa là lặp lại số và b) vì chúng ta đang đếm số 1
s ở cuối, chúng ta thậm chí không cần phân biệt giữa 0
s và1
s trong quá trình. Điều này sẽ trở nên rõ ràng hơn trong một giây.
Những gì chương trình làm là trước tiên nó thêm dấu phẩy vào đầu làm điểm đánh dấu cho bao nhiêu đầu vào mà chúng tôi đã xử lý:
^
,
Bên trái điểm đánh dấu, chúng ta sẽ có giá trị chúng ta tích lũy (được khởi tạo chính xác thành biểu diễn đơn nhất bằng 0) và bên phải của giá trị sẽ là bit tiếp theo để xử lý. Bây giờ chúng tôi áp dụng thay thế sau trong một vòng lặp:
,(.)
$`$1,
Chỉ cần nhìn vào ,(.)
và $1,
, điều này di chuyển điểm đánh dấu một chút sang bên phải mỗi lần. Nhưng chúng tôi cũng chèn $`
, đó là tất cả mọi thứ ở phía trước điểm đánh dấu, tức là giá trị hiện tại, chúng tôi đang nhân đôi. Dưới đây là các bước riêng lẻ khi xử lý đầu vào 1011
, trong đó tôi đã đánh dấu kết quả của việc chèn $`
phía trên mỗi dòng (nó trống cho bước đầu tiên):
,1011
1,011
_
110,11
___
1101101,1
_______
110110111011011,
Bạn sẽ thấy rằng chúng tôi đã giữ lại và nhân đôi số 0 cùng với mọi thứ khác, nhưng vì cuối cùng chúng tôi không quan tâm đến họ, nên chúng tôi có thường xuyên nhân đôi số đó không, miễn là số lượng 1
là chính xác. Nếu bạn đếm chúng, có 11
chúng, chỉ là những gì chúng ta cần.
Vì vậy, điều đó đặt ra câu hỏi làm thế nào để đánh golf này xuống còn 12 byte. Phần đắt nhất của phiên bản 18 byte là phải sử dụng điểm đánh dấu. Mục tiêu là để thoát khỏi điều đó. Chúng tôi thực sự muốn tăng gấp đôi tiền tố của mỗi bit, vì vậy một ý tưởng đầu tiên có thể là:
.
$`$&
Vấn đề là những sự thay thế này xảy ra đồng thời, vì vậy bit đầu tiên không được nhân đôi cho mỗi bit, nhưng nó chỉ được sao chép một lần mỗi lần. Đối với đầu vào, 1011
chúng tôi sẽ nhận được (đánh dấu phần được chèn $`
):
_ __ ___
1101011011
Chúng ta vẫn cần xử lý đệ quy đầu vào để tiền tố đầu tiên được nhân đôi được nhân đôi lần thứ hai, v.v. Một ý tưởng là chèn các điểm đánh dấu ở mọi nơi và liên tục thay thế chúng bằng tiền tố:
\B
,
+%`,
¶$`
Sau khi thay thế mỗi điểm đánh dấu bằng tiền tố lần đầu tiên, chúng ta cần nhớ nơi bắt đầu của đầu vào, vì vậy chúng tôi cũng chèn nguồn cấp dữ liệu và sử dụng %
tùy chọn để đảm bảo rằng lần tiếp theo$`
chỉ chọn mọi thứ lên nguồn cấp dữ liệu gần nhất.
Điều này không hoạt động, nhưng nó vẫn quá dài (16 byte khi đếm 1
s ở cuối). Làm thế nào về chúng ta xoay chuyển mọi thứ? Những nơi chúng tôi muốn chèn các điểm đánh dấu được xác định bởi \B
(một vị trí giữa hai chữ số). Tại sao chúng ta không chỉ cần chèn tiền tố vào các vị trí đó? Điều này gần như hoạt động, nhưng sự khác biệt là trong giải pháp trước đó, chúng tôi thực sự đã loại bỏ một điểm đánh dấu trong mỗi lần thay thế và điều đó rất quan trọng để làm cho quá trình chấm dứt. Tuy nhiên,\B
nhân vật không chỉ là vị trí, vì vậy không có gì bị xóa. chúng ta có thểTuy nhiên dừng\B
thay vì khớp bằng cách chèn một ký tự không có chữ số vào vị trí này. Điều đó biến ranh giới không từ thành ranh giới từ, tương đương với việc loại bỏ ký tự đánh dấu trước đó. Và đó là những gì giải pháp 12 byte thực hiện:
+%`\B
¶$`:
Để hoàn thiện, đây là các bước xử lý riêng lẻ 1011
, với một dòng trống sau mỗi bước:
1
1:0
10:1
101:1
1
1:0
1
1:0:1
1
1:0
10:1:1
1
1:0
1
1:0:1
1
1:0
1
1:0:1:1
Một lần nữa, bạn sẽ thấy rằng kết quả cuối cùng chứa chính xác 11 1
giây.
Là một bài tập cho người đọc, bạn có thể thấy cách khái quát này khá dễ dàng đối với các cơ sở khác (đối với một vài byte bổ sung cho mỗi mức tăng trong cơ sở) không?