Geben Sie die kleinste Zahl mit N Teilern an

17

Ihre Funktion nimmt eine natürliche Zahl und gibt die kleinste natürliche Zahl zurück, die genau so viele Teiler enthält, einschließlich sich selbst.

Beispiele:

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

Die Funktion muss nicht die Liste der Teiler zurückgeben, sie sind nur für die Beispiele hier.

SteeveDroz
quelle
2
Ist das Code-Golf oder Code-Herausforderung?
marinus
Hoppla, vergessen Sie diesen Tag, Code-Golf!
SteeveDroz
11
A005179
Peter Taylor

Antworten:

6

APL, 25 24 23 Zeichen

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

Definiert eine Funktion f, mit der die Zahlen berechnet werden können:

> f 13
4096

> f 14
192

Die Lösung nutzt die Tatsache, dass LCM (n, x) == n, wenn x n teilt . Der Block {+/⍵=⍵∧⍳⍵}berechnet also einfach die Anzahl der Teiler. Diese Funktion gilt für alle Zahlen von 1 bis 2 ^ d ¨⍳2*⍵ . Die resultierende Liste wird dann nach d selbst ( ⍳⍵) durchsucht, was die gewünschte Funktion f (d) ist .

Howard
quelle
Glückwunsch! 23 Zeichen ... wow!
SteeveDroz
19:{⍵⍳⍨(+/⊢=⊢∧⍳)¨⍳2*⍵}
Adám
Ich glaube nicht, dass Sie definieren müssen f.
Zacharý
5

GolfScript, 29 28 Zeichen

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

Bearbeiten: Ein einzelnes Zeichen kann gespeichert werden, wenn wir die Suche auf <2 ^ n beschränken. Dank an Peter Taylor für diese Idee.

Vorherige Version:

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

Ein Versuch in GolfScript, online auszuführen .

Beispiele:

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

Der Code enthält im Wesentlichen drei Blöcke, die in den folgenden Zeilen ausführlich erläutert werden.

# 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
quelle
Scheint für die Eingabe in eine Endlosschleife zu gehen 1.
Peter Taylor
Meine bisher beste Lösung leiht sich ziemlich stark bei Ihnen aus, insofern ich denke, dass es eher einen Kommentar als eine separate Antwort verdient.
Peter Taylor
4

Python: 64

Wenn wir Bakurius Lösung überarbeiten und den Vorschlag von grc sowie den Trick aus der R-Lösung von plannapus einbeziehen, erhalten wir:

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

Das obige löst RuntimeError: maximum recursion depth exceededbei kleinen Eingaben in CPython einen aus, und selbst das Festlegen des Grenzwerts auf eine große Anzahl wird wahrscheinlich einige Probleme verursachen. Bei Python-Implementierungen, die die Schwanzrekursion optimieren, sollte dies problemlos funktionieren.

Eine ausführlichere Version, die keine solchen Einschränkungen haben sollte, ist die folgende 79- Byte-Lösung:

def f(n,k=1):
    while 1:
        if sum(k%i<1for i in range(1,k+1))==n:return k
        k+=1
Bakuriu
quelle
Ich überschreite die Rekursionsgrenze für 11, 13, 17, 19 und andere.
Steven Rumbalski
@StevenRumbalski Niemand hat erwähnt, dass das Programm mit beliebigen ganzen Zahlen arbeiten soll. Leider wachsen die Zahlen auch bei kleinen Eingaben recht schnell.
Bakuriu
Sie können einige Zeichen speichern , indem Sie ersetzen if elsemit and orund ==1mit <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
Da ich 66 ein wenig zu böse finde, können Sie 2 Zeichen speichern, wenn Sie verwendensum(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)spart 7 Bytes.
Dennis
4

Mathematica 38 36

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

Verwendung:

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

Ergebnis:

498960

Bearbeiten

Einige Erklärungen:

DivisorSum [n, form] repräsentiert die Summe der Form [i] für alle i, die n teilen.

Da form[i]ich die Funktion verwende 1 &, kehrt diese immer zurück 1und berechnet die Summe der Teiler auf eine knappe Art und Weise.

