To rozwiązanie działa ze wszystkimi wymaganymi wartościami wejściowymi.
Największym problemem, z którym mierzy się Retina w tym wyzwaniu, jest to, że jego łańcuchy mają maksymalną długość 2 ^ 30 znaków, więc zwykły sposób radzenia sobie z liczbami (reprezentacja jedności) nie działa z wartościami większymi niż 2 ^ 30.
Aby rozwiązać ten problem, podjąłem inne podejście, zachowując rodzaj dziesiętnej reprezentacji liczb, ale gdzie każda cyfra jest zapisywana w jedności (nazywam tę reprezentację cyfrową ). Na przykład numer 341
byłby zapisany jak 111#1111#1#
w cyfrowej. Dzięki tej reprezentacji możemy teraz pracować z liczbami do 2^30/10
cyfr (~ sto milionów cyfr). Jest mniej praktyczny niż standardowe jednoargumentowe dla dowolnej arytmetyki, ale przy odrobinie wysiłku możemy wykonać dowolne operacje.
UWAGA: cyfrowo w teorii można użyć dowolnej innej podstawy (np. Binarne 110
byłoby 1#1##
w bazie 2 cyfrowo), ale ponieważ Retina ma wbudowane funkcje do konwersji między dziesiętną i jednostkową i nie ma bezpośredniego sposobu radzenia sobie z innymi bazami, liczba dziesiętna jest prawdopodobnie najłatwiejszą do zarządzania bazą.
Algorytm, którego użyłem, dokonuje kolejnych podziałów całkowitych o dwa, aż osiągniemy zero, liczba dokonanych podziałów to liczba bitów potrzebna do przedstawienia tej liczby.
Jak dzielimy przez dwa cyfrowo? Oto fragment kodu 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
Ta zamiana wystarczy, aby podzielić cyfrę cyfrową przez 2, wystarczy usunąć ewentualne 0,5 s od końca, jeśli oryginalny numer był nieparzysty.
Oto pełny kod, dzielimy przez dwa, dopóki cyfry nie będą zawierać cyfr, i umieszczamy literę n
przed ciągiem przy każdej iteracji: liczba n
na końcu jest wynikiem.
. |
$*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
Wypróbuj online!
Zaktualizowane rozwiązanie, 37 bajtów
Wielkie refaktoryzacja z wieloma dobrymi pomysłami, które grały w golfa na około jednej trzeciej długości, wszystko dzięki Martinowi Enderowi!
Główną ideą jest użycie _
jako naszego jednoznacznego symbolu: w ten sposób możemy używać regularnych cyfr w naszym ciągu, o ile przekonwertujemy je z powrotem na_
s, gdy jest to potrzebne: pozwala nam to zaoszczędzić wiele bajtów na dzieleniu i wstawianiu wielu cyfry
Oto kod:
<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
Wypróbuj online!