Convertir vers et depuis le système numérique factoriel


27

Le système de nombres factoriels , également appelé factoradique, est un système de nombres mixtes radix. Les factorielles déterminent la valeur de position d'un nombre.

Dans ce système, le chiffre le plus à droite peut être 0 ou 1, le deuxième chiffre le plus à droite peut être 0, 1 ou 2, etc. Cela signifie qu'un nnombre factoriel numérique peut avoir une valeur maximale de (n + 1)!.

Par exemple, pour convertir le nombre factoriel 24201en décimal, vous feriez ceci:

2 * 5! = 240
4 * 4! = 96
2 * 3! = 12
0 * 2! = 0
1 * 1! = 1
240 + 96 + 12 + 0 + 1 = 349

Par conséquent, le nombre factoriel 24201est de 349base 10.

Pour convertir un nombre décimal (avec 349comme exemple) en nombre factoriel, vous feriez ceci:

Prenez la plus grande factorielle inférieure au nombre. Dans ce cas, c'est le cas 120, ou 5!.

349 / 5! = 2 r 109
109 / 4! = 4 r 13
13 / 3! = 2 r 1
1 / 2! = 0 r 1
1 / 1! = 1 r 0

La 349base 10est donc le nombre factoriel 24201.

Votre défi consiste à créer le programme ou la fonction la plus courte qui convertit un numéro d'entrée dans l'autre base.

L'entrée sera une représentation sous forme de chaîne d'un entier non négatif. Un nombre factoriel sera précédé d'un !(par exemple !24201), tandis qu'un nombre décimal ne sera précédé de rien. Vous pouvez supposer que l'entrée maximale sera 10! - 1- 3628799en décimal et 987654321en factoradique. Cela signifie que les lettres n'apparaîtront pas dans une entrée / sortie factorielle.

Le programme n'a pas besoin d'ajouter un !à une sortie factorielle et peut sortir une chaîne ou un entier. L'entrée peut être dans n'importe quel format raisonnable.


Cas de test:

Input: 1234
Output: 141120

Input: 746
Output: 101010

Input: !54321
Output: 719

Input: !30311
Output: 381

Réponses:


10

APL, 39 37 caractères

{A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}

Exemples:

      {A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}'1234'
141120
      {A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}'!54321'
719

1
Je pense que vous pouvez remplacer ⍴⍵∩'!'par '!'∊⍵pour enregistrer un personnage.
Volatilité

@Volatility Oui, vous le pouvez. J'en ai aussi trouvé un autre.
Howard

11
IMO ayant le mot "pwn" dans votre script vaut bien le caractère supplémentaire.
ejrb

1
Je suis d'accord avec ejrb. Pourriez-vous décomposer cela s'il vous plaît?
Titus

1
Remplacez ~'!'par ∩⎕Dpour enregistrer un caractère.
Adám

9

Python 2.7 ( 163 157 152)

i=raw_input()
exec("b='';a=362880;j=int(i);x=9;"+'b+=`j//a`;j%=a;a/=x;x-=1;'*9,"a=x=1;b=0;"+'b+=a*int(i[-x]);x+=1;a*=x;'*~-len(i))['!'in i]
print int(b)

Version plus lisible:

i=raw_input()
if'!'in i:a=x=1;b=0;c='b+=a*int(i[-x]);x+=1;a*=x;'*~-len(i)
else:b='';a=362880;j=int(i);x=9;c='b+=`j//a`;j%=a;a/=x;x-=1;'*9
exec c;print int(b)

Panne:

Factoradic -> Decimal, when i is in the form !(number)
a=1   #Factorial value (multiplied every iteration)
x=1   #Index value
b=0   #Output
iterate ~-len(i) times:    #PSEUDOCODE! bitwisenot(a) = ~a = -a-1
    b+=a*int(i[-x])        #add the value of the xth last character in the factoradic #
    x+=1                   #Increment x
    a*=x                   #Set a to x!, (x-1)! * x = x!

Decimal -> Factoradic
b=''                       #Output
a=362880                   #Factorial value, set to 9! here
j=int(i)                   #Integer value of the input
x=9                        #Index value
iterate 9 times:           #PSEUDOCODE! This block is in an exec() loop
    b+=`j/a`               #Add floor(j/a) to b
    j%=a                   #Take out all multiples of a in j
    a/=x                   #Set a to (x-1)!, x! / x = (x-1)!
    x-=1                   #Decrement x