Dr. belisarius
quelle
Es gab kein Code-Golf-Tag, also gab ich eine lange Antwort! oops
DavidC
@ DavidCarraher Ich habe gerade erraten :)
Dr. Belisarius
Ich dachte, ich wüsste, was DivisorSumzurückkommt (die Summe der Teiler), aber ich sehe nicht, wie dies für die Beantwortung der gestellten Frage von Bedeutung ist. Würden Sie erklären, wie es funktioniert? BTW, ich denke, Sie sollten Timing-Daten für n = 200 einschließen; Die Funktion ist bemerkenswert schnell, wenn man alle Zahlen berücksichtigt, die überprüft werden mussten.
DavidC
@ DavidCarraher Siehe Bearbeiten. Re: Timings - Meine Maschine ist viel zu langsam :(
Dr. Belisarius
Verfügt Mathematica nicht über genügend integrierte Funktionen, um den differenzierteren Ansatz des Factorings zu verkürzen? Wenn das der Fall ist, bin ich enttäuscht.
Peter Taylor
3

J, 33 Zeichen

Ziemlich schnell, durchläuft alle kleineren Zahlen und berechnet die Anzahl der Teiler basierend auf der Faktorisierung.

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

   f 19
262144
randomra
quelle
3

Haskell 54

Schnelle und schmutzige (also lesbare und nicht schwierige) Lösung:

f k=head[x|x<-[k..],length[y|y<-[1..x],mod x y==0]==k]
Shiona
quelle
Die Bearbeitung hat die Antwort nicht kürzer gemacht, aber vielleicht ist sie haskellartiger. Außerdem habe ich die nachgestellte Newline immer in meine Codelänge eingefügt. Ist das falsch?
Shiona
Ich dachte, Sie haben falsch gezählt. Der Hauptzweck für die Bearbeitung war die Aktualisierung der Zählung. Die Änderung im Code selbst war geringfügig. Ich denke, die anderen Einträge hier zählen auch nicht den abschließenden Zeilenumbruch, wie zB der Eintrag für J (33 Zeichen).
Will Ness
2

K, 42

Ineffiziente rekursive Lösung, die den Stapel leicht in die Luft jagt

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

APL 33

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

Beispiel:

F 6
12           
Graham
quelle
2

APL (25)

{⍵{⍺=+/0=⍵|⍨⍳⍵:⍵⋄⍺∇⍵+1}1}
Marinus
quelle
Betrüger! echo -n '{⍵ {⍺ = + / 0 = ⍵ | ⍨⍳⍵: ⍵⋄⍺∇⍵ + 1} 1}' | wc -c gibt mir 47! Aber können Sie mir bitte einen Link zu einem einfachen Tutorial für APL geben? Ich habe versucht, es zu googeln und habe ein paar Artikel gelesen, aber am Ende möchte ich immer noch fragen: "Warum machen sie das?". Ich habe noch nie mit einer anderen Sprache als ASCII-Syntax gearbeitet und wollte herausfinden, ob Es hat jeden wirklichen Vorteil.
XzKto
Dies ist für Dyalog APL, was ich verwende. Sie können die Windows-Version kostenlos auf derselben Site herunterladen. dyalog.com/MasteringDyalogAPL/MasteringDyalogAPL.pdf
marinus
Wow, sieht so aus, als könnte ich das wirklich verstehen. Danke für den Link! Der einzige Nachteil ist, dass sie einige sehr seltsame Lizenzierungsrichtlinien haben, aber vielleicht muss ich nur mein Englisch verbessern)
XzKto
2

R - 47 Zeichen

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

!n%%1:nergibt einen Vektor von Booleschen Werten: TRUE, wenn eine Ganzzahl von 1 bis n ein Teiler von n ist, andernfalls FALSE. sum(!n%%1:n)Erzwingt boolesche Werte zu 0, wenn FALSE und 1, wenn TRUE und summiert sie, so dass N-sum(...)0 ist, wenn die Anzahl der Teiler N ist. 0 wird dann als FALSE interpretiert, whilewodurch dann aufhört.

Verwendung:

f(6)
[1] 12
f(13)
[1] 4096
Plannapus
quelle
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}

Wirklich gibt es nur 46 sinnvolle Zeichen:

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

Ich sollte wahrscheinlich eine Sprache mit kürzerer Syntax lernen :)

XzKto
quelle
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 buchstaben

Es könnte als Verbesserung der früheren Haskell-Lösung angesehen werden, wurde jedoch eigenständig konzipiert (Warnung: Es ist sehr langsam):

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

Es ist eine interessante Funktion, zum Beispiel, dass f (p) = 2 ^ (p-1) ist, wobei p eine Primzahl ist.

Fors
quelle
Die effiziente, im Gegensatz zu der kurzen, Methode zur Berechnung besteht darin, nPrimzahlen (mit Wiederholung) zu zerlegen, absteigend zu sortieren, jede einzelne zu dekrementieren, mit einer unendlichen Folge von Primzahlen zu zipen und dann das Produkt vonp^(factor-1)
Peter Taylor
2
@ PeterTaylor Nicht erforderlich. Für n = 16 = 2 · 2 · 2 · 2 ist die Lösung 2 · 3 · 3 · 1 · 5 · 1 = 120, nicht 2 · 1 · 3 · 1 · 5 · 1 · 7 · 1 = 210.
Randomra
2

