망막 , 56 37 바이트
이 솔루션은 필요한 모든 입력 값으로 작동합니다.
이 과제에서 Retina가 직면하는 가장 큰 문제는 문자열의 최대 길이가 2 ^ 30 자이므로 숫자를 처리하는 일반적인 방법 (단항 표현)이 2 ^ 30보다 큰 값에서는 작동하지 않는다는 것입니다.
이 문제를 해결하기 위해 숫자의 소수 표현을 유지하면서 각 숫자가 단항으로 쓰여지는 다른 접근법을 채택했습니다 (이 표현을 digitunary 라고 부릅니다 ). 예를 들어 숫자 341
는 111#1111#1#
digitunary 로 기록됩니다 . 이 표현으로 우리는 이제 최대 2^30/10
자릿수 (~ 1 억 자릿수)로 작업 할 수 있습니다 . 임의의 산술에 대해서는 표준 단항보다 실용적이지 않지만 약간의 노력으로 모든 종류의 작업을 수행 할 수 있습니다.
참고 : 이론상 digitunary는 다른 기수를 사용할 수 있지만 (예 : 2 진 110
은 1#1##
기수 2 digitunary 일 수 있음) Retina는 십진법과 단 항법 사이를 변환 할 수있는 내장 기능이 있으며 다른 염기를 처리하는 직접적인 방법이 없기 때문에 십진법이 가장 관리하기 쉬운 염기 서열 일 것입니다.
내가 사용한 알고리즘은 0에 도달 할 때까지 연속적인 정수 나누기를 2 씩 만드는 것입니다. 나누기 수는이 숫자를 나타내는 데 필요한 비트 수입니다.
그렇다면 어떻게 digitunary에서 2로 나눕니 까? 이를 수행하는 Retina 스 니펫은 다음과 같습니다.
(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
이 대체는 digitunary 숫자를 2로 나누기에 충분합니다. 원래 숫자가 홀수 인 경우 가능한 0.5를 제거해야합니다.
따라서 전체 코드는 다음과 같습니다. 숫자에 여전히 숫자가있을 때까지 계속 2로 나누고 n
매 반복마다 문자열 앞에 리터럴 을 넣습니다 n
. 끝의 수는 결과입니다.
. |
$*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
온라인으로 사용해보십시오!
업데이트 된 솔루션, 37 바이트
Martin Ender 덕분에 길이의 약 3 분의 1에 달하는 많은 좋은 아이디어로 큰 리팩토링!
주요 아이디어는 _
단항 기호 로 사용 하는 것입니다.이 방법으로 문자열 _
이 필요할 때 다시 s 로 변환되는 한 문자열에 일반 숫자를 사용할 수 있습니다 . 이는 분할 및 다중 삽입시 많은 바이트를 절약 할 수 있습니다 숫자.
코드는 다음과 같습니다.
<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
온라인으로 사용해보십시오!