Les nombres sous - factoriels ou rencontres ( A000166 ) sont une séquence de nombres similaires aux nombres factoriels qui apparaissent dans la combinatoire des permutations. En particulier, le n ième sous-factoriel ! N donne le nombre de dérangements d'un ensemble de n éléments. Un dérangement est une permutation dans laquelle aucun élément ne reste dans la même position. La sous-factorielle peut être définie via la relation de récurrence suivante:
!n = (n-1) (!(n-1) + !(n-2))
En fait, la même relation de récurrence vaut pour la factorielle, mais pour la sous-factorielle, nous partons de:
!0 = 1
!1 = 0
(Pour la factorielle, nous aurions, bien sûr, 1! = 1. )
Votre tâche consiste à calculer ! N , étant donné n .
Règles
Comme le factoriel, le sous-factoriel croît très rapidement. C'est bien si votre programme ne peut gérer que les entrées n de telle sorte que ! N puisse être représenté par le type de numéro natif de votre langue. Cependant, votre algorithme doit en théorie fonctionner pour n arbitraire . Cela signifie que vous pouvez supposer que les résultats intégraux et la valeur intermédiaire peuvent être représentés exactement par votre langue. Notez que cela exclut la constante e si elle est stockée ou calculée avec une précision finie.
Le résultat doit être un entier exact (en particulier, vous ne pouvez pas approximer le résultat avec une notation scientifique).
Vous pouvez écrire un programme ou une fonction et utiliser l'une des méthodes standard de réception d'entrée et de sortie.
Vous pouvez utiliser n'importe quel langage de programmation , mais notez que ces failles sont interdites par défaut.
Il s'agit de code-golf , donc la réponse valide la plus courte - mesurée en octets - l'emporte.
Cas de test
n !n
0 1
1 0
2 1
3 2
4 9
5 44
6 265
10 1334961
12 176214841
13 2290792932
14 32071101049
20 895014631192902121
21 18795307255050944540
100 34332795984163804765195977526776142032365783805375784983543400282685180793327632432791396429850988990237345920155783984828001486412574060553756854137069878601
la source
Réponses:
Funciton , 336 octets
Le nombre d'octets suppose un codage UTF-16 avec BOM.
Ceci définit une fonction
f
qui prend un entier et sort un autre entier à un virage de 90 degrés vers la gauche. Il fonctionne pour des entrées arbitrairement grandes.Essayez-le en ligne!
Étant donné que c'est Funciton, il est même assez rapide (n = 20 prend environ 14 secondes sur TIO). Le principal ralentissement vient de la double récursivité, car je ne pense pas que l'interpréteur Funciton mémorise automatiquement les fonctions.
Malheureusement, certaines polices à espacement fixe n'espacent pas correctement
♭
et / ou n'insèrent pas de petits espaces entre les lignes. Voici une capture d'écran du code de TIO dans toute sa beauté:Je pense qu'il pourrait être possible de golf ce un peu plus, par exemple en changeant la condition de
>0
la<1
et échangeant les branches du conditionnel, afin que je puisse réutiliser le littéral, ou peut - être en utilisant une formule complètement différente, mais je suis tout à fait satisfait de sa compacité.Explication
Cela implémente essentiellement la récursivité donnée dans le défi, bien qu'il utilise le cas de base ! (- 1) =! 0 = 1 . n-1 et n-2 sont calculés avec la fonction prédécesseur
♭
, et le résultat intermédiaire n-1 est réutilisé à trois endroits. Il n'y a pas grand-chose d'autre, donc je vais rapidement passer en revue le flux de contrôle:Il s'agit de l'en-tête de fonction qui émet l'entrée de la fonction n le long de la ligne attachée. Cela atteint immédiatement la jonction en T, qui duplique simplement la valeur.
La
0
case n'est qu'un littéral numérique. Une jonction à 4 voies calcule deux fonctions: le chemin qui part du bas calcule 0 <n , que nous utiliserons pour déterminer le cas de base. Le chemin qui part à gauche calcule 0 << n (un décalage à gauche), mais nous rejetons cette valeur avec la construction de Starkov .Nous menons cela dans le conditionnel à trois voies
?
. Si la valeur est fausse, nous retournons le résultat constant1
. L'extrémité libre à droite de?
est la sortie de fonction. Je le tord de 180 degrés ici, de sorte que l'orientation relative de l'entrée et de la sortie def
soit plus pratique dans le reste du programme.Si la condition était vraie, l'autre valeur sera utilisée. Regardons le chemin qui mène à cette branche. (Notez que l'évaluation de Funciton est en fait paresseuse de sorte que cette branche ne sera jamais évaluée si elle n'est pas nécessaire, ce qui rend la récursion possible en premier lieu.)
Dans l'autre branche, nous calculons d'abord n-1 , puis divisons le chemin deux fois afin d'obtenir trois copies de la valeur (une pour le coefficient de récurrence, une pour la première sous-factorielle, la dernière pour n-2 ).
Comme je l'ai dit, nous décrémentons à nouveau une copie avec une autre
♭
, puis nous alimentons récursivement n-1 et n-2 pourf
finalement ajouter les deux résultats ensemble dans le+
.Il ne reste plus qu'à multiplier n-1 par ! (N-1) +! (N-2) .
la source
Oasis , 5 octets
Utilise la formule donnée par Martin. Code:
Version disséquée:
avec
a(0) = 1
eta(1) = 0
.Explication,
a(n) =
:Essayez-le en ligne!
la source
X
:-) BTW, avez-vous déjà implémenté cela ? Un de ces jours, nous ne pourrons pas nous en sortir en changeant simplement les valeurs initialesHaskell , 25 octets
Essayez-le en ligne! Utilise l'autre récurrence de la page OEIS .
la source
Gelée , 7 octets
Cette approche construit les dérangements, donc c'est plutôt lent.
Essayez-le en ligne!
Comment ça marche
la source
Brachylog (2), 11 octets
Essayez-le en ligne!
Explication
Il s'agit essentiellement d'une traduction directe de la spécification de l'anglais vers Brachylog (et présente donc l'avantage de pouvoir être facilement modifiée pour gérer de petites modifications de la spécification, telles que la recherche du nombre de dérangements d'une liste spécifique).
la source
Langues avec solutions intégrées
Suivant la suggestion de xnor, il s'agit d'une réponse CW dans laquelle des solutions triviales basées sur un seul intégré pour calculer la sous-factorielle ou générer tous les dérangements doivent être éditées.
Mathematica, 12 octets
la source
Python 3 ,
3532 octetsCela utilise la relation de récurrence ! N = n! (N-1) + (-1) n de la réponse Haskell de @ Laikoni , avec le cas de base ! 0 = 1 .
Essayez-le en ligne!
la source
f=lambda n:n<1or n*f(n-1)+(-1)**n
.n=-1
, peu importe la valeur que vous utilisez. Cela pourrait être utile pour certaines langues (par exemple, dans Mathematica, vous pourriez en fait ne pas le définir si cela a sauvé des octets).M , 9 octets
Comme vous pouvez le voir en supprimant le
Ḟ
, M utilise des mathématiques symboliques, il n'y aura donc aucun problème de précision.Essayez-le en ligne! Pas la solution la plus courte qui ait été publiée, mais rapide .
Comment ça marche
la source
MATL ,
98 octetsDe la même manière que la réponse Jelly de @Dennis , cela construit en fait les permutations et compte combien d'entre elles sont des dérangements; c'est donc lent.
Essayez-le en ligne!
la source
Mathématiques , 21 octets
Je suis très nouveau dans ce domaine et je n'ai aucune idée de ce que je fais ...
Essayez-le en ligne!
la source
Round[(#/. 0->2)!/E]&
et±0=1;±n_:=Round[n!/E]
(même si je ne sais pas si Mathics prend en charge les encodages à un octet pour les fichiers source comme Mathematica).±
en charge le second. Cela fonctionnerait avecf
, mais au prix de deux octets.Round[#!/E]+1-Sign@#&
. Des valeurs initiales ennuyeuses ...!Rubis, 27 octets
~0**n
est plus court que(-1)**n
!la source
CJam (10 octets)
Démo en ligne .
Cela utilise la récurrence
!n = n !(n-1) + (-1)^n
, dont j'ai dérivén! / e
puis découvert que c'était déjà dans OEIS.Dissection
La boucle calcule
(-1)^n !n
, nous devons donc prendre la valeur absolue à la fin:la source
05AB1E , 8 octets
Essayez-le en ligne!
Explication
la source
MATLAB, 33 octets
Fonction Anonympus qui utilise la formule de la section 3 des Dérangements et applications de Mehdi Hassani.
Exemple d'utilisation:
la source
JavaScript (ES6), 26 octets
Utilise la relation de récurrence de la réponse de @ Laikoni. Dans ES7, vous pouvez enregistrer un octet en utilisant
+(-1)**n
au lieu de-(~n%2|1)
.la source
PostScript,
817669 octetsVoici les implémentations des deux formules.
n * f (n-1) + (- 1) ^ n
/ f {dup 0 eq {pop 1} {dup dup 1 sub f mul exch 2 mod 2 mul 1 sub sub} ifelse} defCette version génère un flottant. S'il est nécessaire de sortir un entier:
qui pèse 73 octets.
L'autre formule est un peu plus longue: 81 octets.
(n-1) * (f (n-1) + f (n-2))
Ces fonctions obtiennent leur argument de la pile et laissent le résultat sur la pile.
Vous pouvez tester les fonctions, soit dans un fichier soit à une invite PostScript interactive (par exemple GhostScript) avec
sortie
Voici un fichier PostScript complet qui rend la sortie à l'écran ou sur une page d'imprimante. (Les commentaires dans PostScript commencent par
%
).la source
-1 3 2 roll exp
est un peu plus court queexch 2 mod 2 mul 1 sub
.exp
: oops: Cependant, il renvoie un flottant, et je pense que je dois sortir un entier pour se conformer à la question.cvi
et faire des économies. (Remarque: non testé, mais à la lecture du document, je pense que cela devrait fonctionner).cvi
ça marche, et c'est toujours plus court que ma version précédente.PHP, 69 octets
utiliser de cette façon
a(n) = n*a(n-1) + (-1)^n
la source
PHP,
5044Courir avec
echo <n> | php -nR '<code>
La beauté de
a(n) = n*a(n-1) + (-1)^n
c'est que cela ne dépend que de la valeur précédente. Cela lui permet d'être implémenté de manière itérative plutôt que récursive. Cela enregistre une longue fonction déclaration de .-6 octets par @Titus. Merci !
la source
$i++<$argv[1]
. -2 Octetsfor(;$i++<$argv[1];)$n=++$n*$i-$i%2*2;echo$n+1;
. (-3 octets avec-R
et$argn
.)-R
et$argn
?Mathematica, 40 octets
Ce qui arrive à 31 octets sous l'encodage ISO 8859-1 par défaut.
la source
C, 34 octets
Explication:
la source
R, 47 octets
Utilise la même formule que la réponse de Mego .
Méthode alternative, 52 octets utilisant la
PerMallows
bibliothèquela source
En fait , 18 octets
Essayez-le en ligne!
Explication:
Une version de 12 octets qui fonctionnerait si en fait avait plus de précision:
Essayez-le en ligne!
Contrairement à toutes les autres réponses (au moment de la publication), cette solution n'utilise ni la formule récursive ni la formule de sommation. Au lieu de cela, il utilise la formule suivante:
Cette formule est relativement facile à mettre en œuvre en fait:
Maintenant, le seul problème est que la formule ne vaut que pour le positif
n
. Si vous essayez d'utilisern = 0
, la formule donne incorrectement0
. Ceci est facilement corrigé, cependant: en appliquant la négation booléenne à l'entrée et en ajoutant qu'à la sortie de la formule, la sortie correcte est donnée pour tous les non négatifsn
. Ainsi, le programme avec cette correction est:la source
n = 100
),(-1)**n/n!
ne peut pas être représenté avec des flottants IEEE 754 à double précision. C'est acceptable selon le défi.n=4
...Empilé , 30 octets
Essayez-le en ligne!
Fonction récursive simple. Utilise le fait que
!n = not n
pourn < 2
. Appelez len f
.la source
Alice ,
2018 octetsEssayez-le en ligne!
Explication
Celui - ci utilise la récursion de réponse de Laikoni , ! N = n! (N-1) + (-1) n . Semblable à la réponse de Funciton, j'utilise le cas de base ! (- 1) = 1 . Nous avons mis ce 1 sur la pile avec
1.
. Ensuite ceci...... est juste le cadre d'E / S décimal habituel. Le code principal est en fait
En panne:
la source