Ist diese Zahl eine Fakultät?


38

Die Aufgabe

Bei einer natürlichen Zahl als Eingabe müssen Sie einen Wahrheits- oder Falschwert ausgeben, der davon abhängt, ob die Eingabe eine Fakultät einer natürlichen Zahl ist. Sie können davon ausgehen, dass die eingegebene Nummer immer in dem von Ihrer Sprache unterstützten Zahlenbereich liegt, aber Sie dürfen native Nummerntypen nicht missbrauchen, um das Problem zu trivialisieren .

Es gelten Standard-Regelungslücken .


Eingang

Sie erhalten eine natürliche Nummer (vom Typ Integeroder ähnlich).

Sie können Eingaben auf beliebige Weise vornehmen, außer wenn Sie davon ausgehen, dass sie in einer vordefinierten Variablen vorliegen. Das Lesen von Dateien, Konsolen, Dialogfeldern ( prompt), Eingabefeldern usw. ist zulässig. Die Eingabe als Funktionsargument ist ebenfalls erlaubt!


Ausgabe

Ihr Programm sollte einen Wahrheits- oder Falschwert ausgeben, der davon abhängt, ob die eingegebene Zahl eine Fakultät einer natürlichen Zahl ist.

Stellen Sie sicher, dass Ihre Wahrheits / Falsch-Werte für alle Eingaben konsistent sind. Wenn Sie also ein Paar von 1 und 0 verwenden, um Wahrheits und Falsch-Werte anzuzeigen, muss Ihr Programm 1 für alle Eingaben ausgeben, die Wahrheits-Werte haben sollen, und 0 für Alle Eingaben, die falsche Werte haben sollen.

Sie können die Ausgabe auf jede beliebige Weise ausführen, außer in eine Variable schreiben. Das Schreiben in eine Datei, eine Konsole, einen Bildschirm usw. ist zulässig. Funktion returnist auch erlaubt!

Ihr Programm darf bei keiner Eingabe Fehler erzeugen!


Testfälle

Input     Output

1         Truthy (0! or 1!)
2         Truthy (2!)
3         Falsey
4         Falsey
5         Falsey
6         Truthy (3!)
7         Falsey
8         Falsey
24        Truthy (4!)
120       Truthy (5!)

Gewinnkriterium

Das ist , also gewinnt der kürzeste Code in Bytes!


2
Wenn die Sprache nur Zahlen im Bereich {0,1} unterstützt, kann ich davon ausgehen, dass die Eingabe immer erfolgt 1?
eush77

11
@ eush77 Der Missbrauch nativer Nummerntypen zur Trivialisierung eines Problems ist standardmäßig verboten.
Dennis

1
ist 4! eine wahrheit?
Tuskiomi

Frage: Warum verwenden Sie nicht die E / A-Standardeinstellungen?
CalculatorFeline

Antworten:


37

Brachylog , 1 Byte

Probieren Sie es online!

Erläuterung

ist eine integrierte Funktion, die die folgende Beziehung behauptet: Ihre Ausgabe ist die Fakultät ihrer Eingabe. Wir geben ihm einfach eine festgelegte Ausgabe und sehen, ob sie mit einer variablen Eingabe erfolgreich ist oder nicht.


6
@BetaDecay Das liegt daran, dass es so ist, wie es in Prolog gedruckt wurde (das hat damit zu tun, dass true.es sich um eine Aussage handelt und truenicht)
Fatalize

6
Es ist eine triviale Lösung, aber aufgrund der Art und Weise, wie Prolog funktioniert, ist es clever.
Esolanging Fruit


17
Erst benutzerdefinierte Sprachen, dann benutzerdefinierte Codierungen ... Code Golf ist tot. Wir haben den ganzen Sinn dieser lustigen Probleme auf den
Alexander,

13
@Alexander Benutzerdefinierte Codierungen sind für jedes Problem, über das Sie sprechen, irrelevant. Ich könnte stattdessen jede "vorhandene" Codierung verwenden und es wäre immer noch 1 Byte. Es wäre nur viel weniger lesbar.
Fatalize


19

Gelee , 4 Bytes

Œ?IE

Nicht die kürzeste Antwort von Jelly, aber ziemlich effizient.

Probieren Sie es online!

Wie es funktioniert

Œ?IE  Main link. Argument: n

Œ?    Yield the n-th permutation of the positive integers, without the sorted tail.
      For 120, this yields [5, 4, 3, 2, 1], the tail being [6, 7, 8, ...].
  I   Increments; compute all forward differences.
      For 120, this yields [-1, -1, -1, -1].
   E  Check if all differences are equal.

2
Weil wir Code-Golfer Wert auf Effizienz legen.
Ok

12
Es ist eine dramatische Komplexitätsverbesserung auf Kosten eines Bytes und es ist eine kluge Verwendung eines eingebauten, wenn ich es selbst so sagen darf. ¯ \ _ (ツ) _ / ¯
Dennis

Interessanterweise gibt dies für 0 den Wert true zurück, während die 3-Byte-Antwort von @ LeakyNun im Allgemeinen viel langsamer den Wert false für 0 zurückgibt. Werden zusätzliche Bytes benötigt, um in einer Antwort mit effizienter Ausführungszeit false für 0 zurückzugeben?
Deadcode

@Deadcode Das Überprüfen auf 0 würde zwei zusätzliche Bytes erfordern. Wenn Sie nicht sicher sind, ob die Definition des OP für "natürliche Zahlen" 0 enthält oder nicht. Die Testfälle nicht ...
Dennis