1
Belle solution. Je pense que vous pouvez remplacer '!'==i[0]avec '!'in i, et peut utiliser a=x=1. De plus, vous n'avez pas besoin de crochets autour de l'instruction exec.
grc

1
Vous pouvez également remplacer (len(i)-1)par ~-len(i).
Volatilité

@Volatility, grc: Merci! Je devrais apprendre mes opérateurs au niveau du bit :)
beary605

1
Belle réponse, j'ai pris la liberté d'essayer de remplacer l'instruction if par (a,b)['!'in i]et j'ai réussi à raser 6 caractères. Ce n'est pas aussi lisible que par le
passé

@erjb: Merci pour la suggestion! J'ai utilisé un tuple 2 avec le code en tant que chaîne en ligne avec la fonction exec, qui enregistre deux autres caractères :)
beary605

8

GolfScript ( 48 44 43 caractères)

.~\{1{):?\.?%\?/@}9*{*+}+9*}:^{:N,{^N=}?}if

Il s'agit d'un programme autonome. La conversion factoriadique => décimale est assez lente, car elle effectue une recherche en utilisant la conversion décimale => factoriadique plutôt qu'une conversion de base directe.

Le format d'entrée permet un changement de mode très court: .~copie la chaîne d'entrée et l'évalue, donc si l'entrée n'est qu'un nombre, nous nous retrouvons par exemple "1234" 1234sur la pile, et si elle commence par !(logique non, avec aucune non vide chaîne étant véridique) on se retrouve par exemple 0 30311sur la pile. Ensuite, la valeur au bas de la pile est véridique pour décimal => factoriadique et fausse pour factoriadic => décimal.


4

PHP <7,1 178 171 170 168 164 155 155 147 144 138 126 123 123 octets

for($b=$j=1,$i=strlen($x=$argn);+$x?$b<=$x:--$i;$b*=++$j)$r+=$x[$i]*$b;if(+$x)for(;$j>1;$x%=$b)$r.=$x/($b/=$j--)|0;echo+$r;

Exécuter en tant que pipe avec -rou tester en ligne .

  • aucune extension requise
  • aucune sous- fonction nécessaire: la base factorielle est réutilisée (incrémentée / diminuée dans les boucles)
  • arithmétique pure et entière, devrait même fonctionner en php 3 (et fonctionne toujours en php 7):
  • décimal 0 renvoie une chaîne vide au lieu de 0. (les deux autres réponses PHP le font aussi.) Si cela est inacceptable, ajoutez +5 pour le cas supplémentaire.

non golfé:

// two loops in one: compute the decimal number from a factorial
// or find the first factorial larger than a decimal $x
// the latter inits $r with '0': $i=strlen -> $x[$i]=='' -> (int)$x[$i]==$x[$i]*$b==0
// $b is the current digit´s base; $j is the bases´ latest factor
for($b=$j=1,$i=strlen($x=$argn);+$x?$b<=$x:--$i;$b*=++$j)
    $r+=$x[$i]*$b;
// and now for dec->fact ...
if(+$x)
    for(;$j>1;$x%=$b)
        // both $b and $j are one step too far in the first iteration;
        // -> decrement must precede the actual loop body
        // -> can be merged into the digit calculation -> all braces golfed
        $r.=$x/($b/=$j--)|0;
        // now: go on with the remainder (see loop head)
echo+$r; // final type cast removes leading zeros (from the first loop)
    // and fixes the '0' result (no operations at all on that input!)

