Pseudofaktoriell


39

Es gibt eine ziemlich merkwürdige Zahl, die manchmal in mathematischen Problemen oder Rätseln auftaucht. Das Pseudofaktorielle (N) ist das kleinste (dh niedrigste) gemeinsame Vielfache der Zahlen 1 bis N; Mit anderen Worten, es ist die niedrigste Zahl, die alle Zahlen von 1 bis N als Faktoren hat.

Zum Beispiel pseudofaktoriell (7) = 3 * 4 * 5 * 7, das ist das Gleiche wie 7! mit der Ausnahme, dass 2 und 6 entfernt wurden, weil sie in anderen Begriffen enthalten sind.

Schreiben Sie ein Programm zur Berechnung von Pseudofaktoren (N), und wie immer gewinnt der kürzeste Code.

Hier ist eine kurze Liste für Ihre Verwendung. Weitere Testfälle finden Sie im OEIS unter A003418 .

Fakultät:

  1. 1
  2. 2
  3. 6
  4. 24
  5. 120
  6. 720
  7. 5040

Pseudofaktoriell:

  1. 1
  2. 2
  3. 6
  4. 12
  5. 60
  6. 60
  7. 420

6
Ich bin mir nicht sicher, warum ich das verstehe 2und 6von der Liste der Vielfachen gestrichen wurde. Können Sie bitte die Regeln klären?
Maltysen

2
@Mattysen, psuedofactorial (N) ist die kleinste Zahl mit den Zahlen 1 bis N als Faktoren (das am wenigsten verbreitete Vielfache dieser Zahlen). Das ist die technische Definition, aber die Art und Weise, wie ich es geschrieben habe, deutet darauf hin, dass es einer Fakultät ähnlich ist.
Tony Ruth


4
Willkommen bei Programming Puzzles & Code Golf! Dies ist eine schöne erste Herausforderung!
Alex A.

1
Deine erste Herausforderung hat die Spitze von HNQ erreicht. Nett!
Daniel M.

Antworten:




8

C (mit x86), 52 Bytes

d(n,k,b,t){for(b=k=1;b;++k)for(t=n,b=0;t;b+=k%t--);}

Prüft Zahlen von 1 aufwärts. Dividiert es für jede Zahl durch alle Zahlen von n bis 1 und summiert die verbleibenden Zahlen. Stoppt, wenn die Summe 0 ist.

Verwendungszweck:

main()
{
    printf("%d\n", d(7)); // outputs 420
}

Es ist nicht offensichtlich, wie ein Wert zurückgegeben wird (es gibt keine returnAnweisung).

Die Aufrufkonvention für x86 besagt, dass die Funktion ihren Wert im eaxRegister zurückgeben muss. Praktischerweise idiverwartet der Divisionsbefehl seine Eingabe in eaxund gibt das Ergebnis in eax(Quotient) und edx(Rest) aus. Die letzte Iteration dividieren kdurch 1, so eaxenthält den richtigen Wert , wenn die Funktion beendet.

Dies funktioniert nur, wenn Optimierungen aktiviert sind (im Debug-Modus werden diese ausgegeben 421).


Wie kommt man durch, wenn man den Typ von n, k, b und t nicht deklariert?
Tony Ruth

C hat die Standard-Int-Regel - alle ausgelassenen Typen sind intstandardmäßig (einschließlich des Rückgabewerts). Es funktioniert für Funktionsargumente, wenn sie mit der sogenannten "old-style" -Syntax deklariert werden. Die Deklaration mit explizit definierten Typen wäreint d(n,k,b,t) int n,k,b,t; {...}
anatolyg

Wenn Sie eine Aufrufkonvention nutzen, sollte diese wirklich mit "C (cdecl)" und nicht nur mit "C" gekennzeichnet sein
Steve Cox

@SteveCox Beide cdeclund stdcallverwenden die gleiche Methode für den Rückgabewert, also x86ist es
wahrscheinlich

7

Haskell, 20 Bytes

f x=foldr1 lcm[1..x]

Anwendungsbeispiel: map f [1..7]-> [1,2,6,12,60,60,420].

Der lcmTrick in Haskell.


6

Python + SymPy, 45 Byte

import sympy
lambda n:sympy.lcm(range(1,n+1))

Ziemlich selbsterklärend.


Python 2, 57 54 Bytes

i=r=input();exec't=r\nwhile r%i:r+=t\ni-=1;'*r;print r

Teste es auf Ideone .

Wie es funktioniert

Die Eingabe wird in den Variablen i und r gespeichert .

execFührt den folgenden Code r- mal aus.

t=r
while r%i:r+=t
i-=1

Während i von r bis 1 variiert , addieren wir den Anfangswert von r (in t gespeichert ) so oft wie nötig, um selbst ein Vielfaches von i zu erzeugen . Das Ergebnis ist offensichtlich ein Vielfaches von t .

Der Endwert von r ist also ein Vielfaches aller ganzen Zahlen im Bereich [1, ..., n] , wobei n die Eingabe ist.