17

ECMAScript Regex, 733+ 690+ 158 119 118 (117🐌) Bytes

Mein Interesse an Regex hat sich nach über 4½ Jahren Inaktivität mit neuer Kraft geweckt. Aus diesem Grund suchte ich nach natürlicheren Zahlensätzen und -funktionen, die mit unären ECMAScript-Regexen übereinstimmen, nahm die Verbesserung meiner Regex-Engine wieder auf und begann, auch PCRE auf den neuesten Stand zu bringen.

Ich bin fasziniert von der Fremdheit, mathematische Funktionen in ECMAScript Regex zu konstruieren. Probleme müssen aus einer ganz anderen Perspektive angegangen werden, und bis zu einer entscheidenden Einsicht ist nicht bekannt, ob sie überhaupt lösbar sind. Sie zwingt dazu, ein viel breiteres Netz zu werfen, um herauszufinden, welche mathematischen Eigenschaften verwendet werden können, um ein bestimmtes Problem lösbar zu machen.

Die Übereinstimmung von Fakultätszahlen war ein Problem, das ich 2014 gar nicht in Betracht gezogen habe - oder wenn ich es nur für einen Moment als zu unwahrscheinlich abgetan habe, dass es möglich ist. Aber letzten Monat wurde mir klar, dass es möglich ist.

Wie bei meinen anderen ECMA-regulären Texten gebe ich eine Warnung: Ich empfehle dringend, zu lernen, wie man unäre mathematische Probleme in ECMAScript regulären Texten löst. Es war eine faszinierende Reise für mich, und ich möchte sie keinem verderben, der sie möglicherweise selbst ausprobieren möchte, insbesondere denen, die sich für Zahlentheorie interessieren. In diesem früheren Beitrag finden Sie eine Liste der nacheinander mit Spoiler-Tags gekennzeichneten empfohlenen Probleme, die nacheinander gelöst werden müssen.

So lesen keine weiteren , wenn Sie nicht einige erweiterte einstellige regex Magie für Sie verwöhnen wollen . Wenn Sie versuchen möchten, diese Magie selbst herauszufinden, empfehle ich dringend, zunächst einige Probleme in ECMAScript regex zu lösen, wie in dem oben verlinkten Beitrag beschrieben.

Das war meine Idee:

Das Problem beim Abgleichen dieses Nummernsatzes ist, wie bei den meisten anderen, dass es in ECMA normalerweise nicht möglich ist, zwei sich ändernde Nummern in einer Schleife zu verfolgen. Manchmal können sie gemultiplext werden (z. B. können Potenzen derselben Basis eindeutig addiert werden), dies hängt jedoch von ihren Eigenschaften ab. Ich konnte also nicht einfach mit der eingegebenen Zahl beginnen und sie durch eine inkrementell ansteigende Dividende dividieren, bis ich 1 erreiche (zumindest dachte ich).

Dann habe ich einige Nachforschungen über die Vielzahl von Primfaktoren in Fakultätszahlen angestellt und herausgefunden, dass es eine Formel dafür gibt - und diese könnte ich wahrscheinlich in einen ECMA-Regex implementieren!

Nachdem ich eine Weile darüber nachgedacht und in der Zwischenzeit einige andere Regexe konstruiert hatte, begann ich, die faktorielle Regex zu schreiben. Es hat einige Stunden gedauert, hat aber gut funktioniert. Als zusätzlichen Bonus könnte der Algorithmus die inverse Fakultät als Übereinstimmung zurückgeben. Es gab nicht einmal einen Ausweg; Aufgrund der Art und Weise, wie es in ECMA implementiert werden muss, ist es erforderlich, vor allen anderen Maßnahmen eine Abschätzung der Umkehrung der Fakultät vorzunehmen.

Der Nachteil war, dass dieser Algorithmus für einen sehr langen regulären Ausdruck sorgte ... aber ich war erfreut, dass dafür eine Technik erforderlich war, die in meinem regulären Ausdruck mit 651-Byte-Multiplikation (der letztendlich veraltet war, weil eine andere Methode für einen 50-Byte-Ausdruck sorgte) verwendet wurde Byte Regex). Ich hatte gehofft, dass ein Problem auftaucht, das diesen Trick erfordert: Man operiert mit zwei Zahlen, die beide Potenzen derselben Basis sind, in einer Schleife, indem man sie eindeutig addiert und bei jeder Iteration trennt.

Aufgrund der Schwierigkeit und Länge dieses Algorithmus verwendete ich molekulare Lookaheads (der Form (?*...)), um ihn zu implementieren. Dies ist eine Funktion, die nicht in ECMAScript oder einer anderen regulären Regex-Engine enthalten ist, sondern die ich in meiner Engine implementiert habe . Ohne Aufnahmen in einem molekularen Lookahead ist es funktional äquivalent zu einem atomaren Lookahead, aber mit Aufnahmen kann es sehr leistungsfähig sein. Die Engine kehrt in den Lookahead zurück und kann verwendet werden, um einen Wert zu erraten, der alle Möglichkeiten (für spätere Tests) durchläuft, ohne Zeichen der Eingabe zu verbrauchen. Ihre Verwendung kann zu einer viel saubereren Implementierung führen. (Lookbehind mit variabler Länge hat mindestens die gleiche Leistung wie molekularer Lookahead, aber letzterer führt tendenziell zu einfacheren und eleganteren Implementierungen.)

