Masalah:
Dalam pilihan bahasa Anda, tulis fungsi terpendek yang mengembalikan lantai akar kuadrat dari integer 64-bit yang tidak ditandatangani.
Kasus uji:
Fungsi Anda harus bekerja dengan benar untuk semua input, tetapi di sini ada beberapa yang membantu mengilustrasikan ide tersebut:
INPUT ⟶ OUTPUT
0 ⟶ 0
1 ⟶ 1
2 ⟶ 1
3 ⟶ 1
4 ⟶ 2
8 ⟶ 2
9 ⟶ 3
15 ⟶ 3
16 ⟶ 4
65535 ⟶ 255
65536 ⟶ 256
18446744073709551615 ⟶ 4294967295
Aturan:
- Anda dapat memberi nama fungsi apa pun yang Anda suka. (Fungsi yang tidak disebutkan namanya, anonim, atau lambda baik-baik saja, asalkan fungsi tersebut dapat dipanggil.)
- Hitungan karakter adalah yang terpenting dalam tantangan ini, tetapi runtime juga penting. Saya yakin Anda dapat memindai ke atas secara iteratif untuk jawaban dalam waktu O (√n) dengan jumlah karakter yang sangat kecil, tetapi waktu O (log (n)) akan benar-benar lebih baik (yaitu, dengan asumsi nilai input n, tidak sedikit-panjang n).
- Anda mungkin ingin mengimplementasikan fungsi menggunakan integer murni dan / atau artitmetika boolean. Namun, jika Anda benar-benar ingin menggunakan perhitungan floating-point, maka itu tidak masalah selama Anda memanggil fungsi pustaka. Jadi, hanya mengatakan
return (n>0)?(uint32_t)sqrtl(n):-1;
dalam C adalah terlarang meskipun itu akan menghasilkan hasil yang benar. Jika Anda menggunakan aritmatika floating-point, Anda dapat menggunakan*
,/
,+
,-
, dan eksponensial (misalnya,**
atau^
jika itu built-in operator dalam bahasa pilihan Anda, tetapi eksponensial hanya kekuasaan tidak kurang dari 1 ). Pembatasan ini untuk mencegah "kecurangan" dengan memanggilsqrt()
atau varian atau meningkatkan nilai ke kekuatan ½. - Jika Anda menggunakan operasi floating-point (lihat # 3), Anda tidak diharuskan untuk mengembalikan tipe integer; hanya bahwa nilai kembali adalah bilangan bulat, mis. lantai (sqrt (n)), dan dapat menampung nilai 32-bit yang tidak ditandatangani.
- Jika Anda menggunakan C / C ++, Anda dapat mengasumsikan keberadaan tipe integer 64-bit dan 32-bit yang tidak ditandatangani, misalnya,
uint64_t
danuint32_t
seperti yang didefinisikan dalamstdint.h
. Jika tidak, pastikan saja tipe integer Anda mampu menahan integer 64-bit yang tidak ditandatangani. - Jika bahasa Anda tidak mendukung bilangan bulat 64-bit (misalnya, Brainfuck tampaknya hanya memiliki dukungan bilangan bulat 8-bit), maka lakukan yang terbaik dengan itu dan nyatakan batasan dalam judul jawaban Anda. Yang mengatakan, jika Anda dapat mengetahui cara mengkodekan integer 64-bit dan mendapatkan akar kuadrat dengan benar menggunakan aritmatika primitif 8-bit, maka lebih banyak kekuatan untuk Anda!
- Bersenang-senang dan menjadi kreatif!
code-golf
math
arithmetic
Todd Lehman
sumber
sumber
O(log_2 n) === O(log_4 n)
.log_4(n) = log_2(n) / log_2(2) = log_2(n) / 2
Jawaban:
CJam, 17 (atau 10) byte
Cobalah online dengan memverifikasi kasus uji:
Itu tidak akan lulus ujian terakhir karena masalah pembulatan, tetapi karena
18446744073709551615
bukan Integer di CJam (ini adalah Integer Besar ), kami masih bagus, kan?Jika tidak, kode berikut (dan sedikit lebih lama) akan memperbaiki kesalahan tersebut:
Bukan solusi terpendek lagi, tapi faaast .
Bagaimana itu bekerja
sumber
<.@%~^&1.5
. Dapatkah saya memposting ini sebagai jawaban terpisah (karena pada dasarnya ini adalah port yang tepat untuk Anda)?4294967295
dan4294967296
terlihat sangat mirip ...Haskell,
2826Saya percaya bahwa ini adalah entri terpendek dari bahasa apa pun yang tidak dirancang untuk bermain golf.
Ini nama fungsi
s
dengan parametera
dan mengembalikan satu minus angka pertama yang kuadratnya lebih besar daria
. Berjalan sangat lambat (O (sqrt n), mungkin?).sumber
[...]!!0
) lebih pendek dari kepala?Golfscript, 17 karakter
Saya bisa memberi nama fungsi saya dengan cara apa pun yang saya suka, tetapi saya memutuskan untuk tidak menyebutkannya sama sekali. Tambahkan dua karakter untuk nama itu, tambahkan tiga untuk nama itu dan tidak meninggalkannya di tumpukan, kurangi satu karakter jika menyediakan program lengkap tidak masalah.
Kekejian ini berjalan tidak dalam waktu logaritmik dalam nilai input, bukan dalam waktu O (sqrt n), dibutuhkan jumlah waktu rejan linear untuk menghasilkan hasilnya. Itu juga membutuhkan banyak ruang. Benar-benar menghebohkan. Tapi ... ini kode-golf.
Algoritme adalah:
sumber
Pyth , 14 karakter
Menyediakan fungsi bernama, s, yang menghitung akar kuadrat dengan memfilter daftar dari 0 ke n untuk kuadrat yang lebih besar dari input, lalu mencetak angka tersebut. Tidak menggunakan eksponensial atau mengapung.
Contoh penggunaan:
sumber
Retina (non-bersaing - Bahasa lebih baru daripada tantangan), 43
Saat mengerjakan jawaban ini , terpikir oleh saya bahwa metode yang sama dapat digunakan untuk menghitung akar kuadrat integer menggunakan retina:
Ini bergantung pada fakta bahwa kuadrat sempurna dapat dinyatakan sebagai
1+3+5+7+...
, dan secara wajar bahwa jumlah istilah dalam ungkapan ini adalah akar kuadrat.Cobalah online. (Baris pertama ditambahkan untuk memungkinkan beberapa testcase dijalankan.)
Jelas karena konversi desimal ke unary, ini hanya akan bekerja untuk input yang relatif kecil.
sumber
Perl, 133 karakter
Bukan yang terpendek sejauh ini, tetapi menggunakan algoritma digit-per-digit untuk menangani input ukuran apa pun, dan berjalan dalam waktu O (log n). Mengubah secara bebas antara angka-sebagai-string dan angka-sebagai-angka. Karena produk terbesar yang mungkin adalah root-sejauh ini dengan kuadrat dari satu digit, ia harus mampu mengambil akar kuadrat hingga 120-bit atau lebih pada sistem 64-bit.
Didekompresi, yaitu:
sumber
if length%2
bukanif(length)%2
? Itu akan mengurangi 1 karakter. Juga, akan bekerja untuk mengatakan$y=$z,$d=$_ if
bukan($y,$d)=($z,$_)if
? Saya pikir itu akan mengurangi 3 karakter lagi.for
loop sebagai:$a<($z=$_*(20*$r+$_))or$y=$z,$d=$_ for(1..9);
%2
), tetapi yang lain valid. Saya akan mengerjakannya.for
tidak perlu tanda kurung; menambahkan itu ke saran Anda total saya 6 karakter. Terima kasih!Matlab (56) / Oktaf (55)
Ini berhasil akar kuadrat dengan menggunakan metode titik tetap. Itu konvergen dalam maksimal 36 langkah (untuk 2 ^ 64-1 sebagai argumen) dan kemudian memeriksa apakah itu yang lebih rendah dari akar integer 'mungkin'. Karena selalu menggunakan 36 iterasi, ia memiliki runtime O (1) = P
Argumennya dianggap uint64.
Matlab:
Oktaf:
sumber
Ruby - 36 karakter
sumber
while
loop berakhir tepat ketika g menyatu ke lantai (√n) yang merupakan nilai yang diinginkan. Apakah Anda melihat kasus di mana ini tidak benar?Python (39)
Pendekatan rekursif alami. Menghitung akar kuadrat potensial hingga kuadratnya terlalu tinggi, lalu turun dengan 1. Gunakan Stackless Python jika Anda khawatir melebihi kedalaman tumpukan.
The
and/or
idiom setara dengan operator ternary sebagaiEdit: Aku bisa malah mendapatkan 25 karakter dengan memanfaatkan aturan "Anda dapat menggunakan
*
,/
,+
,-
, dan eksponensial (misalnya,**
atau^
jika itu adalah eksponensial built-in operator dalam bahasa pilihan Anda, tetapi hanya kekuasaan tidak kurang dari 1). " (Sunting: Rupanya Dennis sudah menemukan dan mengeksploitasi trik ini.)Saya menggunakan operator divisi integer
//
dari Python 3 untuk membulatkan ke bawah. Sayangnya, saya menghabiskan banyak karakter agar casen=0
tidak memberikan pembagian dengan kesalahan 0. Jika bukan karena itu, saya bisa melakukan 18 karakterAturan juga tidak mengatakan fungsi harus dinamai (tergantung bagaimana Anda mengartikan "Anda dapat memberi nama fungsi apa pun yang Anda suka."), Tetapi jika ya, itu adalah dua karakter lagi.
sumber
C99 (58 karakter)
Ini adalah contoh jawaban yang saya tidak akan menganggapnya sebagai jawaban yang baik, meskipun menarik dari sudut pandang kode golf karena sangat tidak sopan, dan saya pikir akan menyenangkan untuk memasukkannya ke dalam campuran:
Asli: 64 karakter
Alasan yang satu ini mengerikan adalah karena ia berjalan dalam waktu O (√n) daripada waktu O (log (n)). (Di mana n adalah nilai input.)
Edit: 63 karakter
Mengubah
r-1
to--r
dan berbatasan denganreturn
:Edit: 62 karakter
Memindahkan kenaikan loop ke dalam bagian kondisional loop (catatan: ini memiliki perilaku tidak dijamin karena urutan operasi sehubungan dengan operator preincrement adalah khusus-kompiler):
Edit: 60 karakter
Menambahkan
typedef
untuk disembunyikanuint64_t
(kredit ke pengguna technosaurus untuk saran ini)Edit: 58 karakter
Sekarang membutuhkan parameter kedua dilewatkan sebagai 0 dalam doa fungsi, misalnya,
r(n,0)
bukan hanyar(n)
. Ok, untuk kehidupan saya, pada titik ini saya tidak bisa melihat bagaimana mengompres ini lebih jauh ... siapa pun?sumber
uint64_t s(uint64_t n){for(uint64_t r=n;--n>r/n;);return n;}
.--n
kapann==0
akan –1, dan ini adalah nilai yang tidak ditandatangani, jadi –1 akan menjadi 2⁶⁴ – 1.#define Z uint64_t
... atau typedef akan menghemat pasangann/++r/r
memiliki perilaku yang tidak jelas ....Golfscript - 14 karakter
Temukan nomor terkecil
i
lebih sedikit dari pada inputn
yang manan < i*i
. Kembalii - 1
.Yaitu
[0..n-1].first(i => n < i*i) - 1
Penjelasan untuk mereka yang tidak tahu Golfscript juga, untuk panggilan sampel dengan input
5
:sumber
1
mungkin membutuhkan dua karakter.Haskell,
147138134128 byteBukan kode terpendek di dunia, tetapi itu berjalan di O (log n), dan pada nomor berukuran sewenang-wenang:
Ini melakukan pencarian biner dari rentang [0..n] untuk menemukan perkiraan lebih rendah terbaik ke sqrt (n). Ini adalah versi yang tidak dikoleksi:
Sunting: Menyimpan dua byte dengan mengganti klausa "jika tidak" dengan "0 <1" sebagai versi yang lebih pendek dari "True", dan beberapa lainnya dengan menggarisbawahi g * g.
Juga, jika Anda senang dengan O (sqrt (n)) Anda bisa melakukannya
untuk 35 karakter, tapi apa yang menyenangkan itu?
Sunting 2: Saya baru menyadari bahwa karena pasangan diurutkan berdasarkan urutan kamus, alih-alih melakukan min2Cycle. map fst, saya bisa melakukan fst. min2Cycle. Dalam kode golf, yang artinya mengganti f $ map pertama dengan fst pertama, menghemat 4 byte lebih banyak.
Sunting 3: Disimpan enam byte lagi berkat banggahaskeller!
sumber
JavaScript
918886: Dioptimalkan untuk kecepatanJavaScript 46: Tidak dioptimalkan untuk kecepatan
Berikut ini adalah JSFiddle: http://jsfiddle.net/rmadhuram/1Lnjuo4k/
sumber
function s(n){for(a=1;++a*a<n;);return a}
C 95
97Edit Typedef, disarankan oleh @Michaelangelo
Ini harus lebih atau kurang merupakan implementasi langsung dari algoritma Heron. Satu-satunya kekhasan adalah dalam menghitung rata-rata menghindari integer overflow: a = (m + n) / 2 tidak bekerja untuk angka biiiig.
sumber
C #
646255Karena ini adalah kode-golf (dan saya buruk dengan matematika), dan runtime hanyalah saran, saya telah melakukan pendekatan naif yang berjalan dalam waktu linier:
( tes pada dotnetfiddle )
Tentu saja, ini sangat lambat untuk input yang lebih besar.
sumber
return i-1
kereturn--i
?i*i<=a
, apakah itu dijamin bilangan bulat aritmatika dari tipe yang biasa? (Saya tidak terbiasa dengan C #.) Jika demikian, dan jika C # memungkinkan konversi integer implisit ke boolean seperti C, maka Anda mungkin dapat menyimpan satu karakter lagi dengan mengubahnya kea/i/i
.Decimal
, nilai dan presisi max lebih tinggi), untuk menghindari overflow karena hasil perkalian berpotensi melewati satu langkah terakhirUInt64.MaxValue
. Tetapi C # tidak memiliki konversi implisit ke Boolean. Saya harus bisa mengubahreturn
, terima kasih. Saya akan melakukannya ketika saya kembali ke komputer.Clojure - 51 atau 55 byte
Memeriksa semua angka dari n hingga 0, memberikan yang pertama di mana
x^2 <= n
. Runtime adalahO(n - sqrt n)
Tanpa nama:
Bernama:
Contoh:
sumber
Befunge 93 - 48 Bytes atau 38 Karakter
Cobalah di sini.
sumber
Cobra - 62
Angkatan - 74
sumber
Haskell,
535049 karakter, O (log n)solusi ini mengimplementasikan metode newton-raphson, meskipun mencari bilangan bulat bukan mengapung. wiki: http://en.wikipedia.org/wiki/Newton%27s_method
kerumitan tampaknya tentang O (log n), tetapi apakah ada buktinya? tolong jawab di komentar.
sumber
\g->div(n+g^2)$2*g
menghemat 7 byte.J (10)
Sangat, sangat, sangat terinspirasi oleh jawaban @ Dennis :
Dan sedikit lebih lama, tetapi dengan kinerja yang lebih baik (saya curiga):
floor(halve under log)
Untuk mengeksekusi, bagian indentasi adalah input:
sumber
APL - 12 karakter, 19 byte
contoh gunakan:
mengembalikan 4
Tes vektor
kembali
1 1 1 1 2 2 3 3 4 255 256 4294967296
Coba Online
Terima kasih banyak kepada : pengguna "ssdecontrol" untuk algoritme
sumber
0
→1
! Menggunakan Dyalog APL , Anda dapat mengatur⎕DIV←1
(yang banyak digunakan sebagai default) untuk mendapatkan hasil yang benar.C99 (108 karakter)
Ini adalah solusi saya sendiri di C99, yang diadaptasi dari suatu algoritma dalam sebuah artikel di Wikipedia . Saya yakin ini harus dilakukan jauh lebih baik daripada ini dalam bahasa lain.
Golf:
Golf sebagian:
Tidak Disatukan:
sumber
a
, gunakann
.n
sehingga sebelum kembali saya bisa membuat pernyataan (tidak ditampilkan) bahwa r ^ 2 <= n <(r + 1) ^ 2. Dengan pernyataan itu dihilangkan, itu perlu lagi untuk tetapn
utuh.const
dalam versi yang tidak disolf.JavaScript
7381 (untuk memenuhi persyaratan angka 64-bit)n=prompt();g=n/3;do{G=g,g=(n/g+g)/2}while(1E-9<Math.abs(G-g))alert(Math.floor(g))
Menerapkan algoritma Heron of Alexandria ...
sumber
|0
mempengaruhi hingga 32-bit sedangkanMath.floor
lebih efektif pada 64-bit ... Saya telah memperbarui kode saya, harus mengambil 8 karakter tambahan untuk melakukannya ...Powershell (52) Terbatas untuk Int32 (-2.147.483.648 hingga 2.147.483.647)
Saya berteriak pada Powershell sekarang mencoba untuk membuat test case terakhir bekerja tetapi tidak peduli apa yang saya lakukan Powershell akhirnya menggunakan variabel pipa $ _ sebagai Int32, dan saya tidak dapat menemukan cara mengatasinya sekarang.
Jadi saya akan membatasi jawaban saya untuk saat ini. Jika saya dapat menemukan cara yang lebih baik untuk menangani uint64, saya akan mengedit. (Omong kosong terakhir terlalu besar untuk tipe Int64 normal Powershell!)
Berikut adalah beberapa test case (dengan sedikit output tambahan yang saya gunakan untuk melacak waktu)
Saya tidak tahu O () saya, tapi ini sepertinya lompatan yang cukup dramatis.
sumber
Peringatan: pada 2011, R tidak memiliki dukungan bawaan untuk integer 64 bit seperti yang saya asumsikan. Jawaban-jawaban ini mungkin tidak valid dalam hal teknis, tetapi sekali lagi R telah banyak berubah dalam 3 tahun terakhir.
R, 85
Menggunakan metode Newton:
yang menyatu secara kuadrat. +2 karakter untuk menetapkan fungsi ke variabel untuk pembandingan:
R, 37
Paksaan:
Dan cek yang sama:
R, 30
The murah / brilian eksponensial trik :
yang juga terjadi sangat cepat (walaupun tidak secepat built-in):
sumber
C, 38
Terjemahan dari kiriman Keempat saya. Lambat tapi benar. O (√n). Diuji pada OS X (64 bit).
sumber
dc, 50 byte
Ditata dan dijelaskan:
sumber
C,
139137136 bytePercobaan pertama saya di kode golf. Sepertinya ini adalah yang terpendek dalam C yang sesuai dengan persyaratan "efisien", karena berjalan dalam
O(log n)
waktu, hanya menggunakan penambahan dan pergeseran bit. Meskipun saya yakin itu bisa lebih pendek lagi ...Seharusnya berfungsi dengan baik untuk nilai integer yang lebih besar juga asalkan
a=32
bagian tersebut diubaha=NUMBITS/2
.sumber
(t++)
alih-alih hanyat++
dalam penugasanr
?a--+1
sebagai cara untuk menulis menghindaria-- != UINT64_C(-1)
. Apakah Anda mempelajari trik itu di suatu tempat atau menciptakannya sendiri?C - 50 (61 tanpa global)
Ini menggunakan variabel global sebagai parameter dan nilai kembali untuk menghemat ruang.
Tidak ada versi global:
sumber
C ++ 125
sumber
x+=(d<0)-0.5;
... menyimpan 5 karakter lagi?main
adalah fungsi, tetapi tidak bisa dipanggil dari dalam program seperti apa adanyaf(y)
.)while((d=x*x-y)>0.5)
bukanwhile((d=(x*x-y))>0.5)
. Menghemat 2 karakter lebih banyak. :)