Converter de e para o sistema de números fatoriais

27

O sistema de número fatorial , também chamado de fatorádico, é um sistema numérico de raiz mista. Os fatoriais determinam o valor da posição de um número.

Nesse sistema, o dígito mais à direita pode ser 0 ou 1, o segundo dígito mais à direita pode ser 0, 1 ou 2 e assim por diante. Isso significa que um nnúmero fatorádico de dígito pode ter um valor máximo de (n + 1)!.

Por exemplo, para converter o número fatorádico 24201em decimal, você faria o seguinte:

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

Portanto, o número fatorádico 24201é 349base 10.

Para converter um número decimal (com 349um exemplo) em um número fatorádico, faça o seguinte:

Tome o maior fatorial menor que o número. Nesse caso, é 120ou 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

Portanto, 349base 10é o número fatorádico 24201.

Seu desafio é criar o programa ou função mais curto que converta um número de entrada na outra base.

A entrada será uma representação em cadeia de um número inteiro não negativo. Um número fatorádico será precedido por um !(por exemplo !24201), enquanto um número decimal não será precedido por nada. Você pode assumir que a entrada máxima será 10! - 1- 3628799em decimal e 987654321em fatorádico. Isso significa que as letras não aparecerão em uma entrada / saída fatorádica.

O programa não precisa !acrescentar a a uma saída fatorádica e pode gerar uma string ou um número inteiro. A entrada pode estar em qualquer formato razoável.


Casos de teste:

Input: 1234
Output: 141120

Input: 746
Output: 101010

Input: !54321
Output: 719

Input: !30311
Output: 381
Volatilidade
fonte

Respostas:

10

APL, 39 37 caracteres

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

Exemplos:

      {A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}'1234'
141120
      {A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}'!54321'
719
Howard
fonte
1
Eu acho que você pode substituir ⍴⍵∩'!'por '!'∊⍵para salvar um personagem.
Volatilidade
@ Volatility Sim, você pode. Eu também encontrei outro.
209 Howard
11
A IMO com a palavra "pwn" em seu script vale bem o caractere extra.
ejrb
1
Eu concordo com ejrb. Você poderia quebrar isso, por favor?
Titus
1
Substitua ~'!'por ∩⎕Dpara salvar um personagem.
Adám 07/06/19
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)

Versão mais legível:

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)

Demolir:

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
beary605
fonte
1
Ótima solução. Eu acho que você pode substituir '!'==i[0]por '!'in i, e pode usar a=x=1. Além disso, você não precisa de colchetes na declaração exec.
grc
1
Você também pode substituir (len(i)-1)por ~-len(i).
Volatilidade
@ Volatility, grc: Obrigado! Eu deveria aprender meus operadores bit a bit :)
beary605
1
Boa resposta, tomei a liberdade de tentar substituir a instrução if por (a,b)['!'in i]e consegui raspar 6 caracteres. Não é tão legível como era embora ... pastebin ligação
ejrb
@erjb: Obrigado pela sugestão! Eu usei um 2-tupla com o código como uma string em linha com a função exec, o que economiza mais dois personagens :)
beary605
8

GolfScript ( 48 44 43 caracteres)

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

Este é um programa independente. A conversão factoriadic => decimal é bastante lenta, porque faz uma pesquisa usando a conversão decimal => factoriadic em vez de uma conversão de base direta.

O formato de entrada permite um comutador de modo muito curto: .~copia a string de entrada e a avalia; portanto, se a entrada for apenas um número, acabamos com, por exemplo, "1234" 1234na pilha e se ela começa com !(não é lógico, com qualquer não vazio) string sendo verdade) nós terminamos com, por exemplo, 0 30311na pilha. Então o valor na parte inferior da pilha é verdadeiro para decimal => factoriadic e falso para factoriadic => decimal.

Peter Taylor
fonte
4

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

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;

Execute como tubo -rou teste-o online .

  • nenhuma extensão necessária
  • não é necessária subfunção : a base fatorial está sendo reutilizada (aumentada / diminuída nos loops)
  • aritmética pura de número inteiro e string, deve funcionar no php 3 (e ainda funciona no php 7):
  • decimal 0 retorna uma string vazia em vez de 0. (as duas outras respostas PHP também.) Se isso for inaceitável, adicione +5 para o caso extra.

ungolfed:

