Convierte ay desde el sistema de numeración factorial


27

El sistema de numeración factorial , también llamado factoradic, es un sistema mixto de números radix. Los factoriales determinan el valor posicional de un número.

En este sistema, el dígito más a la derecha puede ser 0 o 1, el segundo dígito a la derecha puede ser 0, 1 o 2, y así sucesivamente. Esto significa que un nnúmero factoradic de un dígito puede tener un valor máximo de (n + 1)!.

Por ejemplo, para convertir el número factoradic 24201a decimal, haría esto:

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

Por lo tanto, el número factoradic 24201es 349base 10.

Para convertir un número decimal (con 349un ejemplo) en un número factoradic, debe hacer esto:

Tome el factorial más grande menor que el número. En este caso es 120, o 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

Por lo tanto, 349base 10es el número factoradic 24201.

Su desafío es crear el programa o la función más corta que convierta un número de entrada a la otra base.

La entrada será una representación de cadena de un entero no negativo. Un número factoradic estará precedido por un !(por ejemplo !24201), mientras que un número decimal no estará precedido por nada. Puede suponer que la entrada máxima será 10! - 1- 3628799en decimal y 987654321en factoradic. Esto significa que las letras no aparecerán en una entrada / salida factoradic.

El programa no necesita anteponer !a una salida factoradic, y puede generar una cadena o un entero. La entrada puede estar en cualquier formato razonable.


Casos de prueba:

Input: 1234
Output: 141120

Input: 746
Output: 101010

Input: !54321
Output: 719

Input: !30311
Output: 381

Respuestas:


10

APL, 39 37 caracteres

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

Ejemplos:

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

1
Creo que se puede sustituir ⍴⍵∩'!'con '!'∊⍵guardar un carácter.
Volatilidad

@Volatility Sí puedes. También encontré otro.
Howard

11
En mi opinión, tener la palabra "pwn" en tu guión bien vale el carácter extra.
ejrb

1
Estoy de acuerdo con ejrb. ¿Podría romper esto por favor?
Titus

1
Reemplazar ~'!'con ∩⎕Dpara guardar un personaje.
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)

Versión más legible:

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)

Descompostura:

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
Buena solución Creo que se puede sustituir '!'==i[0]con '!'in i, y puede utilizar a=x=1. Además, no necesita corchetes alrededor de la declaración ejecutiva.
GRC

1
También podría reemplazar (len(i)-1)con ~-len(i).
Volatilidad

@Volatility, grc: ¡Gracias! Debería aprender mis operadores bit a bit :)
beary605

1
Buena respuesta, me tomé la libertad de tratar de reemplazar la declaración if (a,b)['!'in i]y logré eliminar 6 caracteres. Sin embargo, no es tan fácil de leer ... enlace de pastebin
ejrb

@erjb: ¡Gracias por la sugerencia! Utilicé una tupla de 2 con el código como una cadena en línea con la función ejecutiva, que guarda dos caracteres más :)
beary605

8

GolfScript ( 48 44 43 caracteres)

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

Este es un programa autónomo. La conversión factoriadic => decimal es bastante lenta, porque realiza una búsqueda utilizando la conversión decimal => factoriadic en lugar de una conversión de base directa.

El formato de entrada permite un cambio de modo muy corto: .~copia la cadena de entrada y la evalúa, por lo que si la entrada es solo un número, terminamos, por ejemplo, "1234" 1234en la pila, y si comienza con !(no lógico, con cualquier no vacío cadena siendo veraz) terminamos con, por ejemplo, 0 30311en la pila. Entonces el valor en la parte inferior de la pila es verdadero para decimal => factoriadic y falso para factoriadic => decimal.


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;

Ejecutar como tubería con -ro probarlo en línea .

  • no se requiere extensión
  • sin sub necesita : la base factorial se reutiliza (aumenta / disminuye en los bucles)
  • aritmética de enteros y cuerdas puras, incluso debería funcionar en php 3 (y aún funciona en php 7):
  • decimal 0 devuelve una cadena vacía en lugar de 0. (las otras dos respuestas PHP también lo hacen). Si eso es inaceptable, agregue +5 para el caso adicional.

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