idées de golf abandonnées:

  • $b<=$x-> $b<$x(-1)
    casserait les factorielles décimales pures (c'est-à-dire celles qui donnent un nombre factoriel avec un seul chiffre non nul). La solution de JMPC en souffre; HamZa´s ne le fait pas.
  • floor($x/$b)-> (int)($x/$b)
    pourrait être un peu plus rapide, mais la conversion de type précède la division, j'ai donc besoin des parenthèses et je ne gagne pas un octet.
    $x/$b|0fait l'affaire
  • La boucle en fait-> dec est similaire à la recherche factorielle en dec-> fact. Même incrément, le corps n'a pas d'importance, mais malheureusement un preset différent et une post-condition différente. Dang; aurait pu y jouer au golf -21.
    YAY j'ai trouvé une solution. A pris un peu de golf, mais a coupé un autre -4 (non: -9) et a fermé tous les bugs / échappatoires.

Plus de potentiel ... ou ai-je fini de jouer au golf?


@ JörgHülsermann Merci pour cet indice.
Titus

1
+$rau lieu d' $r|0enregistrer un octet. Pareil pourif($x|0)
Jörg Hülsermann

3

JavaScript (ES 6) 139 137 122 113 111

essayé une approche différente en utilisant un peu de magie de tableau; mais je me suis retrouvé à 174 172 octets avec ça:

f=x=>{if('!'==x[0]){a=x.split``.reverse();i=b=1;r=0;a.pop();a.map(d=>{r+=d*b;b*=++i})}else{t=[];for(i=b=1;b<=x;b*=++i){t.unshift(b)}r='';t.map(b=>{r+=x/b|0;x%=b})}return r}

J'ai donc pris mon code PHP et l'ai traduit. Pourrait supprimer tous les $s et quelques-uns ;, mais la nécessité d'initialiser les vars a absorbé une partie de cet avantage. Géré au golf les deux réponses un peu plus loin, cependant.

golfé

f=x=>{for(r=0,b=j=1,i=x.length;x|0?b<=x:--i;b*=++j)r+=x[i]*b;if(x|0)for(r='';j>1;x%=b)r+=x/(b/=j--)|0;return r}
  • la première version renvoie '' pour 0 décimal; ajouter +2 pour corriger
  • la deuxième version nécessite une entrée de chaîne
  • tous deux testés dans Firefox, Edge et Opera

non golfé

f=x=>
{
    for(r=0,b=j=1,i=x.length;x|0?b<=x:--i;b*=++j)
        r+=x[i]*b;
    if(x|0)
        for(r='';j>1;x%=b)
            r+=x/(b/=j--)|0;
    return r
}

suite de tests

<table id=out border=1><tr><th>dec</th><th>result<th>expected</th><th>ok?</th></tr></table>
<script>
    addR=(r,s)=>{var d=document.createElement('td');d.appendChild(document.createTextNode(s));r.appendChild(d)}
    test=(x,e)=>{var y=f(x),r=document.createElement('tr');addR(r,x);addR(r,y);addR(r,e);addR(r,e==y?'Y':'N');document.getElementById('out').appendChild(r)}
    samples={'349':'24201','1234':'141120','746':'101010','719':'54321','381':'30311','24':'1000','0':'0'};
    for(d in samples){test(d,samples[d]);test('!'+samples[d],d)}
</script>

1
ES5 n'a pas la notation de flèche IIRC. Et si vous allez utiliser ES6, alors .split('')=>.split``
Zacharý

@ Zacharý Gna J'aurais dû noter dans quel navigateur je l'ai testé ... probablement Firefox ou Opera. Alors ES 6?
Titus

Oui, la notation des flèches est ES6.
Zacharý

1
Oh, cela m'a pris au dépourvu, je pensais que le bloc de code en haut était votre solution! Quoi qu'il en soit, je ne pense pas que vous ayez besoin de le dire f=. Peut- r+=(x/(b/=j--)|0)être aussi r+=x/(b/=j--)|0?
Zacharý


1

GolfScript, 69 caractères

10,1>{1$*}*](.0=33={1>01/-1%0\{~@(@*@+}/\}{~\-1%{1$<},{1$1$/@@%}/}if;

Prend l'entrée de STDIN comme d'habitude et imprime le résultat. Test en ligne .


1

Haskell, 221 caractères

Code Golf

m v@(a:b)|a=='!'=(sum.zipWith(*)g.map(read.(:[])).reverse) b|True=(fst.until((<0).fst.snd)(\(s,(i,b))->(s*10+b`quot`f i,(i-1,b`rem`f i))).(\n->(0,((1+).last.takeWhile((n>=).f)$[1..], n))).read) v;g=scanl1(*)[1..];f=(g!!)

Usage

$ ghci factorial.hs
ghci> m "1234"
 141120
ghci> m "!54321"
 719

Code non golfé

parse v@(a:b) | a == '!' = to b
              | otherwise = from v

to = sum . zipWith (*) factorials . map (read . (:[])) . reverse

from = fst . until finished next . boostrap . read
    where finished = ((<0) . fst . snd)
          next (s,(i,r)) = (s * 10 + r `quot` factorial i, (i-1 ,r `rem` factorial i))
          bootstrap n = (0, (lastFact n, n))
          lastFact n = (1+) . last . takeWhile ((n>=) . factorial) $ [1..]

factorials = scanl1 (*) [1..]

factorial = (factorials!!)

De loin l'entrée la plus lisible. Haskell FTW!
Soham Chowdhury

1

Mathematica 213 177 175

Un nombre factoriel est encapsulé f[], qu'il s'agisse d'une entrée ou d'une sortie.

g@{n_,j_,r_}:=If[j==0,FromDigits@r,g@{q=QuotientRemainder[n,j!];q[[2]],j-1,Append[r,q[[1]]]}]
z@n_:=If[!IntegerQ@n, g[{n[[1]],9,{}}], f@Tr@(p=1;# (p++)!&/@Reverse@IntegerDigits@n)]

Usage

z[24201]

f [349]

z[f[349]]

24201

Conversion du nombre factoriel en nombre décimal . QuotientRemainder[n,j!]agit récursivement sur les chiffres du nombre factoriel de gauche à droite, décrémentant jà chaque pas. QuotientRemainder[349, 5!], par exemple, renvoie {2, 109}et ainsi de suite.

Conversion du nombre décimal en nombre factoriel . De droite à gauche, la fonction pure # (p++)! &, multiplie chaque chiffre #, par la factorielle appropriée.


1

Python, 128 caractères

Cela prend environ une demi-heure pour fonctionner, mais c'est petit:

A=[`x`for x in xrange(10**9)if all(x/10**d%10<d+2 for d in range(9))]
i=raw_input()
print A.index(i[1:])if'!'in i else A[int(i)]

Il construit une liste de tous les nombres factoriels <= 9 chiffres dans l'ordre numérique, puis effectue une recherche ou un index à convertir.

Si vous voulez tester, remplacez simplement 10**9par 10**6et limitez-vous aux nombres variadiques à 6 chiffres.

Je pourrais techniquement enregistrer un personnage en utilisant range(10**9)au lieu de xrange(10**9). N'essayez pas ca a la maison.


Aucun espace n'est nécessaire entre d+2etfor
Zacharý

1

PHP 231 214 204

Réponse la plus récente

function g($x){return $x?$x*g($x-1):1;}function f($x,$e){if($x[0]=="!"){for($t=1;$t<$c=strlen($x);$t++){$e+=$x[$t]*g($c-$t);}}else{while(g(++$p)<=$x);while(--$p){$e.=floor($x/g($p));$x%=g($p);}}return$e;}

Ancienne réponse

 function f($n){if($n[0]=="!"){$n=str_split($n);$c=count($n);$f=$y=1;while($c-->1){$e+=($f*$n[$c]);$f*=++$y;}return$e;}else{for($i=$c=1;$i<$n;$i*=$c){$r[$c++]=$i;}foreach(array_reverse($r)as$t){$e.=floor($n/$t);$n=$n%$t;}return$e;}}

Exemple

echo f('349')."\n"
    .f('!24201')."\n"
    .f('1234')."\n"
    .f('746')."\n"
    .f('!54321')."\n"
    .f('!30311');

Sortie

24201
349
141120
101010
719
381

2
Je compte 212 pour la nouvelle réponse, pas 214. $ e n'a pas besoin d'initialisation (-6) et foreach(range())peut être remplacé par une simple forboucle (-9). J'aime bien l'idée.
Titus

2
mauvais résultat pour les factorielles pures. 24devrait revenir 1000mais revient 400. Correction: g(++$p)<$x-> g(++$p)<=$x(+1)
Titus

@Titus Merci pour vos deux réponses! J'ai mis à jour ma réponse. J'apprécie que vous m'aidiez à améliorer ma réponse lorsque la vôtre semble de loin supérieure.
JPMC

1
1) Je compte 2 de moins que vous, encore une fois: 204, pas 206. Incluez-vous un saut de ligne Windows dans votre nombre d'octets? 2) erreur de syntaxe dans la forconstruction: ,devrait être ;3) J'ai encore 7 changements en économisant 20 octets sur ce code. Je les veux?
Titus

2
Eh bien, il ne s'agit en fait que de 5 changements, mais l'un d'eux comporte trois parties. a) deuxième argument obsolète pour f () (-3) b) blanc obsolète dans la fonction g (-1) c) accolades obsolètes dans la vraie branche (-4) d) permutez les vraies et les fausses branches, inversez la ifcondition, puis utilisez mon type sexy cast en int (-6) Cela n'affectera pas le résultat décimal 0! e) la forconstruction restante peut être réécrite avec une très belle while(++$t<$c=strlen($x)): incrémentation avant body -> $ t n'a pas besoin d'initialisation (-6)
Titus

1

JELLY, 5 octets

Æ!ŒṘ€

Explication

Æ!ŒṘ€
Æ!     -Convert to factoriadic (list form)
  ŒṘ€  -Construct string

* Jelly est plus jeune que l'âge de la question donc ma réponse est non compétitive.


1
Bienvenue chez PPCG! Je pense que Jelly est plus jeune que ce défi, vous devez donc marquer votre réponse comme non compétitive.
Laikoni

Oh, je ne savais pas que c'était une règle. Ça ira.
DaggerOfMesogrecia

Les réponses à ce défi ne sont-elles pas censées fonctionner dans les deux sens? Cela ne semble fonctionner que dans un sens; vous voudrez peut-être résoudre ce problème. (Sur une note distincte, si vous convertissez entre des entiers et des chaînes dans Jelly, il est généralement plus simple d'utiliser une combinaison de Vet .)

1

Gelée , 15 octets

ḊV€;0Æ¡µÆ!ṖḌƊ¬?

Essayez-le en ligne!

Comment ça marche

ḊV€;0Æ¡µÆ!ṖḌƊ¬?     Main link (monad). Input: integer or string
             ¬?  *) If the given input is a string, run 1); otherwise run 2)

