Ce nombre est-il factoriel?


38

La tâche

À partir d’un nombre naturel en entrée, votre tâche consiste à produire une valeur de vérité ou de falsey selon que l’entrée est une factorielle de tout nombre naturel. Vous pouvez supposer que le numéro saisi sera toujours compris dans la plage de numéros prise en charge par votre langue, mais vous ne devez pas abuser des types de numéros natifs pour banaliser le problème .

Des échappatoires standard s'appliquent.


Contribution

Vous recevrez un nombre naturel (de type Integerou similaire).

Vous pouvez prendre les entrées de la manière que vous voulez, sauf en supposant que ce soit dans une variable prédéfinie. La lecture depuis un fichier, une console, une boîte de dialogue ( prompt), une zone de saisie, etc. est autorisée. L'entrée comme argument de fonction est également autorisée!


Sortie

Votre programme doit générer une valeur de vérité ou de falsey selon que le nombre entré est une factorielle d'un nombre naturel.

Assurez-vous que vos valeurs de vérité / falsey sont cohérentes pour toutes les entrées, c.-à-d. Si vous utilisez une paire de 1 et 0 pour désigner respectivement les valeurs de vérité et de falsey, votre programme doit générer 1 pour toutes les entrées qui doivent avoir des valeurs de vérité et 0 pour toutes les entrées qui devraient avoir des valeurs de falsey.

Vous pouvez utiliser la sortie de n'importe quelle manière, sauf l'écrire dans une variable. L'écriture dans un fichier, une console, un écran, etc. est autorisée. La fonction returnest également autorisée!

Votre programme ne doit générer aucune erreur pour aucune entrée!


Cas de test

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

Critère gagnant

C'est du , donc le code le plus court en octets gagne!


2
Si la langue ne prend en charge que les nombres compris entre {0,1}, puis-je m'attendre à ce que l'entrée soit toujours 1?
eush77

11
@ eush77 Abuser des types de nombres natifs pour banaliser un problème est interdit par défaut.
Dennis

1
est 4! une vérité?
Tuskiomi

Question: Pourquoi n'utilisez-vous pas les paramètres par défaut d'E / S?
CalculatorFeline

Réponses:


37

Brachylog , 1 octet

Essayez-le en ligne!

Explication

est une fonction intégrée qui affirme la relation suivante: sa sortie est la factorielle de son entrée. Nous lui donnons simplement une sortie définie et voyons si elle réussit ou non avec une entrée variable.


6
@BetaDecay C'est parce que c'est la manière dont elle est imprimée dans Prolog (c'est dû au fait que true.c'est une déclaration et qu'elle truene l'est pas)
Fatalize

6
C'est une solution triviale, mais astucieuse à cause du fonctionnement du prologue.
Fruit Esolanging


17
D'abord des langues personnalisées, puis des encodages personnalisés ... le code golf est mort. Nous avons complètement détourné le sens de ces problèmes amusants en premier lieu
Alexander - Réintégrer Monica

13
@Alexander Les encodages personnalisés ne sont pas pertinents, quel que soit le problème dont vous parlez. Je pourrais utiliser n'importe quel encodage "existant" à la place et ce serait toujours un octet. Ce serait juste beaucoup moins lisible.
Fataliser


19

Gelée , 4 octets

Œ?IE

Pas la réponse la plus courte, mais c'est plutôt efficace.

Essayez-le en ligne!

Comment ça marche

Œ?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
Parce que nous, les golfeurs, nous nous soucions de l'efficacité.
Okx

12
C'est une amélioration spectaculaire de la complexité au prix d'un octet et une utilisation intelligente d'une fonction intégrée si je puis le dire moi-même. ¯ \ _ (ツ) _ / ¯
Dennis

Fait intéressant, cela retourne vrai pour 0, alors que la réponse sur 3 octets de @ LeakyNun, bien que beaucoup plus lente en général, renvoie correctement faux pour 0. Des octets supplémentaires sont-ils nécessaires pour renvoyer faux pour 0 dans une réponse à délai d'exécution efficace?
Deadcode

@Deadcode La vérification de 0 nécessiterait deux octets supplémentaires. Si vous n'êtes pas sûr si la définition de "nombres naturels" dans l'OP inclut 0 ou non. Les cas de test ne ...
Dennis

17

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