1
Ohne Bibliotheken oder execTricks von Drittanbietern gibt es eine 78-Byte-Lösung: from fractions import*;lambda n:reduce(lambda x,y:x*y/gcd(x,y),range(1,n+1),1) Nutzt die Tatsache, dass lcm(x,y) = x*y/gcd(x,y).
Bakuriu

6

Python, 46 Bytes

g=lambda n,c=0:n<1or(c%n<1)*c or g(n,c+g(n-1))

Auf der Suche nach dem Vielfachen cvon g(n-1)direkt. Ich hatte zwar vorher, dass diese Methode fälschlicherweise 0 als ein Vielfaches von irgendetwas finden würde, aber das orKurzschließen oder (c%n<1)*cwird auch überspringen, c==0weil 0 falsch ist.


50 Bytes:

g=lambda n,i=1:n<1or(i*n%g(n-1)<1)*i*n or g(n,i+1)

Wie Dennis 'Lösung , aber als rekursive Funktion. Nach der Berechnung g(n-1)wird nach dem kleinsten Vielfachen i*ngesucht n, das auch ein Vielfaches von ist g(n-1). Wirklich langsam.

Dank Dennis 4 Bytes um ein Vielfaches von der Suche nstatt g(n-1).


5

J 9 Bytes

[:*./1+i.

Unkomplizierter Ansatz. Erstellt den Zahlenbereich [0, ..., n-1], fügt dann jeweils einen hinzu und reduziert ihn mithilfe des LCM.

Verwendungszweck

   f =: [:*./1+i.
   f 7
420


4

Mathematica, 13 Bytes

LCM@@Range@#&

ist das nicht gleichbedeutend mit komponieren LCMund Rangemit @*?
Maltysen

1
LCMarbeitet elementweise mit einer Liste, die übergeben werden würde Range, was bedeutet, dass dies nur die lcm ( x ) für x von 1 bis n zurückgibt . Außerdem fehlt eine &Funktion, die die anonyme Funktion schließen würde. So etwas wie LCM@@Range@#&für 13 Bytes würde funktionieren.
Meilen



3

Oktave, 27 Bytes

@(x)lcm(1,num2cell(1:x){:})

Erstellt eine anonyme Funktion, die als aufgerufen werden kann ans(N).

Online Demo

Erläuterung

Diese Lösung erstellt eine Liste aller Zahlen zwischen 1und x( 1:x), konvertiert sie in ein Zellenfeld mit num2cell. Die {:}Indizierung erstellt dann eine durch Kommas getrennte Liste, die lcmals mehrere Eingabeargumente übergeben wird, um das am wenigsten verbreitete Vielfache zu berechnen. Eine 1 wird immer als erstes Argument an übergeben, lcmda lcmimmer mindestens zwei Eingabeargumente benötigt werden.


1
Also lcmin Octave akzeptiert mehr als 2 Eingänge! Interessant
Luis Mendo


3

MATLAB, 49 Bytes

@(x)find(~any(bsxfun(@rem,1:prod(1:x),(1:x)')),1)

+1 fürbsxfun
flawr

3

Perl 6 , 13 Bytes

{[lcm] 1..$_}

Anonymer Codeblock, der einen Bereich von 1 bis zur Eingabe (einschließlich) erstellt und diesen dann mit reduziert &infix:<lcm>.

Beispiel:

#! /usr/bin/env perl6
use v6.c;

my &postfix:<p!> = {[lcm] 1..$_}

say 1p!; # 1
say 2p!; # 2
say 3p!; # 6
say 4p!; # 12
say 5p!; # 60
say 6p!; # 60
say 7p!; # 420

say 10000p!; # 5793339670287642968692270879...
# the result from this is 4349 digits long


2

JavaScript (ES6), 92 88 80 74 69 Byte:

Danke @ConorOBrien und @Neil

y=>(g=(a,b)=>b?g(b,a%b):a,[...Array(y)].map((_,i)=>y=y*++i/g(y,i)),y)

b?g(b,a%b):aSpeichert ein Byte.
Neil

y*++i/g(y,i)spart etwas mehr Bytes.
Neil

1

05AB1E, 20 Bytes

Lpvyi¹LÒN>¢àN>*ˆ}}¯P

Erläuterung

Lpv                    # for each item in isprime(range(1,N)): N=7 -> [0,1,1,0,1,0,1]
   yi                  # if prime
     ¹LÒN>¢            # count occurrences of the prime 
                         in the prime-factorization of range(1,N):
                         p=2 -> [0,1,0,2,0,1,0]
           àN>*ˆ       # add max occurrence of that prime multiplied by the prime 
                         to global array: N=7 -> [4,3,5,7]
                }}     # end if/loop
                  ¯P   # get product of global array

Probieren Sie es online aus


1

Minkolang 0,15 , 12 Bytes

Ich habe zwei 12-Byte-Lösungen und habe sie beide enthalten.

1n[i1+4$M]N.

Probieren Sie es hier aus!

Erläuterung

1               Push 1
 n              Take number from input
  [             For loop that repeats n times
   i1+          Push loop counter + 1
      4$M       Pop b, a and push lcm(a,b)
         ]      Close for loop
          N.    Output as number and stop.

Ungefähr so ​​einfach wie es nur geht.


11nLd[4$M]N.

Probieren Sie es hier aus!

Erläuterung

11              Push two 1s
  n             Take number from input
   L            Pop b, a and push range from a to b, inclusive
    d           Duplicate top of stack (n)
     [4$M]      Pop b, a and push lcm(a,b), n times
          N.    Output as number and stop.

Daraus lässt sich eine dritte Lösung ableiten: a entfernen 1und a dnach dem Strom hinzufügen d. In beiden Fällen wird die zusätzliche Nummer benötigt, da die for-Schleife ein Mal zu oft ausgeführt wird und das einmalige Ausführen zwei Bytes ( 1-kurz vor der [) dauert .


1

Ruby, 25 Bytes

g=->n{(1..n).reduce :lcm}

Ruby, 25 Bytes

g=->n{n<1?1:a[n-1].lcm n}

1
Hallo und willkommen bei PPCG! Toller erster Beitrag! Sie müssen Ihre Funktion nicht benennen, damit Sie sie entfernen können g=.
NoOneIsHere

Anonyme Funktionen sind erlaubt.
Erik der Outgolfer

1

GameMaker-Sprache, 60 Byte

for(b=k=1;b;++k){b=0for(t=argument0;t;b+=k mod t--)}return k

Basierend auf der Logik von Anatolygs Antwort.


1

PHP, 61 52 48 Bytes

sparte 9 Bytes dank @ user59178, 4 Bytes durch Zusammenführen der Schleifen.

Rekursion in PHP ist aufgrund des functionSchlüsselworts umfangreich; Also benutze ich Iteration.
Und mit ein paar "kleinen" Tricks habe ich jetzt sogar Arnauld´s JS geschlagen .

while(++$k%++$i?$i>$argv[1]?0:$i=1:$k--);echo$k;

Nimmt Eingaben vom Kommandozeilenargument entgegen. Laufen Sie mit -r.

Nervenzusammenbruch

while(++$k%++$i?    # loop $i up; if it does not divide $k
    $i>$argv[1]?0       # break if $i (smallest non-divisor of $k) is larger than input
    :$i=1               # while not, reset $i and continue loop with incremented $k
    :$k--);         # undo increment while $i divides $k
echo$k;         # print $k

ungolfed

Das sind eigentlich zwei Loops in einem:

while($i<=$argv[1]) # loop while $i (smallest non-divisor of $k) is not larger than input
    for($k++,       # loop $k up from 1
        $i=0;$k%++$i<1;);   # loop $i up from 1 while it divides $k
echo$k;             # print $k

Hinweis: Von meiner Antwort auf das Duplikat kopiert


1

AWK, 42 Bytes

{for(x=n=1;n<=$1;)if(x%n++){x++;n=1}$0=x}1

Befehlszeilenverwendung:

awk '{for(x=n=2;n<=$1;)if(x%n++){x++;n=2}$0=x}1' <<< NUM

Ich habe AWKgestern keine Lösung und kein Duplikat der Frage gesehen, also dachte ich, ich würde das zusammenwerfen. Es ist ziemlich langsam für 19meine Box oder größer zu lösen , aber es funktioniert.




0

Hoon , 67 Bytes

|*
*
(roll (gulf 1 +<) |=({a/@ b/_1} (div (mul a b) d:(egcd a b))))

Erstellen Sie die Liste [1..n], falten Sie die Liste mit lcm. Leider gibt es in der Hoon-Stdlib keine vorgefertigte, die ich verwenden kann: /



0

QBIC , 35 32 Bytes

Das hat mich hierher gebracht.

:{p=0[a|~q%b|p=1]]~p=0|_Xq\q=q+1

Erläuterung:

:        Get cmd line param as number 'a'
{        Start an infinite DO loop
p=0      Sets a flag that shows if divisions failed
[a|      FOR (b=1; b<=a; b++)
~q%b     IF 'q' (which starts at 1 in QBIC) is not cleanly divisible by 'b'
|p=1     THEN Set the flag
]]   Close the FOR loop and the IF, leave the DO open
~p=0     IF 'q' didn't get flagged
|_Xq     THEN quit, printing 'q'
\q=q+1   ELSE raise 'q', redo
         [DO Loop implicitly closed by QBIC]

Hier ist eine Version, die den Test beendet, qwenn bsie nicht sauber aufgeteilt wird. Auch die Reihenfolge der Prüfung bist gegen qin der Annahme , umgekehrt , dass höhere b's zu teilen sein wird härter durch (nehmen 2, 3, 4zum Beispiel: wenn %2=0, %4könnte sein !0. Umgekehrt nicht so sehr ...).

:{p=0[a,2,-1|~q%b|p=1┘b=2]]~p=0|_Xq\q=q+1



0

8. 23 Bytes

Code

1 ' lcm rot 2 swap loop

Dieser Code belässt das resultierende Pseudofaktorielle im TOS

Verwendung und Beispiel

ok> 7 1 ' lcm rot 2 swap loop .
420

Oder klarer

ok> : pseudofact 1 ' n:lcm rot 2 swap loop ;

ok> 7 pseudofact .
420
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.