ḊV€;0Æ¡  1) Factorial base -> integer
ḊV€         Remove "!" and map each char to number
   ;0       Append zero (this is needed to run the built-in correctly)
     Æ¡     Built-in conversion

Æ!ṖḌ  2) Integer -> factorial base
Æ!       Built-in conversion
  ṖḌ     Remove a zero at the end, and convert to decimal

Pourquoi *)fonctionne

¬est NON logique par élément. Lorsque donné un seul entier, il devient un simple zéro, ce qui est faux. Cependant, quand on lui donne une chaîne, chaque élément (caractère) est mis à zéro, et le résultat entier est un tableau de zéros qui est vrai.

Zéro comme entier est un cas particulier. Il passe par la route "factorielle -> entière", mais il donne toujours zéro qui est correct.

Sans base factorielle intégrée, 25 octets

⁵R!µ³%Ḋ:ṖUḌ
⁵R!ḋḊUV€ƊµÇ¬?

Essayez-le en ligne!

Comment ça marche

⁵R!µ³%Ḋ:ṖUḌ  Aux. link (monad). Integer -> factorial base
⁵R!µ         Set (1..10)! as left argument
    ³%Ḋ:Ṗ    Compute each digit: (input % (2..10)!) // (1..9)!
         UḌ  Reverse and convert the digit array to decimal