Mon intérêt pour regex a été suscité avec une vigueur renouvelée après plus de quatre ans et demi d'inactivité. En tant que tel, je suis allé à la recherche d'ensembles de nombres et de fonctions plus naturels à assortir à des expressions rationnelles unaires ECMAScript, j'ai repris l'amélioration de mon moteur d'expression régulière et ai commencé à mettre à jour PCRE.

Je suis fasciné par l'aliénation de la construction de fonctions mathématiques dans les expressions rationnelles ECMAScript. Les problèmes doivent être abordés sous un angle totalement différent et, jusqu'à l'arrivée d'une idée clé, on ne sait pas s'ils sont résolus. Cela oblige à utiliser un réseau beaucoup plus large pour déterminer quelles propriétés mathématiques pourraient être utilisées pour résoudre un problème particulier.

La correspondance des nombres factoriels était un problème que je n'avais même pas envisagé de résoudre en 2014 - ou, le cas échéant, momentanément, le rejetant comme étant trop improbable pour être possible. Mais le mois dernier, j'ai réalisé que cela pourrait être fait.

Comme pour mes autres posts sur les expressions rationnelles ECMA, je tiens à vous avertir: je vous recommande vivement d'apprendre à résoudre des problèmes mathématiques unaires dans ECMAScript regex. Ce voyage a été fascinant pour moi et je ne veux pas le gâter pour ceux qui voudraient éventuellement l'essayer eux-mêmes, en particulier ceux qui s'intéressent à la théorie des nombres. Voir ce message précédent pour une liste de problèmes recommandés consécutivement étiquetés spoiler à résoudre un par un.

Donc , ne lisez pas plus loin si vous ne voulez pas que la magie avancée des regex unaires soit gâtée . Si vous voulez vraiment essayer de découvrir cette magie vous-même, je vous recommande vivement de commencer par résoudre certains problèmes de la regex ECMAScript, comme indiqué dans l'article ci-dessus.

C'était mon idée:

Le problème de la correspondance de cet ensemble de numéros, comme de la plupart des autres, est que dans ECMA, il est généralement impossible de garder trace de deux numéros changeants dans une boucle. Parfois, ils peuvent être multiplexés (par exemple, des puissances de la même base peuvent être additionnées sans ambiguïté), mais cela dépend de leurs propriétés. Je ne pouvais donc pas simplement commencer par le nombre entré et le diviser par un dividende croissant progressivement jusqu'à atteindre 1 (ou du moins je le pensais, au moins).

Ensuite, j'ai fait des recherches sur les multiplicités des facteurs premiers en nombres factoriels et appris qu'il existe une formule pour cela - et que je pourrais probablement la mettre en œuvre dans une regex ECMA!

Après avoir cuit dessus pendant un certain temps et construit entre-temps d'autres expressions rationnelles, je me suis lancé dans la tâche d'écrire l'expression rationnelle factorielle. Cela a pris plusieurs heures, mais a fini par bien fonctionner. En prime, l'algorithme pourrait renvoyer la factorielle inverse sous forme de correspondance. Il n'y avait pas moyen de l'éviter, même; De par la nature même de la manière dont il doit être mis en œuvre dans ECMA, il est nécessaire de deviner ce qu'est la factorielle inverse avant de faire autre chose.

L’inconvénient est que cet algorithme créait une très longue expression régulière ... regex octet). J'espérais qu'un problème nécessitant cette astuce se présenterait: Opérer sur deux nombres, qui sont tous deux des puissances de la même base, en boucle, en les additionnant sans ambiguïté et en les séparant à chaque itération.

Mais à cause de la difficulté et de la longueur de cet algorithme, j'ai utilisé des propriétés d'anticipation moléculaires (de la forme (?*...)) pour le mettre en œuvre. Il s’agit d’une fonctionnalité qui ne figure pas dans ECMAScript ni dans aucun autre moteur regex traditionnel, mais que j’ai implémentée dans mon moteur . Sans capture à l'intérieur d'un look moléculaire moléculaire, son fonctionnement est équivalent à un look atomique, mais avec des captures, il peut être très puissant. Le moteur fera un retour en arrière dans la vue anticipée, ce qui peut être utilisé pour conjecturer une valeur qui parcourt toutes les possibilités (pour des tests ultérieurs) sans consommer les caractères de l'entrée. Leur utilisation peut permettre une implémentation beaucoup plus propre. (La recherche de longueur variable est à tout le moins égale en puissance à la présentation moléculaire, mais cette dernière a tendance à donner lieu à des implémentations plus simples et élégantes.)

