N bölücüsü olan en küçük sayıyı ver


17

İşleviniz doğal bir sayı alır ve kendisi de dahil olmak üzere tam olarak bu miktarda bölücü içeren en küçük doğal sayıyı döndürür.

Örnekler:

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

Fonksiyon bölen listesini döndürmek zorunda değildir, sadece örnekler içindir.


2
Bu kod golf mü yoksa kod zorluğu mu?
marinus

Hata! Bu etiketi unuttum, kod golf!
SteeveDroz

Yanıtlar:


6

APL, 25 24 23 karakter

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

fDaha sonra sayıları hesaplamak için kullanılabilecek bir işlev tanımlar :

> f 13
4096

> f 14
192

Çözüm, LCM (n, x) == n iff x'in n'yi böldüğü gerçeğini kullanır . Böylece, blok {+/⍵=⍵∧⍳⍵}basitçe bölen sayısını hesaplar. Bu fonksiyon 1 ile 2 ^ d arasındaki tüm sayılara uygulanır ¨⍳2*⍵. Elde edilen liste daha sonra istenen f (d) işlevi olan d'nin kendisi ( ⍳⍵) için aranır .


Tebrikler! 23 karakter ... vay!
SteeveDroz

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

Tanımlamanız gerektiğini düşünmüyorum f.
Zacharý

5

GolfScript, 29 28 karakter

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

Düzenleme: Bu fikir için Peter Taylor sayesinde aramayı <2 ^ n ile kısıtlarsak, tek bir karakter kaydedilebilir .

Önceki versiyon:

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

GolfScript'te bir deneme, çevrimiçi çalıştırın .

Örnekler:

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

Kod, esasen aşağıdaki satırlarda ayrıntılı olarak açıklanan üç blok içerir.

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

Giriş için sonsuz bir döngüye giriyor gibi görünüyor 1.
Peter Taylor

Şimdiye kadarki en iyi çözümüm , ayrı bir cevaptan ziyade bir yorum olmayı hak ettiğini düşündüğüm ölçüde, sizden oldukça ağır ödünç alıyor.
Peter Taylor

4

Python: 64

Bakuriu'nun çözümünü gözden geçirmek ve grc'nin önerisinin yanı sıra plannapus'un R çözeltisinden gelen hileyi de dahil ederek:

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)

Yukarıdaki, RuntimeError: maximum recursion depth exceededCPython'da küçük girdilerle bir artıracak ve sınırı çok büyük bir sayıya bile ayarlayabilmek, muhtemelen bazı sorunlar verecektir. Kuyruk özyinelemesini optimize eden python uygulamalarında iyi çalışmalıdır.

Bu tür sınırlamalara sahip olmaması gereken daha ayrıntılı bir sürüm, aşağıdaki 79 bayt çözümüdür:

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

11, 13, 17, 19 ve diğerlerinde özyineleme sınırına ulaşıyorum.
Steven Rumbalski

@StevenRumbalski Kimse, programın keyfi tamsayılarla çalışması gerektiğini söylemedi. Ne yazık ki, rakamlar küçük girdilerle bile oldukça hızlı büyüyor.
Bakuriu

Sen değiştirerek kullanarak bazı karakter kaydedebilirsiniz if elseile and orve ==1ile <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

66 ufak bir şeytani bulduğum için, kullanırsanız 2 karakter kaydedebilirsinizsum(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)7 bayt kaydeder.
Dennis

4

Mathematica 38 36

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

Kullanımı:

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

Sonuç:

498960

Düzenle

Bazı açıklamalar:

DivisorSum [n, form], n'yi bölen tüm i için form [i] 'nin toplamını temsil eder.

Gibi form[i]ben işlevini kullanıyorum 1 &döner hep, 1bu yüzden etkili veciz şekilde bölenler toplamını hesaplama.


Hiçbir kod golf etiketi vardı, bu yüzden uzun bir cevap verdi! ayy
DavidC