Die Längen von 733 und 690 Byte stellen also keine ECMAScript-kompatiblen Inkarnationen der Lösung dar - daher das "+" nach ihnen; Es ist sicherlich möglich, diesen Algorithmus auf reines ECMAScript zu portieren (was seine Länge beträchtlich erhöhen würde), aber ich bin nicht dazu gekommen ... weil ich an einen viel einfacheren und kompakteren Algorithmus gedacht habe! Eine, die ohne molekulare Lookaheads problemlos implementiert werden kann. Es ist auch deutlich schneller.

Dieses neue muss wie das vorherige die umgekehrte Fakultät erraten, alle Möglichkeiten durchgehen und sie auf ein Match testen. Sie dividiert N durch 2, um Platz für die zu erledigende Arbeit zu schaffen, und bildet dann eine Schleife, in der die Eingabe wiederholt durch einen Teiler geteilt wird, der bei 3 beginnt und jedes Mal inkrementiert wird. (Daher können 1! Und 2! Vom Hauptalgorithmus nicht abgeglichen werden und müssen separat behandelt werden.) Der Divisor wird verfolgt, indem er zum laufenden Quotienten hinzugefügt wird. Diese beiden Zahlen können eindeutig getrennt werden, da unter der Annahme von M! == N, der laufende Quotient bleibt durch M teilbar, bis er gleich M ist.

Dieser reguläre Ausdruck dividiert durch eine Variable im innersten Teil der Schleife. Der Divisionsalgorithmus ist der gleiche wie in meinen anderen Regexen (und ähnlich dem Multiplikationsalgorithmus): für A ≤ B ist A * B = C, falls überhaupt, nur wenn C% A = 0 und B die größte Zahl ist, die B ≤ C erfüllt und C% B = 0 und (CB- (A-1))% (B-1) = 0, wobei C die Dividende ist, A der Divisor ist und B der Quotient ist. (Ein ähnlicher Algorithmus kann für den Fall verwendet werden, dass A ≥ B ist, und wenn nicht bekannt ist, wie A mit B verglichen wird, ist nur ein zusätzlicher Teilbarkeitstest erforderlich.)

Ich finde es toll , dass das Problem auf noch weniger Komplexität reduziert werden konnte als mein golfoptimierter Fibonacci-Regex , aber ich seufze mit Enttäuschung, dass meine Multiplexing-Potenzen-der-gleichen-Basis-Technik auf ein anderes Problem warten muss Das erfordert es tatsächlich, weil dies nicht der Fall ist. Es ist die Geschichte meines 651-Byte-Multiplikationsalgorithmus, der durch einen 50-Byte-Algorithmus ersetzt wird, und zwar immer wieder!

Bearbeiten: Ich konnte 1 Byte (119 → 118) mit einem von Grimy gefundenen Trick löschen , der die Division für den Fall verkürzen kann, dass der Quotient garantiert größer oder gleich dem Divisor ist.

Hier ist der reguläre Ausdruck:

True / False-Version (118 Bytes):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$|^xx?$

Probieren Sie es online!

Rückgabe inverser Fakultäten oder Nichtübereinstimmung (124 Bytes):