// 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éias de golfe abandonadas:

  • $b<=$x-> $b<$x(-1)
    quebraria fatoriais decimais puros (isto é, aqueles que resultam em um número fatorial com apenas um dígito diferente de zero). A solução da JMPC sofre com isso; HamZa não.
  • floor($x/$b)-> (int)($x/$b)
    poderia ser um pouco mais rápido, mas a conversão de tipo precede a divisão, por isso preciso dos parênteses e não ganho um byte.
    $x/$b|0faz o truque
  • O loop de fato-> dec é semelhante ao fatorial-encontrar em dec-> fato. Mesmo incremento, o corpo não importa, mas, infelizmente, predefinições diferentes e diferentes condições pós. Dang; poderia ter jogado -21 lá.
    YAY eu encontrei uma solução. Tomou bastante golfe, mas cortou outros -4 (no: -9) e fechou todos os bugs / brechas.

Existe mais potencial ... ou já terminei de jogar golfe?

Titus
fonte
@ JörgHülsermann Obrigado pela dica.
Titus
1
+$rem vez de $r|0salvar um byte. O mesmo paraif($x|0)
Jörg Hülsermann
3

JavaScript (ES 6) 139 137 122 113 111

tentou uma abordagem diferente usando alguma mágica de matriz; mas acabei com 174 172 bytes com o seguinte:

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}

Então, peguei meu código PHP e o traduzi. Poderia remover todos os se $alguns ;, mas a necessidade de inicializar vars consumia alguns desses benefícios. Conseguiu jogar as duas respostas um pouco mais longe, no entanto.

golfed

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}
  • primeira versão retorna '' para decimal 0; adicione +2 para corrigir
  • segunda versão requer entrada de string
  • ambos testados no Firefox, Edge e Opera

destroçado

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
}

suíte de teste

<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>
Titus
fonte
1
O ES5 não possui a notação de seta IIRC. E se você estiver usando o ES6, então .split('')=>.split``
Zacharý
@ Zacharý Gna Eu deveria ter notado em que navegador eu o testei ... provavelmente no Firefox ou no Opera. Então ES 6?
Titus
Sim, a notação de seta é ES6.
Zacharý
1
Oh, isso me pegou de surpresa, pensei que o bloco de código no topo fosse sua solução! Independentemente disso, acho que você não precisa dizer f=. Além disso, pode r+=(x/(b/=j--)|0)ser r+=x/(b/=j--)|0?
Zacharý
2

Perl 6 , 66 65 60 bytes

-1 byte graças a Jo King

{/\!/??:1[.flip.chop.comb Z*[\*] 1..*]!![R~] .polymod(2..*)}

Experimente online!

Nwellnhof
fonte
1

GolfScript, 69 caracteres

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

Pega a entrada de STDIN como de costume e imprime o resultado. Teste online .

Howard
fonte
1

Haskell, 221 caracteres

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

Uso

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

Código ungolfed

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!!)
StreakyCobra
fonte
De longe, a entrada mais legível. Haskell FTW!
Soham Chowdhury
1

Mathematica 213 177 175

Um número fatorial é envolvido f[], seja ele de entrada ou de saída.

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

Uso

z[24201]

f [349]

z[f[349]]

24201

Conversão de fatorial para número decimal . QuotientRemainder[n,j!]atua recursivamente nos dígitos do número fatorial da esquerda para a direita, diminuindo ja cada passo. QuotientRemainder[349, 5!], por exemplo, retornos {2, 109}e assim por diante.

Conversão do número decimal em fatorial . Movendo da direita para a esquerda, a função pura # (p++)! &multiplica cada dígito #pelo fatorial apropriado.

DavidC
fonte
1

Python, 128 caracteres

Isso leva cerca de meia hora para ser executado, mas é pequeno:

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

Ele cria uma lista de todos os números fatorádicos <= 9 dígitos em ordem numérica e, em seguida, faz uma pesquisa ou índice para converter.

Se você deseja testar, basta substituir 10**9por 10**6e restringir-se a números variáveis ​​de 6 dígitos.

Eu poderia tecnicamente salvar um personagem usando em range(10**9)vez de xrange(10**9). Não tente isto em casa.

Keith Randall
fonte
Não é necessário espaço entre d+2efor
Zacharý
1

PHP 231 214 204

Resposta mais recente

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

Resposta antiga

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

Exemplo

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

Saída

