Retina , 56 37 bayt
Bu çözüm gerekli tüm giriş değerleriyle çalışır.
Retina'nın bu zorlukla karşılaştığı en büyük sorun, karakter dizilerinin maksimum 2 ^ 30 karakter uzunluğuna sahip olmasıdır, bu yüzden normal sayıların (unary temsili) 2 ile 30'dan büyük değerlerle çalışmaması gerekir.
Bu problemi çözmek için farklı bir yaklaşım benimsedim, sayıları bir miktar ondalık gösterimi koruyarak, ancak her bir basamağın aynı şekilde yazıldığı (bu temsili basamak olarak adlandıracağım ). Mesela bu rakam sayısal 341
olarak yazılır 111#1111#1#
. Bu gösterimle artık rakamlara kadar 2^30/10
rakamlarla (~ yüz milyon rakam) çalışabiliriz . Keyfi aritmetik için standart unary'den daha az pratiktir, ancak biraz çaba sarf ederek her türlü işlemi yapabiliriz.
NOT: teoride digitunary (örn ikili başka tabanını kullanabilirsiniz 110
olacağını 1#1##
taban 2 digitunary), ancak Retina ondalık ve tekli ve diğer bazlar ile başa çıkmak için hiçbir doğrudan yol arasında dönüştürme yerleşiklerini beri, ondalık muhtemelen en yönetilebilir bir başlangıç noktasıdır.
Kullandığım algoritma, sıfıra ulaşana kadar iki kat ardışık tamsayı bölümleri yapmaktır, yaptığımız bölüm sayısı bu sayıyı temsil etmek için gereken bit sayısıdır.
Peki, sayısal olarak iki ile nasıl böleriz? İşte bunu yapan Retina pasajı:
(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
Bu değiştirme, bir sayısal sayıyı 2'ye bölmek için yeterlidir, orijinal sayı tuhafsa yalnızca 5.
Yani, tam kod burada, sayıda hala rakamlar gelinceye kadar ikiye bölünmeye devam ediyoruz n
ve her yinelemede dizenin önüne bir hazır bilgi veriyoruz : sonuçtaki n
sonuç.
. |
$*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
Çevrimiçi deneyin!
Güncelleştirilmiş çözüm, 37 bayt
Martin Ender sayesinde, uzunluğun yaklaşık üçte birini golf oynayan pek çok iyi fikirle büyük refactoring!
Ana fikir, _
tek sembolümüz olarak kullanmaktır : bu şekilde dizgimizdeki normal rakamları tekrar kullanabildiğimiz sürece kullanabiliriz._
, gerektiğinde s'ye çevirdiğimiz sürece kullanabiliriz. basamak.
İşte 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
Çevrimiçi deneyin!