⁵R!ḋḊUV€ƊµÇ¬?  Main link (monad).
         怪?  If the input is a string, apply the left chain;
               otherwise, apply the aux. link above
⁵R!            (1..10)!
   ḋ           Dot product with...
    ḊUV€Ɗ      Remove "!", reverse, map each character to digit

0

K, 102

"I"$,/$*:'|:'{{(x-y*g),g:_(x:*x)%y:*/1+!y}\[x,0n;|1+!{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]]}

Pourrait certainement être amélioré.

k)"I"$,/$*:'|:'{{,[;g]x-y*g:_(x:*x)%y:*/1+!y}\[(x;0n);|1+!{{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]}x]} 349
24201
k)"I"$,/$*:'|:'{{,[;g]x-y*g:_(x:*x)%y:*/1+!y}\[(x;0n);|1+!{{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]}x]} 746
101010
k)"I"$,/$*:'|:'{{,[;g]x-y*g:_(x:*x)%y:*/1+!y}\[(x;0n);|1+!{{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]}x]} 1234
141120

0

D (159 caractères)

int x(string n){import std.conv;int r,i=9,f=9*'鶀',d;if(n[0]<48){while(r.text.x<n[1..$].to!int)r++;}else{d=n.to!int;while(i){r=r*10+d/f;d%=f;f/=i--;}}return r;}

Non golfé et avec point d'entrée de programme

Tous les arguments de ligne de commande sont imprimés en tant que <original> -> <converted>. Seul le nombre décimal à factoradique est réellement implémenté dans x. L'inverse appelle simplementx avec tous les nombres décimaux (0 .. *) jusqu'à ce que le résultat soit égal à l'entrée. Cela prend environ 3 secondes pour la plus grande entrée (! 987654321).

Version en ligne exécutable: http://dpaste.dzfl.pl/46e425f9

void main(string[] args) {
    import std.stdio;
    foreach (arg; args[1 .. $]) {
        writefln("%s -> %s", arg, x(arg));
    }
}