24201
349
141120
101010
719
381
JPMC
fonte
2
Conto 212 para a nova resposta, não 214. $ e não precisa de inicialização (-6) e foreach(range())pode ser substituído por um forloop simples (-9). Eu gosto da ideia no fim das contas.
Titus
2
resultado errado para fatoriais puros. 24deve retornar, 1000mas retorna 400. correção: g(++$p)<$x-> g(++$p)<=$x(+1)
Titus
@Titus Obrigado por ambas as suas respostas! Eu atualizei minha resposta. Agradeço por me ajudar a melhorar minha resposta quando a sua parecer muito superior.
JPMC 5/16
1
1) Conto 2 menos que você, novamente: 204, não 206. Você inclui uma quebra de linha do Windows na contagem de bytes? 2) erro de sintaxe na forconstrução: ,deve ser ;3) Tenho mais 7 alterações economizando 20 bytes nesse código. Os quero?
Titus
2
Bem, na verdade são apenas 5 alterações, mas uma delas tem três partes. a) segundo argumento obsoleto para f () (-3) b) espaço em branco obsoleto na função g (-1) c) chaves obsoletas no ramo verdadeiro (-4) d) troque ramos verdadeiros e falsos, inverta a ifcondição e use meu tipo sexy convertido para int (-6) Isso não afetará o resultado decimal 0! e) os restantes forconstrução pode ser reescrita com uma muito agradável while(++$t<$c=strlen($x)): incremento antes do corpo -> $ t não precisa de inicialização (-6)
Titus
1

GELÉIA, 5 bytes

Æ!ŒṘ€

Explicação

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

* A geléia é menor que a idade da pergunta, portanto minha resposta é não-competitiva.

DaggerOfMesogrecia
fonte
1
Bem-vindo ao PPCG! Eu acho que Jelly é mais jovem que esse desafio, portanto, você deve marcar sua resposta como não competitiva.
Laikoni 7/06
Oh, eu não percebi que isso era uma regra. Vai fazer.
DaggerOfMesogrecia
As respostas a esse desafio não devem funcionar nos dois sentidos? Isso parece funcionar apenas de uma maneira; você pode querer consertar isso. (Em uma nota separada, se você estiver a conversão entre números inteiros e strings in Jelly, é normalmente tersest de usar uma combinação de Ve .)
1

Gelatina , 15 bytes

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

Experimente online!

Como funciona

Ḋ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

Por que *)funciona

¬NÃO é elemento-lógica. Quando determinado um único número inteiro, ele se torna um único zero, o que é falso. No entanto, quando uma string é fornecida, cada elemento (caractere) é transformado em zero, e o resultado inteiro é uma matriz de zeros, o que é verdadeiro.

Zero como um número inteiro é um caso especial. Ele percorre a rota "fatorial -> inteiro", mas ainda dá zero, o que está correto.

Sem base fatorial embutida, 25 bytes

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

Experimente online!

Como funciona

⁵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
Bubbler
fonte
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]]}

Definitivamente poderia ser melhorado.

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
tmartin
fonte
0

D (159 caracteres)

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

Ungolfed e com ponto de entrada do programa

Todos os argumentos da linha de comando são impressos como <original> -> <converted>. Somente decimal para fatorádico é realmente implementado em x. O contrário apenas chama xcom todos os números decimais (0 .. *) até que o resultado seja igual à entrada. Isso leva aproximadamente 3 segundos para a maior entrada (! 987654321).

Versão executável online: 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;
}
mleise
fonte
Eu acho que pode ser possível mudar string npara char[]nsalvar um byte (eu sei que estou atrasado aqui).
Zacharý
Além disso, acho que if(n[0]<48){while(r.text.x<n[1..$].to!int)r++;}pode tornar if(n[0]<48)while(r.text.x<n[1..$].to!int)r++;- se para salvar dois bytes.
Zacharý
0

VBA 225

Obrigado a Titus pela ajuda! Ainda olhando para o golfe um pouco mais.

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
Gaffi
fonte
Não conheço VBA, mas existe uma maneira de verificar bum valor numérico em vez de comparar o primeiro caractere?
Titus
@Titus Há uma verificação numérica, e o equivalente aqui seria:, If Not IsNumeric(b) Thenmas isso exige mais caracteres. Agora, eu não entrei e reexaminei todo o código; pode haver uma maneira um pouco melhor de fazer isso no IsNumericgeral. - Correção, há uma ligeira melhora aqui. Obrigado!
Gaffi #
Eu encontrei mais quatro bytes: For d=9To 1Step-1e Fact(d)-> For d=0To 8e Fact(9-d)e outros dois se você fizer For d=2To eeFact(e-d+1)*Mid(b,d,1)
Tito
O tipo de conversão para Int pode ser escrito de outra maneira?
Titus
@ Titus Olhe para você, correndo círculos ao meu redor. :) Estou ajustando agora ... Quanto ao Int (), não acho que exista um método mais simples (menor), não.
Gaffi #
0

PHP , 124 bytes

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;

Experimente online!

Estendido

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
Jörg Hülsermann
fonte
0

Perl 6 , 150 bytes

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

APL (NARS), 36 caracteres, 72 bytes

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

parece que 10⊥ (9..2) ⊤ é melhor que a função recursiva, graças a Howard pela outra solução de APL que mostra isso ... (mesmo que eu não entenda 100%). Introduza números sem '!' <10 !. Teste:

  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
RosLuP
fonte