ideas de golf abandonadas:

  • $b<=$x-> $b<$x(-1)
    rompería factoriales decimales puros (es decir, aquellos que resultan en un número factorial con solo un dígito distinto de cero) La solución de JMPC sufre de eso; HamZa´s no.
  • floor($x/$b)-> (int)($x/$b)
    podría ser un poco más rápido, pero la conversión de tipos precede a la división, así que necesito los paréntesis y no obtengo un byte.
    $x/$b|0Hace el truco
  • El bucle de hecho-> dec es similar al factorial-find en dec-> fact. El mismo incremento, el cuerpo no importa, pero desafortunadamente, la condición predeterminada y la condición de publicación son diferentes. Dang podría haber jugado golf -21 allí.
    YAY encontré una solución. Tomó bastante golf, pero cortó otro -4 (no: -9) y cerró todos los errores / lagunas.

¿Algún potencial más ... o he terminado de jugar al golf?


@ JörgHülsermann Gracias por la pista.
Titus

1
+$ren lugar de $r|0guardar un byte. Lo mismo paraif($x|0)
Jörg Hülsermann

3

JavaScript (ES 6) 139137122113 111

Probé un enfoque diferente usando un poco de magia de matriz; pero terminé en 174 172 bytes con eso:

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}

Así que tomé mi código PHP y lo traduje. Podría eliminar todos los $sy algunos ;, pero la necesidad de inicializar vars consumió parte de ese beneficio. Sin embargo, manejado para jugar al golf ambas respuestas se redujeron un poco más.

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 primera versión devuelve '' para el decimal 0; agregue +2 para arreglar
  • segunda versión requiere entrada de cadena
  • ambos probados en Firefox, Edge y Opera

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

Banco de pruebas

<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 no tiene notación de flecha IIRC. Y si vas a usar ES6, entonces .split('')=>.split``
Zacharý

@ Zacharý Gna Debería haber notado en qué navegador lo probé ... probablemente Firefox u Opera. Entonces, ¿ES 6?
Titus

Sí, la notación de flecha es ES6.
Zacharý

1
Oh, eso me tomó por sorpresa, ¡pensé que el bloque de código en la parte superior era tu solución! De todos modos, no creo que necesites decirlo f=. Además, puede r+=(x/(b/=j--)|0)ser r+=x/(b/=j--)|0?
Zacharý


1

GolfScript, 69 caracteres

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

Toma información de STDIN como de costumbre e imprime el resultado. Prueba en línea .


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

Con mucho, la entrada más legible. Haskell FTW!
Soham Chowdhury

1

Mathematica 213 177 175

Se incluye un número factorial f[], ya sea entrada o salida.

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

Conversión de factorial a número decimal . QuotientRemainder[n,j!]Actúa recursivamente sobre los dígitos del número factorial de izquierda a derecha, disminuyendo jen cada paso. QuotientRemainder[349, 5!], por ejemplo, retornos, {2, 109}etc.

Conversión de decimal a número factorial . Moviéndose de derecha a izquierda, la función pura # (p++)! &, multiplica cada dígito #, por el factorial apropiado.


1

Python, 128 caracteres

Esto tarda aproximadamente media hora en ejecutarse, pero es pequeño:

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

Construye una lista de todos los números factoradic <= 9 dígitos en orden numérico, luego realiza una búsqueda o índice para convertir.

Si quieres prueba, basta con sustituir 10**9con 10**6y restringirse a los números variadic de 6 dígitos.

Técnicamente podría guardar un personaje usando en range(10**9)lugar de xrange(10**9). No intentes esto en casa.


No se necesita espacio entre d+2yfor
Zacharý

1

PHP 231 214 204

Respuesta más reciente

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

Vieja respuesta

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

Ejemplo

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

Salida

24201
349
141120
101010
719
381

2
Cuento 212 para la nueva respuesta, no 214. $ e no necesita inicialización (-6) y foreach(range())se puede reemplazar con un forbucle simple (-9). Sin embargo, me gusta la idea.
Titus

2
Resultado incorrecto para factoriales puros. 24debería volver 1000pero vuelve 400. arreglo: g(++$p)<$x-> g(++$p)<=$x(+1)
Titus

@Titus ¡Gracias por sus dos respuestas! Actualicé mi respuesta. Le agradezco que me haya ayudado a mejorar mi respuesta cuando la suya parece muy superior.
JPMC