C: 66 64 Zeichen

Eine fast kurze Lösung:

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

Und meine bisherige Lösung, die nicht wiederkehrt:

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

Es müssen viel kürzere Lösungen existieren.

Fors
quelle
2

Haskell (120C), eine sehr effiziente Methode

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

Testcode:

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

Diese Methode ist sehr schnell. Die Idee ist zunächst, die Primfaktoren von zu finden k=p1*p2*...*pm, wobei p1 <= p2 <= ... <= pm. Dann lautet die Antwort n = 2^(pm-1) * 3^(p(m-1)-1) * 5^(p(m-2)-1) ....

Wenn wir zum Beispiel k = 18 faktorisieren, erhalten wir 18 = 2 * 3 * 3. Die ersten 3 Primzahlen sind 2, 3, 5. Also ist die Antwort n = 2 ^ (3-1) * 3 ^ (3-1) * 5 ^ (2-1) = 4 * 9 * 5 = 180

Sie können es testen unter 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
Strahl
quelle
Das ist eine schlechte Punktzahl, aber +1 für den Weg, den Sie genommen haben!
SteeveDroz
Für 8 = 2 * 2 * 2 gibt dieser Algorithmus die Zahl 2 * 3 * 5 = 30 an. Aber die beste Lösung ist 2 ^ 3 * 3 = 24 (für 8 = 2 * 4)
AMK
Die Lösung ist falsch, wenn die angegebene Anzahl von Teilern eine hohe Potenz kleiner Primzahlen enthält. Die wahrscheinlichsten Lösungen für Potenzen von 10 sind also falsch.
AMK
@ AMK Ja, du hast recht. Vielen Dank für den Hinweis.
Ray
2

Brachylog , 2 Bytes

fl

Probieren Sie es online!

Übernimmt die Eingabe über die Ausgabevariable und gibt sie über die Eingabevariable aus.

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

Dieses exakt gleiche Prädikat, das Eingaben über seine Eingabevariable und Ausgaben über seine Ausgabevariable nimmt, löst stattdessen diese Herausforderung .

Nicht verwandte Zeichenfolge
quelle
Nett, aber für dieses Rätsel nicht geeignet, da die Sprache aktueller ist als die Frage.
SteeveDroz
Als ich hier neu war, wurde mir als erstes gesagt, dass Sprachen, die neuer als Fragen sind, nicht mehr konkurrieren.
String
Na gut, dann vergiss es. Anscheinend werden Regeln entwickelt, und wir müssen bedenken, dass es das Hauptziel dieser Website ist, uns selbst zu verbessern und Spaß zu haben. Antwort akzeptiert!
SteeveDroz
1

C 69 Zeichen

Nicht die kürzeste, sondern die erste C-Antwort:

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)zählt Teiler nim Bereich 1..s. So f(n,n)zählt Teiler n.
g(d)Schleifen (durch Rekursion) bis f(x,x)==d, dann wird x zurückgegeben.

ugoren
quelle
1

Mathematica 38 36

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

Verwendung

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

(* 64 *)

Erster Eintrag (vor dem code-golfHinzufügen des Tags zur Frage)

Ein einfaches Problem, da Divisors[n]die Teiler von n(einschließlich n) und Length[Divisors[n]]die Anzahl solcher Teiler zurückgegeben werden. **

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

Beispiele

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

Mathematica-Grafiken

DavidC
quelle
David, kürzer und schneller als er Length@Divisors@nist DivisorSigma[0,n].
Mr.Wizard
Vielen Dank. Ich hatte nicht über diese Verwendung von gewusst DivisorSigma.
DavidC
1

Gelee , 6 Bytes (nicht konkurrierend)

2*RÆdi

Probieren Sie es online! oder überprüfen Sie alle Testfälle .

Wie es funktioniert

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
quelle
Warum tust du das 2*? Hat jede Zahl danach mehr Teiler als n?
Erik der Outgolfer
2
Nein; zB haben alle Primzahlen genau zwei Teiler. Wir suchen jedoch nach der kleinsten positiven Ganzzahl mit n Teilern. Da 2**(n-1)zu diesem Bereich gehört, tut dies auch der kleinste.
Dennis
0

C ++, 87 Zeichen

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
quelle
0

Python2, 95 Zeichen, nicht rekursiv

Ein bisschen ausführlicher als die anderen Python-Lösungen, aber nicht rekursiv, sodass das Rekursionslimit von cpython nicht überschritten wird:

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.
quelle
0

Perl 6 , 39 Zeichen

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

Anwendungsbeispiel:

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
quelle