Berikan angka terkecil yang memiliki pembagi N


17

Fungsi Anda mengambil nomor alami dan mengembalikan nomor alami terkecil yang memiliki jumlah pembagi yang tepat, termasuk dirinya sendiri.

Contoh:

f(1) =  1 [1]
f(2) =  2 [1, 2]
f(3) =  4 [1, 2, 4]
f(4) =  6 [1, 2, 3, 6]
f(5) = 16 [1, 2, 4, 8, 16]
f(6) = 12 [1, 2, 3, 4, 6, 12]
 ...

Fungsi tidak harus mengembalikan daftar pembagi, mereka hanya ada di sini untuk contoh.


2
Apakah ini kode-golf atau kode-tantangan?
marinus

Ups, lupakan tag itu, kode-golf!
SteeveDroz

Jawaban:


6

APL, 25 24 23 karakter

f←{({+/⍵=⍵∧⍳⍵}¨⍳2*⍵)⍳⍵}

Menentukan fungsi fyang kemudian dapat digunakan untuk menghitung angka:

> f 13
4096

> f 14
192

Solusinya memanfaatkan fakta bahwa LCM (n, x) == n iff x membagi n . Dengan demikian, blok {+/⍵=⍵∧⍳⍵}hanya menghitung jumlah pembagi. Fungsi ini diterapkan ke semua angka dari 1 hingga 2 ^ d ¨⍳2*⍵ . Daftar yang dihasilkan kemudian dicari untuk d sendiri ( ⍳⍵) yang merupakan fungsi yang diinginkan f (d) .


Selamat! 23 karakter ... wow!
SteeveDroz

19:{⍵⍳⍨(+/⊢=⊢∧⍳)¨⍳2*⍵}
Adám

Saya tidak berpikir Anda perlu mendefinisikan f.
Zacharý

5

GolfScript, 29 28 karakter

{.{\.,{)1$\%},,-=}+2@?,?}:f;

Sunting: Satu char dapat disimpan jika kami membatasi pencarian untuk <2 ^ n, terima kasih kepada Peter Taylor untuk ide ini.

Versi sebelumnya:

{.{\)..,{)1$\%},,-@=!}+do}:f;

Upaya dalam GolfScript, jalankan online .

Contoh:

13 f p  # => 4096
14 f p  # => 192
15 f p  # => 144

Kode dasarnya berisi tiga blok yang dijelaskan secara rinci di baris berikut.

# Calculate numbers of divisors
#         .,{)1$\%},,-    
# Input stack: n
# After application: D(n)

.,          # push array [0 .. n-1] to stack
{           # filter array by function
  )         #   take array element and increase by one
  1$\%      #   test division of n ($1) by this value
},          # -> List of numbers x where n is NOT divisible by x+1
,           # count these numbers. Stack now is n xd(n)
-           # subtracting from n yields the result



# Test if number of divisors D(n) is equal to d
#         {\D=}+   , for D see above
# Input stack: n d
# After application: D(n)==d

{
  \         # swap stack -> d n
  D         # calculate D(n) -> d D(n)
  =         # compare
}+          # consumes d from stack and prepends it to code block         



# Search for the first number which D(n) is equal to d
#         .T2@?,?    , for T see above
# Input stack: d
# After application: f(d)

.           # duplicate -> d d
T           # push code block (!) for T(n,d) -> d T(n,d)
2@?         # swap and calculate 2^d -> T(n,d) 2^d
,           # make array -> T(n,d) [0 .. 2^d-1]
?           # search first element in array where T(n,d) is true -> f(d)

Tampaknya masuk ke loop tak terbatas untuk input 1.
Peter Taylor

Solusi terbaik saya sejauh ini meminjam cukup banyak dari milik Anda, sejauh yang menurut saya layak menjadi komentar daripada jawaban yang terpisah.
Peter Taylor

4

Python: 64

Merevisi solusi Bakuriu dan memasukkan saran grc serta trik dari solusi R plannapus, kami mendapatkan:

f=lambda n,k=1:n-sum(k%i<1for i in range(1,k+1))and f(n,k+1)or k

4

Python: 66

f=lambda n,k=1:n==sum(k%i<1for i in range(1,k+1))and k or f(n,k+1)

Di atas akan meningkatkan RuntimeError: maximum recursion depth exceededdengan input kecil di CPython, dan bahkan menetapkan batas ke jumlah yang sangat besar itu mungkin akan memberikan beberapa masalah. Pada implementasi python yang mengoptimalkan rekursi ekor, ia seharusnya bekerja dengan baik.

Versi yang lebih verbose, yang seharusnya tidak memiliki batasan seperti itu, adalah solusi 79 byte berikut :

def f(n,k=1):
    while 1:
        if sum(k%i<1for i in range(1,k+1))==n:return k
        k+=1

Saya mencapai batas rekursi pada 11, 13, 17, 19, dan lainnya.
Steven Rumbalski

@StevenRumbalski Tidak ada yang menyebutkan bahwa program harus bekerja dengan bilangan bulat yang sewenang-wenang. Sayangnya jumlahnya tumbuh cukup cepat bahkan dengan input kecil.
Bakuriu

Anda dapat menyimpan beberapa karakter dengan menggunakan penggantian if elsedengan and ordan ==1dengan <1:f=lambda n,k=1:n==sum(k%i<1for i in range(1,k+1))and k or f(n,k+1)
grc

Karena saya menemukan 66 terlalu jahat, Anda dapat menyimpan 2 karakter jika Anda menggunakansum(k%-~i<1for i in range(k))
Volatility

f=lambda n,k=1:n==sum(k%-~i<1for i in range(k))or-~f(n,k+1)menghemat 7 byte.
Dennis

4

Mathematica 38 36