1
1) Cuento 2 menos que usted, nuevamente: 204, no 206. ¿Incluye un salto de línea de Windows en su conteo de bytes? 2) error de sintaxis en la forconstrucción: ,debería ser ;3) Tengo otros 7 cambios ahorrando 20 bytes en ese código. ¿Los quiero?
Titus

2
Bueno, en realidad son solo 5 cambios, pero uno de ellos tiene tres partes. a) segundo argumento obsoleto para f () (-3) b) espacio en blanco obsoleto en la función g (-1) c) llaves obsoletas en la rama verdadera (-4) d) intercambiar ramas verdaderas y falsas, invertir la ifcondición, luego usar my sexy type emitió a int (-6) ¡Esto no afectará el resultado decimal 0! e) la forconstrucción restante se puede reescribir con un muy buen while(++$t<$c=strlen($x)): incremento antes del cuerpo -> $ t no necesita inicialización (-6)
Tito

1

JALEA, 5 bytes

Æ!ŒṘ€

Explicación

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

* Jelly es más joven que la edad de la pregunta, por lo tanto, mi respuesta no es competitiva.


1
Bienvenido a PPCG! Creo que Jelly es más joven que este desafío, por lo tanto, debe marcar su respuesta como no competitiva.
Laikoni

Oh, no me di cuenta de que era una regla. Lo haré
DaggerOfMesogrecia

¿Las respuestas a este desafío no están destinadas a funcionar en ambos sentidos? Esto solo parece funcionar de una manera; Tu podrías querer reparar eso. (En una nota separada, si está convirtiendo entre enteros y cadenas en Jelly, normalmente es mejor usar alguna combinación de Vy .)

1

Jalea , 15 bytes

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

Pruébalo en línea!

Cómo 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

¬es un elemento lógico NO. Cuando se le da un solo entero, se convierte en un solo cero, que es falso. Sin embargo, cuando se le asigna una cadena, cada elemento (carácter) se convierte en cero, y el resultado completo es una matriz de ceros, lo cual es cierto.

Cero como entero es un caso especial. Pasa por la ruta "factorial -> entero", pero aún da cero, que es correcto.

Sin base factorial incorporada, 25 bytes

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

Pruébalo en línea!

Cómo 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

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 podría mejorarse.

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

Sin golf y con punto de entrada al programa

Todos los argumentos de la línea de comando se imprimen como <original> -> <converted>. Solo se implementa en decimal a factoradic x. Al revés solo llama xcon todos los números decimales (0 .. *) hasta que el resultado sea igual a la entrada. Esto toma ~ 3 segundos para la entrada más grande (! 987654321).

Versión en línea ejecutable: 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;
}

Creo que es posible cambiar string na char[]npara guardar un byte (sé que llego tarde aquí).
Zacharý

Además, creo que if(n[0]<48){while(r.text.x<n[1..$].to!int)r++;}puede llegar if(n[0]<48)while(r.text.x<n[1..$].to!int)r++;a ser para guardar dos bytes.
Zacharý

0

VBA 225

¡Gracias a Titus por la ayuda! Todavía estoy buscando jugar al golf un poco más.

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

No sé VBA, pero ¿hay alguna manera de verificar bun valor numérico en lugar de comparar el primer carácter?
Titus

@Titus Hay una verificación numérica, y el equivalente aquí sería:, If Not IsNumeric(b) Thenpero eso requiere más caracteres. Ahora, no entré y reexaminé todo el código; Puede haber una manera ligeramente mejor de hacer esto en IsNumericgeneral. - Corrección, hay una ligera mejora aquí. ¡Gracias!
Gaffi

Encontré otros cuatro bytes: For d=9To 1Step-1y Fact(d)-> For d=0To 8y Fact(9-d)y otros dos si lo haces For d=2To eyFact(e-d+1)*Mid(b,d,1)
Titus

¿Se puede escribir el tipo de conversión a Int de otra manera?
Titus

@Titus Mírate, dando vueltas a mi alrededor. :) Estoy ajustando ahora ... En cuanto a Int (), no creo que haya un método más simple (más pequeño), no.
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;

Pruébalo en línea!

Extendido

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 bytes

{/^\!/??([+] [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 caracteres, 72 bytes

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

parece que 10⊥ (9..2) ⊤ es mejor que la función recursiva, gracias a Howard por la otra solución APL que muestra que ... (incluso si no entiendo 100%). Entrada para números sin '!' <10 !. Prueba:

  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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.