^(?=((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$)\3|^xx?$

Probieren Sie es online!

Rückgabe inverser Fakultäten oder Nichtübereinstimmung\K in ECMAScript + (120 Byte):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\K\3$|^xx?$

Und die freie Version mit Kommentaren:

  ^
  (?=                           # Remove this lookahead and the \3 following it, while
                                # preserving its contents unchanged, to get a 119 byte
                                # regex that only returns match / no-match.
    ((x*)x*)(?=\1$)             # Assert that tail is even; \1 = tail / 2;
                                # \2 = (conjectured N for which tail == N!)-3; tail = \1
    (?=(xxx\2)+$)               # \3 = \2+3 == N; Assert that tail is divisible by \3
    # The loop is seeded: X = \1; I = 3; tail = X + I-3
    (
      (?=\2\3*(x(?!\3)xx(x*)))  # \5 = I; \6 = I-3; Assert that \5 <= \3
      \6                        # tail = X
      (?=\5+$)                  # Assert that tail is divisible by \5
      (?=
        (                       # \7 = tail / \5
          (x*)                  # \8 = \7-1
          (?=\5(\8*$))          # \9 = tool for making tail = \5\8
          x
        )
        \7*$
      )
      x\9                       # Prepare the next iteration of the loop: X = \7; I += 1;
                                # tail = X + I-3
      (?=x\6\3+$)               # Assert that \7 is divisible by \3
    )*
    \2\3$
  )
  \3                            # Return N, the inverse factorial, as a match
|
  ^xx?$                         # Match 1 and 2, which the main algorithm can't handle

Die vollständige Geschichte meiner Golfoptimierungen dieser Regexes ist auf Github:

Regex für die Anpassung von Fakultätszahlen - Multiplizitätsvergleichsmethode mit molekularer lookahead.txt
Regex für die Anpassung von Fakultätszahlen.txt (die oben gezeigte)

((x*)x*)((x*)+)((x+)+)n=3!\233=0

Die .NET-Regex-Engine emuliert dieses Verhalten in ihrem ECMAScript-Modus nicht, und daher funktioniert die 117-Byte-Regex:

Probieren Sie es online! (Exponential-Slow-Down-Version, mit .NET-Regex-Engine + ECMAScript-Emulation)


14

JavaScript (ES6), 30 29 28 Bytes

Erwartet eine positive ganze Zahl. Returns -1für falsy und -2für truthy.

f=(n,k=2)=>n>1?f(n/k,k+1):~n

console.log(1,  '-->',f(1))   // Truthy (0! or 1!)
console.log(2,  '-->',f(2))   // Truthy (2!)
console.log(3,  '-->',f(3))   // Falsey
console.log(4,  '-->',f(4))   // Falsey
console.log(5,  '-->',f(5))   // Falsey
console.log(6,  '-->',f(6))   // Truthy (3!)
console.log(7,  '-->',f(7))   // Falsey
console.log(8,  '-->',f(8))   // Falsey
console.log(24, '-->',f(24))  // Truthy (4!)
console.log(120,'-->',f(120)) // Truthy (5!)

Hinweis : Diese Funktion unterstützt ziemlich große Eingaben (Sie sollten dies als "ziemlich groß für JS" lesen). Es sollte bis zu 2 53 - 1 sicher funktionieren . Ab N = 121.645.100.408.831.992 wird es sicher scheitern , wobei diese Eingabe auf 19 gerundet wird ! = 121.645.100.408.832.000 aufgrund seiner IEEE-754-Codierung. Es kann andere falsch positive Ergebnisse sein , bevor 121.645.100.408.831.991 wegen Rundungsfehler, aber ich weiß es nicht sicher.


Nizza - wirklich wie die Verwendung ~am Ende.
Steve Bennett

Kannst du bearbeiten, damit ich die Abstimmung aufheben kann? (Wenn Sie wissen möchten, warum ich abgelehnt habe, dann, weil ich die ungewöhnlichen E / A-Regeln dieser Frage vergessen habe.)
CalculatorFeline

@ Arnauld Undownvoted.
CalculatorFeline

11

Python 3 , 39 38 Bytes

f=lambda n,i=1:n>1and f(n/i,i+1)or n<1

Eine rekursive Funktion eine Ganzzahl machen, neinen Booleschen Wert zurück , die das Ergebnis inversley (truthy: False, Falsey: True)

Probieren Sie es online!

Dividiert wiederholt ndurch imit einem Anfangswert von 1, bis der Rest kleiner oder gleich ist 1und testet, ob dieser Rest kleiner als oder gleich ist 1. Nur Fakultäten enden mit einem Rest gleich 1und <sind ein Byte kürzer als ==.


@ovs wir haben uns auf zwei konsistente Ausgänge beschränkt. Das gibt leider 1für alle Fakultäten zurück, außer 1für die es zurückgibt True.
Jonathan Allan

11

Java 8, 46 Bytes

i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;}

Dies basiert auf Roman Gräfs Eintrag, von dem ich etwa ein Dutzend Bytes wegschlagen konnte. Ich hätte es dort vorgeschlagen, aber ich habe noch nicht genug Ruf, um einen Kommentar abzugeben! Mein geänderter Testläufercode:

import java.util.function.Function;
import java.util.stream.IntStream;

public class IsFactorial {
    public static Function<Integer, Boolean> isFactorial = i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;};
    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};
    public static void main(String[] args){
        System.out.println(
            IntStream.of(truthyCases).allMatch(i->isFactorial.apply(i)) &&
            IntStream.of(falsyCases).allMatch(i->!isFactorial.apply(i)));
    }
}

9

Netzhaut , 50 38 Bytes

Dank @Neil werden 12 Bytes gespart, indem die Schleife gekürzt und die ;

.+
1¶$&$*
+`^(1+)¶(\1)+$
1$1¶$#2$*
¶.$

Probieren Sie es online!

Ausgänge 1 für wahr und 0falsch.

.+ stimmt mit der gesamten Zahl überein

1¶$&$* Ersetzen durch 1 gefolgt von einer neuen Zeile, und konvertieren Sie das Match zu Unary

Das verbleibende Programm dividiert die unäre Zahl in der untersten Zeile durch sukzessive Erhöhung der positiven Ganzzahlen, wobei es in der obersten Zeile bleibt, während dies möglich ist.

+` Schleife, bis die Zeichenfolge gleich bleibt

  • ^(1+)¶(\1)+$stimmen Sie die oberste Zeile mit vielen 1s und ein Vielfaches davon mit vielen 1s in der untersten Zeile ab und ersetzen Sie sie durch

  • 1$1¶$#2$*Die oberste Zeile enthält viele 1s 1, dh, die durch die oberste Zeile dargestellte Zahl wird um 1 erhöht, gefolgt von der neuen Zeile und der Anzahl der Übereinstimmungen der obersten Zeile in der untersten Zeile (dh Anzahl der Übereinstimmungen der zweiten Erfassungsgruppe) ) viele 1s, das heißt, die untere Zahl durch die obere Zahl teilen

Sobald dies nicht mehr möglich ist,

¶.$Geben Sie die Anzahl der Übereinstimmungen dieses regulären Ausdrucks an, d. h. Gibt es einen Einzelgänger?1 in der untersten Zeile ein Einzelfall, der nur auftritt, wenn die Zahl eine Fakultät ist?


Wenn kein Absturz / Absturz statt wahrer / falscher Werte zulässig ist, kann ich 36 bis 34 Bytes abrufen .

