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.

SteeveDroz
sumber
2
Apakah ini kode-golf atau kode-tantangan?
marinus
Ups, lupakan tag itu, kode-golf!
SteeveDroz
11
A005179
Peter Taylor

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) .

Howard
sumber
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)
Howard
sumber
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
Nikita Borisov
sumber
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
Bakuriu
sumber
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.

Belisarius
sumber
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
randomra
sumber
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]
shiona
sumber
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
tmartin
sumber
2

APL 33

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

Contoh:

F 6
12           
Graham
sumber
2

APL (25)

{⍵{⍺=+/0=⍵|⍨⍳⍵:⍵⋄⍺∇⍵+1}1}
marinus
sumber
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
plannapus
sumber
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 :)

XzKto
sumber
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.

Untuk S
sumber
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.

Untuk S
sumber
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
sinar
sumber
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 .

String yang tidak terkait
sumber
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.

ugoren
sumber
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

DavidC
sumber
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.
Dennis
sumber
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;}
Cisplatin
sumber
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)
Baptiste M.
sumber
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)
Brad Gilbert b2gills
sumber