Giải pháp này hoạt động với tất cả các giá trị đầu vào cần thiết.
Vấn đề lớn nhất mà Retina gặp phải trong thử thách này là thực tế là các chuỗi của nó có độ dài tối đa là 2 ^ 30 ký tự, do đó, cách xử lý thông thường với các số (biểu diễn đơn nhất) không hoạt động với các giá trị lớn hơn 2 ^ 30.
Để giải quyết vấn đề này, tôi đã thông qua một cách tiếp cận khác, giữ một loại đại diện thập phân của số, nhưng trong đó mỗi chữ số được viết bằng unary (Tôi sẽ gọi đại diện này digitunary ). Ví dụ, số 341
sẽ được viết dưới dạng 111#1111#1#
số. Với biểu diễn này, giờ đây chúng ta có thể làm việc với số lượng lên đến 2^30/10
chữ số (~ một trăm triệu chữ số). Nó ít thực tế hơn so với unary tiêu chuẩn cho số học tùy ý, nhưng với một chút nỗ lực, chúng tôi có thể thực hiện bất kỳ loại hoạt động nào.
LƯU Ý: về mặt lý thuyết, số hóa có thể sử dụng bất kỳ cơ sở nào khác (ví dụ: nhị phân 110
sẽ 1#1##
ở cơ sở số 2), nhưng vì Retina đã tích hợp để chuyển đổi giữa số thập phân và đơn nguyên và không có cách nào trực tiếp để xử lý các cơ sở khác, nên số thập phân có thể là cơ sở dễ quản lý nhất.
Thuật toán tôi đã sử dụng đang thực hiện chia hai số nguyên liên tiếp cho đến khi chúng tôi đạt đến 0, số lượng phân chia chúng tôi thực hiện là số bit cần thiết để biểu diễn số này.
Vì vậy, làm thế nào để chúng ta chia cho hai trong số hóa? Đây là đoạn Retina thực hiện điều đó:
(1*)(1?)\1# We divide one digit, the first group captures the result, the second group captures the remainder
$1#$2$2$2$2$2 The result is put in place of the old number, the remainder passes to the next digit (so it is multiplied by 10) and is divided by two there -> 5 times the remainder goes to the next digit
Sự thay thế này là đủ để chia một số kỹ thuật số cho 2, chúng ta chỉ cần loại bỏ 0,5 giây có thể từ cuối nếu số ban đầu là số lẻ.
Vì vậy, đây là mã đầy đủ, chúng tôi tiếp tục chia cho hai cho đến khi vẫn còn các chữ số trong số và đặt một chữ n
đứng trước chuỗi ở mỗi lần lặp: số n
ở cuối là kết quả.
. |
$*1# Convert to digitunary
{`^(.*1) Loop:|
n$1 add an 'n'
(1*)(1?)\1# |
$1#$2$2$2$2$2 divide by 2
)`#1*$ |
# erase leftovers
n Return the number of 'n's in the string
Hãy thử trực tuyến!
Giải pháp cập nhật, 37 byte
Tái cấu trúc lớn với nhiều ý tưởng hay, đánh golf khoảng một phần ba chiều dài, tất cả là nhờ Martin Ender!
Ý tưởng chính là sử dụng _
làm biểu tượng đơn nguyên của chúng tôi: bằng cách này, chúng tôi có thể sử dụng các chữ số thông thường trong chuỗi của mình, miễn là chúng tôi chuyển đổi chúng thành _
s khi cần: điều này cho phép chúng tôi lưu nhiều byte khi chia và chèn nhiều chữ số.
Đây là mã:
<empty line> |
# put a # before each digit and at the end of the string
{`\d Loop:|
$*_ Replace each digit with the corrisponding number of _
1`_ |
n_ Add an 'n' before the first _
__ |
1 Division by 2 (two _s become a 1)
_# |
#5 Wherever there is a remainder, add 5 to the next digit
}`5$ |
Remove the final 5 you get when you divide odd numbers
n Return the number of 'n's in the string
Hãy thử trực tuyến!