^
1¶
{`.+$
$*
^(1+)¶(\1)+$
1$1¶$#2

Dies geschieht auf die gleiche Weise, kombiniert jedoch $*die dritte und vierte Zeile. Die dritte Zeile ab ist ein Teil derselben Schleife, {ist kurz für +(die (Gruppierung der verbleibenden Zeilen in der Schleife. Factorials enden damit, dass das Programm aus der Schleife ausbricht, während Nicht-Factorials für immer in der Schleife stecken bleiben, bis Retina eine OverflowException auslöst, die darauf zurückzuführen ist, dass die letzte Ersetzung fehlschlägt Konvertiert die unterste Zeile von dezimal in unär, sodass sie schnell in die Luft sprengt.


Speichern Sie ein Byte, indem Sie das entfernen, 1wie es $*am Ende des Austauschs impliziert ist.
Neil

Besser noch, kombinieren Sie die $*mit den beiden anderen Zeilen.
Neil


3
Ich bin beeindruckt, dass Sie einen Weg gefunden haben, Retina bedingt zum Absturz zu bringen. :)
Martin Ender

2
Können Sie eine Erklärung hinzufügen?
CalculatorFeline

8

05AB1E , 4 Bytes

L!QO

Probieren Sie es online!

Erläuterung

L      # range [1 ... input]
 !     # calculate factorial of each
  Q    # compare with input for equality
   O   # sum

1
Müssten Sie die Eingabe nicht zuerst duplizieren, weil Ldie Eingabe erscheint? Außerdem erhalten Å!Sie eine Liste von Fakultäten, die kleiner oder gleich der Eingabe sind.
Neil A.

@NeilA. Zum Glück wird die Eingabe erneut abgerufen, wenn nicht genügend Argumente für eine Operation auf dem Stack vorhanden sind, sodass ich sie hier nicht benötige D. Guter Fang über Å!. Ich vergesse immer die Listenbefehle. Es werden keine Bytes gespeichert, aber es ist sicher effizienter.
Emigna

Ich wusste nicht, dass Eingaben erneut abgesetzt werden ... das könnte sicher eine Menge Bytes sparen.
Neil A.

@NeilA. Es ist eine ziemlich neue Funktion. Es wurde vor weniger als einem Monat hinzugefügt, denke ich.
Emigna

8

C ++, 102 100 92 Bytes

#include<cmath>
int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}

Durchläuft alle Werte von 0bisn und berechnet die Fakultät und prüft dann, ob sie gleich ist n.

Danke Christoph! (8 Bytes gespeichert)


Hallo! Willkommen bei PPCG! Schöne erste Antwort! Viel Glück für die Zukunft!
Arjun

Schöne erste Antwort! Sie können ein paar Byte wie folgt speichern: int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}. lroundund lgammasind schon C ++ 11 also könnte das einfach #include<cmath>. Vielleicht kannst du meine Vorschläge noch weiter verbessern :)
Christoph

7

Haskell , 43 26 Bytes

f n=elem n$scanl1(*)[1..n]

Probieren Sie es online!


2
f n=elem n$scanl1(*)[1..n]ist lächerlich ineffizient, aber kürzer.
Laikoni

Gibt es keine Regel zur Codeeffizienz?
Sonntag,

1
Keine, die mir bekannt sind. code-golf fragt nach einer Lösung in möglichst wenigen Bytes ohne Effizienzangaben. Auch auf meiner Maschine funktioniert die Funktion 40430ohne merkliche Verzögerung.
Laikoni

Ich meinte etwas im Sinne von "Die Lösung sollte innerhalb eines angemessenen Zeitrahmens enden", aber ich denke, es passt in beide Richtungen zu den Anforderungen. Vielen Dank!
Sonntag,

1
Schön und einfach. Ich dachte, ich könnte besser mit Division umgehen, divModindem ich [1..]nacheinander einen Nullrest mit einem Quotienten von 1 (Fakultät) oder einem Rest ungleich Null (Fakultät) erreiche, aber es scheint nicht der richtige Ansatz zu sein. Ich habe diese nette 46-Zeichen - Lösung finden, aber: f|let x%n=mod n x==0&&(x+1)%div n x||n==1=(1%).
Jon Purdy

6

Haskell , 38 Bytes

m#n=n<2||mod n m<1&&(m+1)#div n m
(2#)

Probieren Sie es online! Beispiel Nutzung: (2#) 24. Rückgabe Trueoder False.

Dies ist die kürzeste, die ich bekommen konnte, während ich noch sehr effizient bin. Selbst für Zahlen so groß wie

145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000

Das Ergebnis wird sofort angezeigt. Die Lösung funktioniert, indem die Eingabe durch dividiert nwird, m = 2,3,4,5,...bis entweder das Ergebnis eins oder eins istn nicht mehr durch teilbar ist m.

Hier finden Sie die kürzere, aber unglaublich ineffiziente 26-Byte-Lösung, die n!Eingaben berechnet , die keine Fakultäten sind .



5

Fourier , 40 39 Bytes

I~Q1~N(i^~i*N~N{Q}{1~Xo}N>Q{1}{1~X0o}X)

Probieren Sie es auf FourIDE!

Grundsätzlich multipliziert man die Zahl N mit einem ansteigenden Betrag, bis N entweder gleich (Ausgang 1) oder größer (Ausgang 0) der Eingabe ist.

Erklärung Pseudocode:

Q = Input
N = 1
While X != 1
    i += 1
    N = N*i
    If N = Q Then
        Print 1
        X = 1
    End If
    If N > Q Then
        Print 0
        X = 1
    End If
End While

5

Japt , 8 6 Bytes

ol x¥U

Probieren Sie es online!

Dies gibt 0 für falsch und 1 für wahr aus.

Erläuterung

 ol x¥ U
Uol x==U
Uo       # Create the range [0 ... input]
  l      # Replace each element by its factorial
     ==U # Compare each element to the input (yielding 1 if equal and 0 otherwise)
    x    # And sum the result

1
Ich sollte wirklich ein "enthält" eingebaut hinzufügen: P
ETHproductions

1
Oh hey, können Sie ändern , aU ¦Jum x¥U(Karte jeweils Xzu X==Uund Summe), obwohl es wird nicht funktionieren auf TIO.
ETHproductions

Scheitert, 2weil onur Sie geben [0,1]. Hier ist ein Fix mit einer 1-Byte-Einsparung.
Shaggy

4

Perl 5, 31 Bytes

$a=<>;$a/=++$i while$a>1;exit$a

Die Eingabe erfolgt über STDIN, die Ausgabe erfolgt über den Exit-Code (1 für Fakultät, 0 für Fakultät).

Die Eingabe wird durch aufeinanderfolgende Ganzzahlen geteilt, bis sie entweder 1 oder einen Bruch kleiner als 1 ist, der im Ergebnis abgeschnitten wird.


-5 Bytes TIO
Nahuel Fouilleul

4

Perl 6 , 29 Bytes

{($_,{$_/++$}...2>*).tail==1}

Probier es aus

Erweitert:

{   # bare block lambda with implicit parameter 「$_」

  (              # generate a sequence

    $_,          # starting with the input

    {
      $_ / ++$   # divide previous element by an ever increasing number
                 # 1,2,3,4,5,6,7,8 ... *
    }

    ...          # keep generating until

    2 > *        # 2 is greater than what was generated
                 # ( 1 or a fractional number )

  ).tail == 1    # check if it ended at 1
}

17 Bytes {$_∈[\*] 1..$_}. Ein weiterer interessanter Ansatz ist 2>*.polymod(1..*).sum.
Nwellnhof

4

setlX , 32 bytes

f:=n|=>exists(x in{0..n}|n==x!);

Erzeugt eine aufgerufene Funktion f in der Sie Ihre potenzielle Fakultät als Parameter verwenden.

Es funktioniert mit einer beliebigen Ganzzahlgröße, ist aber ziemlich ineffizient.

(Übrigens: Dies ist meine erste Teilnahme an einem Programmierpuzzle.)




4

C # (.NET Core) , 68 Byte

bool f(System.Numerics.BigInteger n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

Probieren Sie es online!

Nicht die kürzeste Lösung, funktioniert aber mit wirklich großen Zahlen. Die TIO-Verknüpfung enthält ein Beispiel mit 10000!.

Hier ist eine kürzere Version, intdie einen Maximalwert von 2147483647 verwendet .

C # (.NET Core) , 45 Byte

bool f(int n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

Probieren Sie es online!

Dank an @KevinCruijssen für das Golfen von insgesamt 3 Bytes aus beiden Antworten!


2
Das &&kann golfen werden &, und das Schleppen ;muss nicht für Lambda-Funktionen gezählt werden. Kann das nicht ulong k=2auch uint k=2in Ihrer 50-Byte-Antwort stehen?
Kevin Cruijssen

1
Guter Fang am &vs &&. Ich dachte, ich hätte einen Stapelüberlauf, aber es scheint trotzdem zu funktionieren. ulong64 Bits ist , während uintist 32. Es sieht aus wie andere verwenden , intso werde ich vielleicht , dass nur für die kurze Version. In Bezug auf das Trailing ;handelt es sich hierbei um vollständige Funktionen, nicht um Lambdas. Ich denke, ich muss sie einbeziehen.
Dana

Das ist wirklich seltsam , wie .NET auflösen kann /und %zwischen ulongunduint , aber nicht ulongund int. Wussten Sie nicht, dass :)
Dana

1
@Oliver - Wenn doubleSie irgendwann eine Rundung bemerken - zum Beispiel 24! und 120! Scheitern. Während System.Numerics.BigIntegerhat die höchste Präzision,int ist die kürzeste Antwort :)
Dana

1
@Deadcode - Sie haben Recht , über 0 :) Basierend auf den Beispielen in der Herausforderung, ich „natürliche Zahlen“ interpretiert 1,2 bedeuten, ... Ich bin damit einverstanden , dass in der realen Welt, es besser ist , die ein Kurzschluss zu verwenden &&Operator . Aber das ist Codegolf;) Schön, dass dir das 10000!Beispiel gefällt !
Dana

4

C ++ (clang), 51 Bytes

Rekursion setzt sich beim Golfen durch.

51 Bytes, Null ist wahr:

int f(int n,int i=2){return n<2?!n:n%i|f(n/i,i+1);}

Dies kostet eine Menge Geschwindigkeit für 1 Byte Einsparungen. Ersetzen Sie das |mit ||, um es schnell zu machen, da das logische ODER kurzgeschlossen wird.

Probieren Sie es online! (51 Byte langsame Version)
Probieren Sie es online! (52 Byte schnelle Version)

Ungolfed langsame Version:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    // Because any nonzero value represents "false", using "|" here is equivalent
    // to "||", provided that the chain of recursion always eventually ends. And
    // it does always end, because whether or not "n" is factorial, the "n / i"
    // repeated division will eventually give the value of zero or one, satisfying
    // the above condition of termination.
    return (n % i) | isFactorial(n / i, i+1);
}

Ungolfed schnelle Version:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    if (n % i != 0)
        return 1; // not factorial
    else
        return isFactorial(n / i, i+1);
}

Es gibt viele Möglichkeiten, dies neu zu ordnen.

52 Bytes, ungleich Null ist wahr:

int f(int n,int i=2){return n<2?n:n%i?0:f(n/i,i+1);}

Probieren Sie es online!

52 Bytes, Null ist wahr:

int f(int n,int i=2){return!n?1:n%i?n-1:f(n/i,i+1);}

Probieren Sie es online!

Bevor ich auf die Rekursion zurückgegriffen habe, habe ich versucht, einige iterative Versionen zu erstellen, und sie kamen einander sehr nahe.

54 Bytes, ungleich Null ist wahr:

int f(int n){for(int i=2;n>1;)n=n%i?0:n/i++;return n;}

Probieren Sie es online!

54 Bytes, null ist wahr (basierend auf der Java 8-Übermittlung von Roman Gräf ):

int f(int n){int a=1,i=0;for(;a<n;a*=++i);return a-n;}

Probieren Sie es online!

Nun, für den Boden des Fasses, rekursive Versionen ohne n==0Behandlung (ich halte diese für ungültig, da 0 eine natürliche Zahl ist und keine Definition, in der es sich nicht um "natürliche Zahlen" handelt, die nur sehr begrenzt verwendet werden können). In den folgenden Versionen f(0)löst die unendliche Rekursion von entweder einen Segfault aufgrund eines Überlaufs des Stacks aus, oder sie wird mit Compilern, die sie für die Iteration optimieren, endlos wiederholt:

48 Bytes, Null ist wahr:

int f(int n,int i=2){return n%i?n-1:f(n/i,i+1);}

Probieren Sie es online!

48 Bytes, null ist wahr (basierend auf Hagen von Eitzens 33-Byte-C-Submission (gcc) ):

int f(int n,int e=0){return n%++e?n-1:f(n/e,e);}

Probieren Sie es online!


50 EDIT: 49 , ohne Rekursion.
Grimmy

Zurück zur Rekursion für 48 . Und das wird Ihnen wahrscheinlich nicht gefallen, aber 44 durch die Verwendung einer globalen Variable.
Grimmy

3

Mathematica, 20 Bytes

!FreeQ[Range[#]!,#]&

andere Version zum Testen großer Zahlen (siehe Kommentare)

Range[10^3]!~MemberQ~#&

testet bis zu 1000!


2
Wie ich die Frage verstehe, ist Mathematica in der Lage, 1001 zu nehmen! Als Eingabe entspricht dies dann nicht der Spezifikation.
Peter Taylor

2
Sie können sogar drei Bytes einsparen und diese für alle Eingaben gültig machen. Ersetzen Sie einfach 10 ^ 3 durch #; Sie könnten ein weiteres Byte mit Range @ # speichern
Julien Kluge

@ Julien Klugethen auf der Suche nach 1243234 würde ewig dauern ...
J42161217

1
Ich denke , dass Sie ein anderes Byte durch Ersetzen speichern kann Range[#]mit Range@#:)
numbermaniac

3
Sieht aus wie Sie können noch ein weiteres Byte mit Infix Syntax speichern: !Range@#!~FreeQ~#&.
numbermaniac

3

Cubix , 24 Bytes

U0O@1I1>-?1u>*w;W;@Orq)p

Probieren Sie es online aus

Cubified

    U 0
    O @
1 I 1 > - ? 1 u
> * w ; W ; @ O
    r q
    ) p

Wir beginnen damit 1, Input 1auf den Stapel zu schieben . Dies sind unser Index, unser Ziel bzw. unser Akkumulator.

Wir machen dann eine Schleife. Bei jeder Iteration subtrahieren wir den Akkumulator von der Eingabe. Wenn das Ergebnis 0 ist, sind wir fertig, also geben wir Push 1, OUtput und Exit ein. Wenn es negativ ist, sind wir zu weit gegangen, also pushen wir 0, Ogeben auf und beenden. Ansonsten sehen wir

;p)*rq;
;         Pop the difference off the stack.
 p)       Move the index to the top of the stack and increment it.
   *      Multiply the accumulator by the index to get the next factorial.
    rq;   Put the stack back in the right order.

3

Neim , 8 Bytes

𝐈Γ𝐈𝐩₁𝔼)𝐠

Erläuterung:

Example input: 6
𝐈         Inclusive range [1 .. input]
          [1, 2, 3, 4, 5, 6]
 Γ        For each...
  𝐈         Inclusive range [1 .. element]
            [[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6]]
   𝐩        Product
            [1, 2, 6, 24, 120, 720]
     𝔼      Check for equality with
    ₁       the first line of input
            [[0, 0, 1, 0, 0, 0]]
      )   End for each
       𝐠  Select largest element
          [1]

Versuch es!

Neim , 3 Bytes (nicht konkurrierend)

Nicht konkurrierende als enthält Token und faktorielle Token wurden hinzugefügt, nachdem die Herausforderung gemacht wurde.

𝐈𝐓𝕚

Erläuterung:

Example input: 6
𝐈     Inclusive range [1 .. input]
      [[1, 2, 3, 4, 5, 6]
 𝐓    Factorial each
      [[1, 2, 6, 24, 120, 720]]
  𝕚   Check that the [cycled] input is in the list
      [1]

Versuch es!


3

> <> , 24 22 Bytes

-2 Bytes dank @Aaron

Ich versuche eine neue Sprache (seit meine Mathematica-Lizenz abgelaufen ist ...)

01\{=n;
?!\$1+:@*:{:}(

Probieren Sie es online oder auf dem Fischspielplatz

Angenommen, die eingegebene Nummer befindet sich bereits auf dem Stapel und gibt 0 oder 1 zurück. Sie multipliziert die ersten n Zahlen, bis die Eingabe nicht mehr kleiner ist, und gibt dann 1 aus, wenn sie der Eingabe entspricht, und 0, wenn sie nicht vorhanden ist. ' t.


Du könntest dich verwandeln v>\n<^in \\n/; siehe hier
Aaron

@ Aaron, das ist genial, danke!
Kein Baum

3

APL (Dyalog Unicode) , 5 6 7 Bytes

Ein Byte , indem golfed ×/zu !dank Erik die Outgolfer

⊢∊!∘⍳

Probieren Sie es online!

Erläuterung

                          Range of numbers from 1 to argument, 1 2 3 4 .. n
   !                       Factorial; 1! 2! 3! 4! .. n!
⊢∊                         Is the right argument a member of this list?

Kumulative Summe?
Undichte Nonne

@LeakyNun Fixed
Kritixi Lithos

Ein zusätzliches Byte in GNU APL 1.2. N∊×\⍳N←⎕Wie nimmt dies ein Argument an? Ich sehe nnirgendwo Ist das eine Dyalog-spezifische Sache?
Arc676

2
@ Arc676 Meine Lösung ist ein Zug und du nennst es so: (⊢∊(×/⍳)) right_argumentwie du im TIO Link siehst. Und das bezieht sich auf das richtige Argument.
Kritixi Lithos

Anmerkungen: AGL speichert Sie ein Byte; ⊢∊×\ä⍳. Die "richtige" (aber längere) Lösung wäre 0=1|!⍣¯1; "Ist die Inverse Fakultät eine ganze Zahl?"
Adám

2

JavaScript (ES6), 71 Byte

Dies nimmt die Eingabe als Funktionsargument und alerts die Ausgabe auf. Ausgänge 0für Falsey und 1für Truthy.

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}alert(r)}

Erläuterung

Das Programm besteht aus zwei Funktionen fund g. fist eine rekursive Fakultätsberechnungsfunktion und gist die Hauptfunktion des Programms. g geht davon aus , ein einziges Argument zu haben n. Es definiert ein Standardargument rmit dem Wert 0 und ein anderes Standardargument mit dem Wert 0. Es iteriert dann über alle Ganzzahlen von 0 bis nund prüft in jeder Iteration, ob die füber i(den aktuellen Index) angewendete Funktion gleich ist n, dh ob neine Fakultät von ist i. In diesem Fall wird rder Wert auf 1 gesetzt. Am Ende der Funktion rwird alerted.

Testschnipsel

( Hinweis: Das Snippet gibt aus, dass console.log()niemand zu viele dieser lästigen alert()s mag . )

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}console.log(r)}

g(1)
g(2)
g(3)
g(4)
g(5)
g(6)
g(7)
g(8)
g(24)
g(120)


Eval ist möglicherweise kürzer als die Verwendung eines Codeblocks.
Downgoat

@Downgoat Wie soll ich das machen? Entschuldigung, wenn es zu offensichtlich ist! : P
Arjun

2

QBIC , 21 bis 19 Bytes

[:|q=q*a~q=b|_x1}?0

Erläuterung

[:|     Start a FOR loop from 1 to n
q=q*a   q starts as 1 and is multiplied by the FOR loop counter
        consecutively: q=1*1, *2, *3, *4 ... *n
~q=b|   If that product equals n
_x1     Then quit, printing a 1
}       Close the IF and the FOR
?0      If we're here, we didn't quit early and didn't find a factorial, print 0

Vorher

[:|q=q*a┘c=c+(q=b)}?c

Erläuterung:

[:|         Start a FOR loop from 1 to n
q=q*a       q starts as 1 and is multiplied by the FOR loop counter
            consecutively: q=1*1, *2, *3, *4 ... *n
┘           Syntactic line break
c=c+        c starts out at 0 and then keeps track of 
    (q=b)       how often our running total == n
}           Closes the FOR-loop
?c          Print c, which is 0 fir non-factorials and -1 otherwise.

2

Java 8, 59 Bytes

i->{for(int j=1,c=0;j<=i;j*=++c)if(j==i)return 1;return 0;}

Testcode

import java.util.function.IntFunction;
import java.util.stream.IntStream;

public class IsFactorial
{
    public static IntFunction<Integer> isFactorial = i->
    {
        for(int j=1,c=0;j<=i;j*=++c)
            if(j==i)return 1;return 0;
    };

    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};

    public static void main(String[] args)
    {
        System.out.println
        (
            IntStream.of(truthyCases)
                .allMatch(i->isFactorial.apply(i)==1)
            && IntStream.of(falsyCases)
                .allMatch(i->isFactorial.apply(i)==0)
        );
    }
}
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.