(For[i=1,DivisorSum[++i,1&]!=#,];i)&

Pemakaian:

(For[i=1,DivisorSum[++i,1&]!=#,];i)&@200

Hasil:

498960

Edit

Beberapa penjelasan:

DivisorSum [n, form] mewakili jumlah form [i] untuk semua i yang membagi n.

Ketika form[i]saya menggunakan fungsi 1 &, itu selalu kembali 1, sehingga secara efektif menghitung jumlah pembagi dengan cara singkat.


Tidak ada tag kode-golf jadi saya memberikan jawaban panjang! oops
DavidC

@DavidCarraher Saya baru saja menebak :)
Dr. belisarius

Saya pikir saya tahu apa yang DivisorSumdikembalikan (jumlah pembagi) tetapi saya tidak melihat bagaimana itu penting untuk menjawab pertanyaan yang diajukan. Tolong jelaskan bagaimana cara kerjanya. BTW, saya pikir Anda harus memasukkan data waktu untuk n = 200; fungsinya sangat cepat, mengingat semua angka yang harus diperiksa.
DavidC

@ DavidCarraher Lihat edit. Re: timing - Mesin saya terlalu lambat :(
Dr. belisarius

Apakah Mathematica tidak memiliki built-in yang cukup untuk pendekatan yang lebih canggih di sekitar anjak menjadi lebih pendek? Jika itu masalahnya, saya kecewa.
Peter Taylor

3

J, 33 karakter

Cukup cepat, melewati semua angka yang lebih kecil dan menghitung jumlah pembagi berdasarkan faktorisasi.

   f=.>:@]^:([~:[:*/[:>:_&q:@])^:_&1

   f 19
262144

3

Haskell 54

Solusi cepat dan kotor (sangat mudah dibaca dan tidak rumit):

f k=head[x|x<-[k..],length[y|y<-[1..x],mod x y==0]==k]

Hasil edit tidak membuat jawaban lebih pendek, tetapi mungkin lebih mirip haskell. Juga saya selalu menyertakan baris tambahan untuk panjang kode saya, apakah ini salah?
shiona

Saya pikir Anda salah menghitung; tujuan utama pengeditan adalah untuk memperbarui hitungan. Perubahan kode itu sendiri kecil. Saya pikir entri lain di sini juga tidak menghitung baris tambahan, seperti misalnya entri untuk J (33 karakter).
Will Ness

2

K, 42

Solusi rekursif yang tidak efisien yang meledakkan tumpukan dengan cukup mudah

{{$[x=+/a=_a:y%!1+y;y;.z.s[x;1+y]]}[x;0]} 

.

k){{$[x=+/a=_a:y%!1+y;y;.z.s[x;1+y]]}[x;0]}14
192
k){{$[x=+/a=_a:y%!1+y;y;.z.s[x;1+y]]}[x;0]}13
'stack

2

APL 33

F n            
i←0              
l:i←i+1          
→(n≠+/0=(⍳i)|i)/l
i 

Contoh:

F 6
12           

2

APL (25)

{⍵{⍺=+/0=⍵|⍨⍳⍵:⍵⋄⍺∇⍵+1}1}

Penipu! echo -n '{⍵ {⍺ = + / 0 = ⍵ | ⍨⍳⍵: ⍵⋄⍺∇⍵ + 1} 1}' | wc -c memberi saya 47! Tapi sungguh, bisakah Anda memberi saya tautan ke beberapa tutorial mudah untuk APL? Saya mencoba untuk google dan telah membaca beberapa artikel, tetapi pada akhirnya saya selalu ingin bertanya "Mengapa mereka melakukan ini :(?". Saya tidak pernah bekerja dengan bahasa sintaksis non-ASCII dan ingin mengetahui apakah itu memiliki keuntungan nyata
XzKto

Ini untuk Dyalog APL, yang saya gunakan, Anda dapat mengunduh versi Windows secara gratis di situs yang sama. dyalog.com/MasteringDyalogAPL/MasteringDyalogAPL.pdf
marinus

Wow, sepertinya saya benar-benar mengerti yang ini. Terima kasih atas tautannya! Satu-satunya downside adalah bahwa mereka memiliki beberapa kebijakan lisensi yang sangat aneh, tetapi mungkin saya hanya perlu meningkatkan bahasa Inggris saya)
XzKto

2

R - 47 karakter

f=function(N){n=1;while(N-sum(!n%%1:n))n=n+1;n}

!n%%1:nmemberikan vektor booleans: BENAR ketika bilangan bulat dari 1 ke n adalah pembagi n dan SALAH jika tidak. sum(!n%%1:n)memaksa booleans ke 0 jika FALSE dan 1 jika TRUE dan menjumlahkannya, sehingga itu N-sum(...)adalah 0 ketika jumlah pembagi adalah N. 0 kemudian diartikan sebagai FALSE olehwhile yang kemudian berhenti.

Pemakaian:

f(6)
[1] 12
f(13)
[1] 4096

2

Javascript 70

function f(N){for(j=i=m=1;m-N||j-i;j>i?i+=m=j=1:m+=!(i%++j));return i}

Benar-benar hanya ada 46 karakter yang bermakna:

for(j=i=m=1;m-N||j-i;j>i?i+=m=j=1:m+=!(i%++j))

Saya mungkin harus belajar bahasa dengan sintaks yang lebih pendek :)


N=>eval("for(j=i=m=1;m-N||j-i;j>i?i+=m=j=1:m+=!(i%++j));i")
TuxCrafting

2

Haskell: 49 karakter

Itu bisa dilihat sebagai peningkatan dari solusi Haskell sebelumnya, tetapi itu dikandung dengan sendirinya (peringatan: sangat lambat):

f n=until(\i->n==sum[1|j<-[1..i],rem i j<1])(+1)1

Ini fungsi yang cukup menarik, misalnya perhatikan bahwa f (p) = 2 ^ (p-1), di mana p adalah bilangan prima.


Cara yang efisien, bukan pendek, untuk menghitungnya adalah dengan faktor nmenjadi bilangan prima (dengan pengulangan), mengurutkan menurun, mengurangi masing-masing, zip dengan urutan bilangan prima yang tak terbatas, dan kemudian melipat produkp^(factor-1)
Peter Taylor

2
@PeterTaylor Tidak perlu. Untuk n = 16 = 2 * 2 * 2 * 2 solusi adalah 2 ^ 3 * 3 ^ 1 * 5 ^ 1 = 120, bukan 2 ^ 1 * 3 ^ 1 * 5 ^ 1 * 7 ^ 1 = 210.
randomra

2

C: 66 64 karakter

Solusi yang hampir singkat:

i;f(n){while(n-g(++i));return i;}g(j){return j?!(i%j)+g(j-1):0;}

Dan solusi saya sebelumnya yang tidak berulang:

i;j;k;f(n){while(k-n&&++i)for(k=0,j=1;j<=i;k+=!(i%j++));return i;}

Harus ada solusi yang jauh lebih pendek.


2

Haskell (120C), metode yang sangat efisien

1<>p=[]
x<>p|mod x p>0=x<>(p+1)|1<2=(div x p<>p)++[p]
f k=product[p^(c-1)|(p,c)<-zip[r|r<-[2..k],2>length(r<>2)](k<>2)]

Kode uji:

main=do putStrLn$show$ f (100000::Integer)

Metode ini sangat cepat. Idenya adalah pertama untuk menemukan faktor utama k=p1*p2*...*pm, di mana p1 <= p2 <= ... <= pm. Maka jawabannya adalah n = 2^(pm-1) * 3^(p(m-1)-1) * 5^(p(m-2)-1) ....

Misalnya, memfaktorkan k = 18, kita mendapatkan 18 = 2 * 3 * 3. 3 bilangan prima pertama adalah 2, 3, 5. Jadi jawabannya n = 2 ^ (3-1) * 3 ^ (3-1) * 5 ^ (2-1) = 4 * 9 * 5 = 180

Anda dapat mengujinya di bawah ghci:

*Main> f 18
180
*Main> f 10000000
1740652905587144828469399739530000
*Main> f 1000000000
1302303070391975081724526582139502123033432810000
*Main> f 100000000000
25958180173643524088357042948368704203923121762667635047013610000
*Main> f 10000000000000
6558313786906640112489895663139340360110815128467528032775795115280724604138270000
*Main> f 1000000000000000
7348810968806203597063900192838925279090695601493714327649576583670128003853133061160889908724790000
*Main> f 100000000000000000
71188706857499485011467278407770542735616855123676504522039680180114830719677927305683781590828722891087523475746870000
*Main> f 10000000000000000000
2798178979166951451842528148175504903754628434958803670791683781551387366333345375422961774196997331643554372758635346791935929536819490000
*Main> f 10000000000000000000000
6628041919424064609742258499702994184911680129293140595567200404379028498804621325505764043845346230598649786731543414049417584746693323667614171464476224652223383190000

Itu skor golf yang buruk, tetapi +1 untuk jalur yang telah Anda ambil!
SteeveDroz

Untuk 8 = 2 * 2 * 2 algoritma ini memberikan angka 2 * 3 * 5 = 30. Tetapi solusi terbaik adalah 2 ^ 3 * 3 = 24 (untuk 8 = 2 * 4)
AMK

Solusinya tidak benar jika jumlah pembagi yang ditentukan mengandung daya tinggi prima kecil. Jadi solusi yang paling mungkin terdaftar untuk kekuatan 10 salah.
AMK

@ AMK Ya, Anda benar. Terima kasih telah menunjukkannya.
Ray

2

Brachylog , 2 byte

fl

Cobalah online!

Mengambil input melalui variabel output dan output melalui variabel inputnya.

f     The list of factors of
      the input variable
 l    has length equal to
      the output variable.

Predikat yang sama persis ini, mengambil input melalui variabel inputnya dan mengeluarkan melalui variabel outputnya, menyelesaikan tantangan ini sebagai gantinya .


Bagus, tetapi tidak memenuhi syarat untuk teka-teki itu karena bahasanya lebih baru daripada pertanyaan.
SteeveDroz

Ketika saya masih baru di sini, salah satu hal pertama yang saya diberitahu adalah bahwa bahasa yang lebih baru daripada pertanyaan tidak lagi bersaing, dan ini didukung oleh meta: codegolf.meta.stackexchange.com/questions/12877/…
String

Oh well, lupakan saja. Tampaknya, aturan dibuat untuk berkembang dan kita harus ingat bahwa tujuan utama situs ini adalah untuk meningkatkan diri dan bersenang-senang. Jawaban diterima!
SteeveDroz

1

C, 69 karakter

Bukan yang terpendek, tetapi jawaban C pertama:

f(n,s){return--s?f(n,s)+!(n%s):1;}
x;
g(d){return++x,f(x,x)-d&&g(d),x;}

f(n,s)menghitung pembagi ndalam kisaran tersebut 1..s. Jadi f(n,n)diperhitungkan pembagi n.
g(d)loop (dengan rekursi) hingga f(x,x)==d, lalu mengembalikan x.


1

Mathematica 38 36

(For[k=1,DivisorSigma[0, k]!= #,k++]; k)&

Pemakaian

   (For[k = 1, DivisorSigma[0, k] != #, k++]; k) &[7]

(* 64 *)

Entri pertama (sebelum code-golftag ditambahkan ke pertanyaan.)

Masalah langsung, mengingat bahwa Divisors[n]mengembalikan pembagi n(termasuk n) dan Length[Divisors[n]]mengembalikan jumlah pembagi tersebut. **

smallestNumber[nDivisors_] :=
   Module[{k = 1},
   While[Length[Divisors[k]] != nDivisors, k++];k]

Contohnya

Table[{i, nDivisors[i]}, {i, 1, 20}] // Grid

Grafik Mathematica


David, lebih pendek dan lebih cepat dari Length@Divisors@nitu DivisorSigma[0,n].
Mr.Wizard

Terima kasih. Saya belum tahu tentang penggunaan itu DivisorSigma.
DavidC


1

Jelly , 6 byte (tidak bersaing)

2*RÆdi

Cobalah online! atau verifikasi semua kasus uji .

Bagaimana itu bekerja

2*RÆdi  Main link. Argument: n (integer)

2*      Compute 2**n.
  R     Range; yield [1, ..., 2**n]. Note that 2**(n-1) has n divisors, so this
        range contains the number we are searching for.
   Æd   Divisor count; compute the number of divisors of each integer in the range.
     i  Index; return the first (1-based) index of n.

Mengapa Anda lakukan 2*? Apakah setiap angka setelahnya memiliki lebih banyak pembagi daripada n?
Erik the Outgolfer

2
Tidak; mis., semua bilangan prima memiliki tepat dua pembagi. Namun, kami mencari bilangan bulat positif terkecil dengan n pembagi. Karena 2**(n-1)termasuk dalam rentang itu, yang terkecil juga.
Dennis

0

C ++, 87 karakter

int a(int d){int k=0,r,i;for(;r!=d;k++)for(i=2,r=1;i<=k;i++)if(!(k%i))r++;return k-1;}

0

Python2, 95 karakter, Non-rekursif

Sedikit lebih bertele-tele daripada solusi python lain tetapi tidak bersifat rekursif sehingga tidak mencapai batas rekursi cpython:

from itertools import*
f=lambda n:next(i for i in count()if sum(1>i%(j+1)for j in range(i))==n)

0

Perl 6 , 39 karakter

{my \a=$=0;a++while $_-[+] a X%%1..a;a}

Contoh penggunaan:

say (0..10).map: {my \a=$=0;a++while $_-[+] a X%%1..a;a}
(0 1 2 4 6 16 12 64 24 36 48)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.