Ainsi, les longueurs de 733 et 690 octets ne représentent pas réellement des incarnations de la solution compatibles avec ECMAScript - d'où le "+" après celles-ci; il est sûrement possible de porter cet algorithme en ECMAScript pur (ce qui augmenterait sa longueur un peu), mais je ne l'ai pas compris… parce que j'ai pensé à un algorithme beaucoup plus simple et plus compact! Une solution qui pourrait facilement être mise en œuvre sans avoir une apparence moléculaire. C'est aussi beaucoup plus rapide.

Ce nouveau, comme le précédent, doit deviner la factorielle inverse, en passant en revue toutes les possibilités et en les testant pour une correspondance. Il divise N par 2 pour faire de la place pour le travail à effectuer, puis amorce une boucle dans laquelle il divise à plusieurs reprises l'entrée par un diviseur qui commence à 3 et s'incrémente à chaque fois. (En tant que tel, 1! Et 2! Ne peuvent pas être comparés par l'algorithme principal et doivent être traités séparément.) Le diviseur est conservé en l'ajoutant au quotient en cours d'exécution; ces deux nombres peuvent être séparés sans ambiguïté car, en supposant que M! == N, le quotient courant continuera d'être divisible par M jusqu'à ce qu'il soit égal à M.

Cette expression rationnelle effectue une division par une variable dans la partie la plus interne de la boucle. L'algorithme de division est le même que dans mes autres expressions rationnelles (et similaire à l'algorithme de multiplication): pour A≤B, A * B = C s'il n'y en a que si C% A = 0 et B est le plus grand nombre qui satisfait B≤C et C% B = 0 et (CB- (A-1))% (B-1) = 0, où C est le dividende, A le diviseur et B le quotient. (Un algorithme similaire peut être utilisé dans le cas où A≥B, et si on ne sait pas comment A se compare à B, un test de divisibilité supplémentaire suffit.)

J'adore donc que le problème ait pu être réduit à un niveau de complexité encore inférieur à celui de mon regex de Fibonacci optimisé pour le golf , mais je soupire avec déception que ma technique de multiplexage des pouvoirs de la même base devra attendre un autre problème. cela l'exige réellement, parce que celui-ci n'en a pas. C'est l'histoire de mon algorithme de multiplication de 651 octets remplacé par un algorithme de 50 octets, encore et encore!

Edit: J'ai pu supprimer 1 octet (119 → 118) en utilisant une astuce trouvée par Grimy qui peut encore raccourcir la division dans le cas où le quotient est garanti supérieur ou égal au diviseur.

Sans plus tarder, voici la regex:

Version vraie / fausse (118 octets):