@DavidCarraher Az önce tahmin ettim :)
Dr. belisarius

Neyin DivisorSumgeri döndüğünü bildiğimi sanıyordum (bölenlerin toplamı) ama bunun soruyu cevaplamak için nasıl etkili olduğunu görmüyorum. Nasıl çalıştığını açıklar mısın? BTW, n = 200 için zamanlama verisi eklemeniz gerektiğini düşünüyorum; kontrol etmesi gereken tüm sayılar göz önüne alındığında, fonksiyon oldukça hızlıdır.
DavidC

@DavidCarraher Bkz. Düzenleme. Re: zamanlamaları - Benim makine yol çok yavaş :(
Dr. belisarius

Mathematica'nın, faktoring konusundaki daha sofistike yaklaşımın daha kısa olması için yeterli yapısı yok mu? Eğer durum buysa, hayal kırıklığına uğradım.
Peter Taylor

3

J, 33 karakter

Oldukça hızlı, tüm küçük sayılardan geçer ve çarpanlara ayırma temelinde bölen sayısını hesaplar.

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

   f 19
262144

3

Haskell 54

Hızlı ve kirli (çok okunaklı ve zor olmayan) çözüm:

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

Düzenleme, cevabı daha kısa yapmadı, ancak belki daha fazla haskell benzeri. Ayrıca her zaman benim kod uzunluğu için son satır dahil, bu yanlış mı?
shiona

Yanlış saydığınızı sanıyordum; düzenlemenin temel amacı sayımı güncellemekti. Koddaki değişiklik küçüktü. Sanırım buradaki diğer girişler de, örneğin J (33 karakter) girişi gibi sondaki yeni satırı saymıyor.
Ness Ness

2

K, 42

Yığını kolayca havaya uçuran verimsiz özyinelemeli çözüm

{{$[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 

Misal:

F 6
12           

2

APL (25)

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

Dolandırıcı! echo -n '{⍵ {⍺ = + / 0 = ⍵ | ⍨⍳⍵: ⍵⋄⍺∇⍵ + 1} 1}' | wc -c bana 47 veriyor! Ama gerçekten, lütfen bana APL için kolay bir öğreticiye bir bağlantı verebilir misiniz? Ben google denedim ve birkaç makale okudum, ama yine de sonunda her zaman "Neden bunu yapıyorlar :(?" Sormak istiyorum. ASCII olmayan bir sözdizimi dili ile hiç çalışmadım ve eğer herhangi bir gerçek avantajı var
XzKto

Bu, kullandığım Dyalog APL için, Windows sürümünü aynı sitede ücretsiz olarak indirebilirsiniz. dyalog.com/MasteringDyalogAPL/MasteringDyalogAPL.pdf
marinus

Vay canına, bunu gerçekten anlayabiliyorum gibi görünüyor. Bağlantı için teşekkürler! Tek dezavantajı, bazı çok garip lisans politikası var ama belki sadece benim İngilizce geliştirmek gerekir)
XzKto

2

R - 47 karakter

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

!n%%1:nbooleans vektörü verir: 1'den n'ye bir tamsayı n'nin bölücüsü olduğunda DOĞRU ve değilse YANLIŞ. sum(!n%%1:n)eğer YANLIŞ ise booleans'ı 0 ve TRUE ise 1'e zorlar ve toplar, böyleceN-sum(...) is 0 when number of divisors is N. 0 is then interpreted as FALSE by while which then stops.

Kullanımı:

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}

Gerçekten sadece 46 anlamlı karakter var:

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

Muhtemelen daha kısa sözdizimi olan bir dil öğrenmeliyim :)


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 characters

It could be seen as an improvement of the earlier Haskell solution, but it was conceived in its own right (warning: it's very slow):

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

It's quite an interesting function, for example note that f(p) = 2^(p-1), where p is a prime number.


The efficient, as opposed to short, way to calculate it would be to factor n into primes (with repetition), sort descending, decrement each one, zip with an infinite sequence of primes, and then fold the product of p^(factor-1)
Peter Taylor

2
@PeterTaylor Not necessary. For n=16=2*2*2*2 solution is 2^3*3^1*5^1=120, not 2^1*3^1*5^1*7^1=210.
randomra

2

C: 66 64 characters

An almost short solution:

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

And my previous solution that doesn't recurse:

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

Much shorter solutions must exist.


2

Haskell (120C), çok verimli bir yöntem

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

Test kodu:

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

Bu yöntem çok hızlı. Fikir ilk olarak k=p1*p2*...*pm, p1 <= p2 <= ... <= pm'nin ana faktörlerini bulmaktır . O zaman cevap n = 2^(pm-1) * 3^(p(m-1)-1) * 5^(p(m-2)-1) ....

Örneğin, k = 18 çarpanlarına ayrılırken 18 = 2 * 3 * 3 elde edilir. İlk 3 asal 2, 3, 5'tir. Yani n = 2 ^ (3-1) * 3 ^ (3-1) * cevabı 5 ^ (2-1) = 4 * 9 * 5 = 180

Aşağıdakileri test edebilirsiniz 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

Bu kötü bir golf skoru, ancak aldığınız yol için +1!
SteeveDroz

8 = 2 * 2 * 2 için bu algoritma 2 * 3 * 5 = 30 sayısını verir. Ancak en iyi çözüm 2 ^ 3 * 3 = 24'tür (8 = 2 * 4 için)
AMK

Belirtilen sayıda bölen yüksek miktarda küçük asal güç içeriyorsa çözüm yanlıştır. Bu nedenle, 10 güç için büyük olasılıkla listelenmiş çözümler yanlıştır.
AMK

@ AMK Evet, haklısın. Bunu işaret ettiğiniz için teşekkürler.
Ray

2

Brachylog , 2 bayt

fl

Çevrimiçi deneyin!

Girdi çıktı değişkeninden alır ve girdi değişkeninden çıktı alır.

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

This exact same predicate, taking input through its input variable and outputting through its output variable, solves this challenge instead.


Nice, but not eligible for that puzzle as the language is more recent than the question.
SteeveDroz

When I was new here one of the first things I was told was that languages newer than questions aren't noncompeting anymore, and this is backed up by meta: codegolf.meta.stackexchange.com/questions/12877/…
Unrelated String

Oh well, nevermind then. Apparently, rules are made to evolve and we must keep in mind that this site main purpose is to improve ourselves and have fun. Answer accepted!
SteeveDroz

1

C, 69 chars

Not the shortest, but the first C answer:

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) counts divisors of n in the range 1..s. So f(n,n) counts divisors of n.
g(d) loops (by recursion) until f(x,x)==d, then returns x.


1

Mathematica 38 36

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

Usage

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

(* 64 *)

First entry (before the code-golf tag was added to the question.)

A straightforward problem, given that Divisors[n] returns the divisors of n (including n) and Length[Divisors[n]] returns the number of such divisors.**

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

Examples

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

Mathematica graphics


David, shorter and faster than Length@Divisors@n is DivisorSigma[0,n].
Mr.Wizard

Thanks. I hadn't known about that use of DivisorSigma.
DavidC


1

Jelly, 6 bytes (non-competing)

2*RÆdi

Try it online! or verify all test cases.

How it works

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.

Why do you do 2*? Is it that every number after that has more divisors than n?
Erik the Outgolfer

2
No; e.g., all primes have exactly two divisors. However, we are searching for the smallest positive integer with n divisors. Since 2**(n-1) belongs to that range, the smallest one does as well.
Dennis

0

C++, 87 characters

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 characters, Non-recursive

A bit more verbose than the other python solutions but it's non-recursive so it doesn't hit cpython's recursion limit:

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 chars

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

Example usage:

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.