int x(string n) {
    import std.conv;
    int r, i=9, f=9*'鶀', d;  // 鶀's Unicode index equals 8*7*6*5*4*3*2*1

    // If the first character value is less than 48 ('0') it should be a '!'.
    if (n[0] < 48) {
        // Call x with different input (0..*) until it matches our n.
        // r.text.x is rewritten as x(text(r)).
        while (r.text.x < n[1..$].to!int) r++;
    } else {
        d = n.to!int;
        // Try d / 9!, d / 8!, etc. just as in the problem description.
        while (i) {
            r = r*10 + d/f;
            d %= f;
            f /= i--;
        }
    }
    return r;
}

Je pense qu'il pourrait être possible de changer string npour char[]nenregistrer un octet (je sais que je suis en retard ici).
Zacharý

En outre, je pense que if(n[0]<48){while(r.text.x<n[1..$].to!int)r++;}peut devenir if(n[0]<48)while(r.text.x<n[1..$].to!int)r++;pour économiser deux octets.
Zacharý

0

VBA 225

Merci à Titus pour l'aide! Toujours à la recherche de golf.

Sub a(b)
Set w=WorksheetFunction
e=Len(b)
If IsNumeric(b) Then
i=0
For d=0To 8
h=w.Fact(9-d)
g=b Mod h
If g<b+i Then
i=1
f=f &Int(b/h)
b=g
End If
Next
Else
For d=2To e
f=f+w.Fact(e-d-1)*Mid(b,d,1)
Next
End If
MsgBox f
End Sub

Je ne connais pas VBA, mais existe-t-il un moyen de vérifier bune valeur numérique au lieu de comparer le premier caractère?
Titus

@Titus Il y a une vérification numérique, et l'équivalent ici serait:, If Not IsNumeric(b) Thenmais cela prend plus de caractères. Maintenant, je ne suis pas entré et j'ai réexaminé tout le code; il peut y avoir un moyen légèrement meilleur de le faire avec l' IsNumericensemble. - Correction, il y a une légère amélioration ici. Merci!
Gaffi

J'ai trouvé quatre autres octets: For d=9To 1Step-1et Fact(d)-> For d=0To 8et Fact(9-d)deux autres si vous le faites For d=2To eetFact(e-d+1)*Mid(b,d,1)
Titus

Le type cast en Int peut-il être écrit d'une autre manière?
Titus

@Titus Regardez-vous, faites des cercles autour de moi. :) Je suis en train de peaufiner maintenant ... Quant à Int (), je ne pense pas qu'il existe une méthode plus simple (plus petite), non.
Gaffi

0

PHP , 124 octets

for($f=1;("$">$a=$argn)&&~$c=strrev($a)[$n];)$r+=$c*$f*=++$n;for(;$a>=$f*=++$i;);for(;~-$i;$a%=$f)$r.=0|$a/$f/=$i--;echo+$r;

Essayez-le en ligne!

Élargi

for($f=1;("$">$a=$argn)&&~$c=strrev($a)[$n];) # runs in case of "!" at the beginning
  $r+=$c*$f*=++$n; #reverse string multiply with the next factorial "!"*$f=0
for(;$a>=$f*=++$i;); # runs not in case of "!" at the beginning string comparing. search the factorial that is higher as input value
for(;~-$i;$a%=$f) # runs only when the second loop had runs
  $r.=0|$a/$f/=$i--; # concat the value of the division with the highest factorial used
echo+$r; # Output result

0

Perl 6 , 150 octets

{/^\!/??([+] [Z*] .comb.skip.reverse,[\*] 1..*)!!(reduce
->\a,\b{a[0]~a[1] div b,a[1]%b},("",+$_),|(first
*[*-1]>$_,[\,] [\*] 1..*).reverse[1..*])[0]}

0

APL (NARS), 36 caractères, 72 octets

{⍵⊆⎕D:10⊥(9..2)⊤⍎⍵⋄t+.×⌽!⍳≢t←⍎¨,1↓⍵}

il semble que 10⊥ (9..2) ⊤ soit meilleur que la fonction récursive, grâce à Howard pour l'autre solution APL qui montre que ... (même si je ne comprends pas 100%). Entrée pour les nombres sans '!' <10 !. Tester:

  u←{⍵⊆⎕D:10⊥(9..2)⊤⍎⍵⋄t+.×⌽!⍳≢t←⍎¨,1↓⍵}    
  u¨'1234' '746' '!54321' '!30311' '!24201'    
141120 101010 719 381 349 
  u '0'
0
  u '!0'
0
  u '9'
111
  u '!111'
9
  u '!9'
9
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.