^((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?$

Essayez-le en ligne!

Renvoyer une factorielle inverse ou une absence de correspondance (124 octets):

^(?=((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?$

Essayez-le en ligne!

Renvoie une factorielle inverse ou une absence de correspondance, en ECMAScript +\K (120 octets):

^((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?$

Et la version libre avec commentaires:

  ^
  (?=                           # 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

L'historique complet de mes optimisations de golf de ces regex est sur github:

regex pour les nombres factoriels correspondants - méthode de comparaison de multiplicité, avec
regex moléculaire lookahead.txt pour les nombres factoriels correspondants.txt (celui présenté ci-dessus)

Notez que vous ((x*)x*)pouvez changer pour((x*)+)((x+)+)n=3!\23-3=0

Le moteur de regex .NET n'émule pas ce comportement en mode ECMAScript, et le regex de 117 octets fonctionne:

Essayez-le en ligne! (version à ralentissement exponentiel, avec moteur de régression .NET + émulation ECMAScript)


14

JavaScript (ES6), 30 29 28 octets

S'attend à un entier positif. Retours -1pour la fausseté et -2pour la vérité.

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

Remarque : cette fonction prend en charge les très grandes entrées (vous devez le lire comme suit: 'assez grand pour JS'). Il devrait fonctionner en toute sécurité jusqu'à 2 53 - 1 . Il échouera à coup sûr à partir de N = 121 645 100 , 408 831 992 , cette entrée étant arrondie à 19! = 121 645 100 408 832 000 en raison de son codage IEEE-754. Il se peut que d’autres résultats faux positifs aient été obtenus avant 121 645 100 408 831 991 à cause d’erreurs d’arrondi, mais je ne le sais pas avec certitude.


Nice - aime vraiment l'utilisation de ~à la fin.
Steve Bennett

Pouvez-vous éditer pour que je puisse annuler le vote? (Si vous voulez savoir pourquoi j'ai rétrogradé, c'est parce que j'ai oublié les règles d'E / S inhabituelles de cette question.)
CalculatorFeline

@Arnauld Non voté.
CalculatriceFeline

11

Python 3 , 39 38 octets

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

Une fonction récursive en prenant un entier n, retournant une valeur booléenne inversley représentant le résultat (truthy: False, Falsey: True)

Essayez-le en ligne!

Divise de manière répétée npar i, avec une valeur initiale de 1, jusqu'à ce que le reste soit inférieur ou égal à 1alors teste si ce reste est inférieur à 1, seules les factorielles se termineront par un reste égal à 1et <sera un octet plus court que ==.


@ovs nous avons été limités à deux sorties cohérentes. Cela, malheureusement, revient 1pour toutes les factorielles sauf 1pour lesquelles il retourne True.
Jonathan Allan

11

Java 8, 46 octets

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

Ceci est basé sur l'entrée de Roman Gräf que j'ai pu supprimer d'une douzaine d'octets. Je l'aurais suggéré mais je n'ai pas encore assez de réputation pour commenter! Mon code de testeur modifié:

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

Retina , 50 38 octets

12 octets économisés grâce à @Neil en combinant raccourcissement de la boucle et suppression du ;

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

Essayez-le en ligne!

Sorties 1pour true et0 pour faux.

.+ correspond au nombre entier

1¶$&$* en le remplaçant par 1 suivi d'un saut de ligne et le match converti en unaire

Le programme restant divise le nombre unaire de la ligne du bas en augmentant successivement les entiers positifs, suivi dans la ligne du haut, alors qu'il est possible de le faire.

+` boucle jusqu'à ce que la chaîne reste identique

  • ^(1+)¶(\1)+$correspondre à la ligne supérieure de nombreux 1s et un multiple de nombreux 1s sur la ligne du bas et le remplacer par

  • 1$1¶$#2$*la ligne du haut est 1remplacée par une autre 1, c’est-à-dire que le nombre représenté par la ligne du haut est augmenté de 1, suivi de la nouvelle ligne et du nombre de correspondances de la ligne du haut dans la ligne du bas (c.-à-d. le nombre de correspondances du deuxième groupe de capture ) beaucoup de 1s, c'est-à-dire en divisant le nombre du bas par le nombre du haut

Une fois qu'il n'est plus possible de le faire,

¶.$donne le nombre de correspondances de cette regex, ie. existe-t-il un seul 1sur la ligne du bas, ce qui ne se produit que si le nombre est un facteur


Si aucun crash / crash est autorisé à la place des valeurs véracité / faux, je peux alors obtenir 36 34 octets.

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

Cela va dans le même sens, mais combine $*les troisième et quatrième lignes. La troisième ligne est en avant d' une partie de la même boucle, {est une abréviation pour le +(cas des (groupes les lignes restantes dans la boucle. Les factorielles se terminent lorsque le programme commence à sortir de la boucle, tandis que les non-factorielles restent bloquées dans la boucle jusqu'à ce que Retina lève une exception OverflowException causée par l'échec du dernier remplacement, le fond étant donc unaire au lieu de décimal et le premier remplacement de la boucle. convertit la ligne de fond de décimale à unaire, de sorte qu'elle explose rapidement.


Enregistrez un octet en supprimant le 1car cela est impliqué quand $*est à la fin du remplacement.
Neil

Mieux encore, combinez le $*avec les deux autres lignes.
Neil


3
Je suis impressionné que vous ayez trouvé un moyen de bloquer la rétine de manière conditionnelle. :)
Martin Ender

2
Pouvez-vous ajouter une explication?
CalculatorFeline

8

05AB1E , 4 octets

L!QO

Essayez-le en ligne!

Explication

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

1
N'auriez-vous pas besoin de dupliquer l'entrée en premier parce que Lapparaît son entrée? En outre, Å!vous donne une liste de factorielle inférieure ou égale à l'entrée.
Neil A.

@ NeilA. Heureusement, l'entrée est réapparue s'il n'y a pas assez d'arguments sur la pile pour une opération, donc je n'en ai pas besoin Dici. Bonne prise à propos de Å!. J'oublie toujours les listes de commandes. Cela ne sauvera pas les octets, mais c’est certainement plus efficace.
Emigna

Je ne savais pas que des entrées étaient à nouveau affichées, ce qui permettrait d'économiser beaucoup d'octets.
Neil A.

@ NeilA. C'est une fonctionnalité assez nouvelle. Il a été ajouté il y a moins d'un mois, je pense.
Emigna

8

C ++, 102 100 92 octets

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

Parcourt toutes les valeurs de 0à net calcule la factorielle, puis vérifie si elle est égale àn .

Merci Christoph! (enregistré 8 octets)


Salut! Bienvenue chez PPCG! Belle première réponse! Bonne chance pour la suite!
Arjun

Belle première réponse! Vous pouvez enregistrer quelques octets comme ceci: int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}. lroundet lgammasont déjà C ++ 11 donc pourrait simplement #include<cmath>. Peut-être pourrez-vous encore améliorer mes suggestions :)
Christoph

7

Haskell , 43 à 26 octets

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

Essayez-le en ligne!

  • 17 octets sauvés, merci à Laikoni

2
f n=elem n$scanl1(*)[1..n]est ridicule inefficace mais plus court.
Laikoni

N'y a-t-il pas une règle sur l'efficacité du code?
Samedi

1
Aucun que je sache. code-golf demande une solution en aussi peu d'octets que possible sans déclaration d'efficacité. La fonction fonctionne également 40430sans délai sur ma machine .
Laikoni

Je voulais dire quelque chose du genre "la solution devrait prendre fin dans un délai raisonnable", mais je suppose que cela répond aux exigences de toute façon. Merci!
Samedi

1
Sympa et simple. Je pensais que je pouvais faire mieux avec la division — disons, divModen [1..]atteignant successivement le zéro restant avec un quotient de 1 (factoriel) ou un reste non nul (non factoriel), mais cela ne semble pas être la bonne approche. J'ai trouvé ce mignon solution 46 caractères, bien que: f|let x%n=mod n x==0&&(x+1)%div n x||n==1=(1%).
Jon Purdy

6

Haskell , 38 octets

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

Essayez-le en ligne! Exemple d' utilisation: (2#) 24. Retours TrueouFalse .

C'est le plus court que j'ai pu obtenir tout en restant très efficace. Même pour des nombres aussi grands que

145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000

le résultat est immédiatement donné. La solution fonctionne en divisant l'entrée npar m = 2,3,4,5,...jusqu'à ce que le résultat soit égal à un ou qu'il nne soit pas divisible par m.

Pour la solution à 26 octets, plus courte mais incroyablement inefficace, qui calcule les n!entrées non factorielles, regardez ici .



5

Fourier , 40 39 octets

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

Essayez-le sur FourIDE!

En gros, multiplie le nombre N par un nombre croissant jusqu'à ce que N soit égal à (sortie 1) ou supérieur à (sortie 0) l'entrée.

Explication 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 octets

ol x¥U

Essayez-le en ligne!

Cette sortie 0 pour faux et 1 pour vrai.

Explication

 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
Je devrais vraiment ajouter un "contient" intégré: P
ETHproductions

1
Oh, hé, vous pouvez changer aU ¦Jen x¥U(mapper chaque Xsur X==Uet résumer), bien que cela ne fonctionne pas sur TIO.
ETHproductions

Échec pour 2becuase one vous donnera que [0,1]. Voici un correctif avec une sauvegarde de 1 octet.
Shaggy

4

Perl 5, 31 octets

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

L'entrée est prise via STDIN, la sortie est donnée par le code de sortie (1 pour factoriel, 0 pour non factoriel).

L'entrée est divisée par des entiers successifs jusqu'à ce que soit 1, soit une fraction inférieure à un, qui est tronquée dans le résultat.


-5 octets TIO
Nahuel Fouilleul

4

Perl 6 , 29 octets

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

Essaye-le

Étendu:

{   # 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 octets: {$_∈[\*] 1..$_}. Une autre approche intéressante est 2>*.polymod(1..*).sum.
Nwellnhof

4

setlX , 32 octets

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

Crée une fonction appelée foù vous utilisez votre factorielle potentielle comme paramètre.

Cela fonctionne avec une taille entière arbitraire, mais c'est assez inefficace.

(au fait: c'est ma première participation à un puzzle de programmation)




4

C # (.NET Core) , 68 octets

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

Essayez-le en ligne!

Pas la solution la plus courte, mais fonctionne avec de très gros nombres. Le lien TIO comprend un exemple avec10000! .

Voici une version plus courte qui utilise intqui a une valeur maximale de 2147483647 .

C # (.NET Core) , 45 octets

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

Essayez-le en ligne!

Nous remercions @KevinCruijssen pour avoir joué au golf 3 octets au total grâce aux deux réponses!


2
Le &&peut être joué au golf &, et la fuite ;ne doit pas être comptée pour les fonctions lambda. De plus, le message ne peut-il pas ulong k=2figurer uint k=2dans votre réponse sur 50 octets?
Kevin Cruijssen le

1
Bonne prise sur le &contre &&. Je pensais avoir un débordement de pile, mais cela semble fonctionner après tout. ulongest 64 bits tandis que uintest 32. Il semble que les autres utilisent, intalors je vais peut-être l'utiliser pour la version courte. En ce qui concerne la fin ;, ce sont des fonctions complètes, pas des lambdas, donc je pense avoir besoin de les inclure?
Dana

C'est vraiment étrange de voir comment .NET peut résoudre /et %entre ulonget uint, mais pas ulonget int. Je ne savais pas que :)
Dana

1
@Oliver - Avec doublevous commencez à voir arrondir à un moment donné - par exemple, 24! et 120! échouer. Alors que System.Numerics.BigIntegerle plus de précision, intest la réponse la plus courte :)
Dana

1
@Deadcode - Vous avez raison à propos de 0 :) D'après les exemples du défi, j'ai interprété "nombres naturels" comme signifiant 1,2, ... Je conviens que dans le monde réel, il est préférable d'utiliser l' &&opérateur de court-circuit . Mais c'est du code golf;) Content que l' 10000!exemple vous plaise !
Dana

4

C ++ (clang), 51 octets

La récursion l'emporte au golf.

51 octets, zéro est vrai:

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

Cela sacrifie beaucoup de vitesse pour 1 octet d'économie. Remplacez le |avec par ||pour le rendre rapide, en raison de l'évaluation du OU logique par court-circuit.

Essayez-le en ligne! (Version lente de 51 octets)
Essayez-le en ligne! (Version rapide de 52 octets)

Version lente non-golfée:

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);
}

Version rapide non-golfée:

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);
}

Il y a plusieurs façons de réorganiser cela.

52 octets, non nul est vrai:

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

Essayez-le en ligne!

52 octets, zéro est vrai:

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

Essayez-le en ligne!

Avant de recourir à la récursivité, j'ai essayé de créer des versions itératives, qui se sont rapprochées.

54 octets, non nul est vrai:

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

Essayez-le en ligne!

54 octets, zéro est vrai (d'après la soumission de Roman 8 par Roman Gräf ):

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

Essayez-le en ligne!

Maintenant, pour le fond du baril, des versions récursives sans n==0manipulation (je les considère comme non valides, car 0 est un nombre naturel, et toute définition dans laquelle elle ne correspond pas à des "nombres naturels" d'utilisation très limitée). Dans les versions ci-dessous, la récursion infinie de l'une f(0)ou de l' autre déclenche une erreur de segmentation due au débordement de la pile, ou des compilateurs qui l'optimisent en itération, boucle en boucle:

48 octets, zéro est vrai:

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

Essayez-le en ligne!

48 octets, zéro est vrai (d'après la soumission de 33 octets C (gcc) de Hagen von Eitzen ):

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

Essayez-le en ligne!


50 EDIT: 49 , sans récursivité.
Grimmy

Retour en récurrence pour 48 . Et vous n'allez probablement pas aimer ça, mais 44 en utilisant une variable globale.
Grimmy

3

Mathematica, 20 octets

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

autre version pour tester les gros nombres (voir commentaires)

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

teste jusqu'à 1000!


2
Si je comprends bien la question, si Mathematica est capable de prendre 1001! en entrée, cela ne correspond pas à la spécification.
Peter Taylor

2
Vous pouvez même économiser trois octets en le rendant valide pour toutes les entrées. Il suffit de remplacer 10 ^ 3 par #; vous pouvez économiser un autre octet en utilisant Range @ #
Julien Kluge

@Julien Klugethen à la recherche de 1243234 prendrait une éternité ...
J42161217

1
Je pense que vous pouvez économiser un autre octet en remplaçant Range[#]par Range@#:)
numbermaniac

3
On dirait que vous pouvez enregistrer un autre octet avec la syntaxe infixe: !Range@#!~FreeQ~#&.
numbermaniac

3

Cubix , 24 octets

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

Essayez-le en ligne

Cubifié

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

Nous commençons par pousser 1, Input, 1sur la pile. Ce seront notre index, notre cible et notre accumulateur, respectivement.

Nous faisons alors une boucle. A chaque itération, on soustrait l'accumulateur de l'entrée. Si le résultat est 0, nous avons terminé, alors nous poussons 1, Output et quittons. Si c'est négatif, nous sommes allés trop loin, alors nous poussons 0, Outputons, et sortons. Sinon, on voit

;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 octets

𝐈Γ𝐈𝐩₁𝔼)𝐠

Explication:

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]

Essayez le!

Neim , 3 octets (non concurrents)

Les jetons Contenus et Factionnaires non compétitifs ont été ajoutés après le lancement du défi.

𝐈𝐓𝕚

Explication:

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]

Essayez le!


3

> <> , 24 22 octets

-2 octets grâce à @Aaron

J'essaie une nouvelle langue (depuis l'expiration de ma licence Mathematica…)

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

Essayez-le en ligne ou au terrain de jeu du poisson

Suppose que le numéro d'entrée est déjà sur la pile et renvoie 0 ou 1. Cela fonctionne en multipliant ensemble les n premiers nombres jusqu'à ce que celui-ci cesse d'être inférieur à l'entrée, puis en imprimant 1 s'il est égal à l'entrée et 0 s'il ne le fait pas. t.


Vous pourriez vous transformer v>\n<^en \\n/; voir ici
Aaron

@ Aaron, c'est génial, merci!
Pas un arbre

3

APL (Dyalog Unicode) , 5 6 7 octets

Golfé un octet en changeant ×/pour !grâce à Erik the Outgolfer

⊢∊!∘⍳

Essayez-le en ligne!

Explication

                          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?

Somme Cumulative?
Leaky Nun

@LeakyNun Fixe
Kritixi Lithos

Un octet supplémentaire dans GNU APL 1.2 N∊×\⍳N←⎕Comment cela prend-il un argument? Je ne vois nnulle part. Est-ce une chose spécifique à Dyalog?
Arc676

2
@ Arc676 Ma solution est un train et vous l'appelez ainsi: (⊢∊(×/⍳)) right_argumentcomme vous pouvez le voir sur le lien TIO. Et le fait référence au bon argument.
Kritixi Lithos

Remarques: AGL vous fera économiser un octet; ⊢∊×\ä⍳. La solution "correcte" (mais plus longue) serait 0=1|!⍣¯1: "La factorielle inverse est-elle un entier?"
Adám

2

JavaScript (ES6), 71 octets

Cela prend en entrée comme argument de fonction et en alertsortie. Sorties 0pour Falsey et 1pour la vérité.

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

Explication

Le programme comprend deux fonctions fet g. fest une fonction récursive de calcul factoriel et gconstitue la fonction principale du programme. g suppose d'avoir un seul argument n. Il définit un argument par défaut ravec une valeur de 0 et un autre argument par défaut avec une valeur de 0. Il effectue ensuite une itération sur tous les entiers de 0 à net vérifie, à chaque itération, si la fonction fappliquée sur i(l'indice actuel) est égale n, c'est-à-dire s'il ns'agit d'une factorielle de i. Si tel est le cas, rla valeur de s est définie sur 1. À la fin de la fonction, rest alertéd.

Test Snippet

( Remarque: les extraits de code n'utilisent console.log()comme autant de personnes que trop de ces satanés alert()s. )

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 peut être plus court que d'utiliser un bloc de code.
Downgoat

@Downgoat Comment dois-je faire cela? Désolé si c'est trop évident! : P
Arjun

2

QBIC , 21 19 octets

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

Explication

[:|     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

Précédemment

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

Explication:

[:|         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 octets

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)
        );
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.