Retina , 56 37 byte
Solusi ini bekerja dengan semua nilai input yang diperlukan.
Masalah terbesar yang dihadapi Retina dalam tantangan ini adalah kenyataan bahwa string-nya memiliki panjang maksimum 2 ^ 30 karakter, jadi cara biasa menangani angka (representasi unary) tidak bekerja dengan nilai lebih besar dari 2 ^ 30.
Untuk mengatasi masalah ini saya mengadopsi pendekatan yang berbeda, menjaga semacam representasi angka desimal, tetapi di mana setiap digit ditulis dalam unary (Saya akan menyebut digitunary representasi ini ). Misalnya angka 341
akan ditulis 111#1111#1#
dalam digitunary. Dengan representasi ini sekarang kita dapat bekerja dengan jumlah hingga 2^30/10
digit (~ seratus juta digit). Ini kurang praktis daripada standar unary untuk aritmatika sewenang-wenang, tetapi dengan sedikit usaha kita bisa melakukan segala jenis operasi.
CATATAN: digitunary dalam teori dapat menggunakan basis lain (misalnya biner 110
akan menjadi 1#1##
basis 2 digitunary), tetapi karena Retina memiliki builtin untuk mengkonversi antara desimal dan unary dan tidak ada cara langsung untuk berurusan dengan basis lain, desimal mungkin merupakan basis yang paling dapat dikelola.
Algoritma yang saya gunakan adalah membuat pembagian integer berturut-turut sebanyak dua hingga kita mencapai nol, jumlah divisi yang kami buat adalah jumlah bit yang diperlukan untuk mewakili angka ini.
Jadi, bagaimana kita membagi dua menjadi digitunary? Berikut cuplikan Retina yang melakukannya:
(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
Penggantian ini cukup untuk membagi angka digital dengan 2, kita hanya perlu menghapus 0,5 mungkin dari akhir jika nomor aslinya ganjil.
Jadi, inilah kode lengkapnya, kita terus membaginya dengan dua sampai masih ada angka dalam bilangan, dan menempatkan literal n
di depan string pada setiap iterasi: jumlah n
pada akhirnya adalah hasilnya.
. |
$*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
Cobalah online!
Solusi yang diperbarui, 37 byte
Refactoring besar dengan banyak ide bagus yang bermain golf sekitar sepertiga panjangnya, semua berkat Martin Ender!
Gagasan utamanya adalah untuk digunakan _
sebagai simbol unary kita: dengan cara ini kita dapat menggunakan digit reguler dalam string kita, selama kita mengubahnya kembali menjadi _
s ketika diperlukan: ini memungkinkan kita menyimpan banyak byte pada pembagian dan penyisipan banyak digit.
Ini kodenya:
<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
Cobalah online!