Expande el número


58

Puede recordar en primer o segundo grado usando la forma expandida para aprender sobre el valor posicional de los números. Es más fácil de explicar con un ejemplo, así que considere el número 123. En forma expandida, se representa como 100 + 20 + 3, lo que ayuda a una mente joven a visualizar el valor posicional. Recuerda cómo lo dices: ciento (más) veinte (más) tres.

Podemos extender esto más allá del lugar de las unidades con decimales: 2.718 => 2 + 0.7 + 0.01 + 0.008

Su desafío es escribir un programa o función que tome un número positivo de coma flotante o cero (suponga que es tan grande o preciso como su lenguaje puede manejar; no estará en notación científica) o cadena e imprime / devuelve en forma expandida como se explicó anteriormente.

No necesita espacios entre los +'s ni el cero antes del punto decimal, por lo que el ejemplo anterior podría ser 2+.7+.01+.008. Deben omitirse los valores que serían iguales a cero ( 101.01 => 100 + 1 + 0.01) a menos que la entrada sea cero (ver más abajo).

Los valores no deben tener más de un cero a la izquierda antes del punto decimal o cualquier ceros a continuación (no-no:) 0060, 0000.2, 30., 30.000, .0400. La entrada también se ajustará a esto.

Como los alumnos de primer grado tienen períodos de atención cortos, su código tendrá que ser lo más breve posible.

Casos de prueba

0 => 0
6 => 6
0.99 => 0.9 + 0.09
24601 => 20000 + 4000 + 600 + 1
6.283 => 6 + 0.2 + 0.08 + 0.003
9000000.0000009 => 9000000 + 0.0000009

22
+1 para "Dado que los alumnos de primer grado tienen períodos de atención cortos, su código deberá ser lo más breve posible".
Downgoat

2
@ Me alegro de ver que el meme todavía se está ejecutando.
gato

44
Habría sido divertido hacerlo de la misma manera que nosotros (francés) contamos, para ver a las personas luchar con el caso del 97 (4 * 20 + 10 + 7) ^^
Katenkyo

2
@ jimmy23013 Sí, siempre que funcione en teoría.
NinjaBearMonkey

1
@Ogaday No lo sé, son solo algunos casos extremos. Tal vez la manera NBZ sería mejor, pero aún así, no lo haría si realmente fuera interesante
Katenkyo

Respuestas:


6

CJam, 33 26 bytes

r_ee\'0fe<f{\~t~}{},'+*0e|

Esto no funcionará con el intérprete de Java; imprime flotadores de manera diferente. Pruébelo con el intérprete de CJam .

Se imprime el último caso de prueba 9000000+9e-7, que ha sido declarado válido por @NinjaBearMonkey .

¡Gracias a @ jimmy23013 por jugar golf en 7 bytes!

Cómo funciona

r_                           Read a token from STDIN and push a copy.
  ee                         Enumerate its characters, i.e., push the array of all
                             [index character] pairs.
    \                        Swap the original input on top of the stack.
     '0fe<                   Perform vectorized minimum with the character '0'.
                             This replaces all digits with '0', but leaves '.'
                             untouched, since `.' < '0'.
          f{    }            For each [index character] pair, push the pair and the
                             string of zeroes and (possibly) a dot; then:
            \                    Swap the pair on top of the stack.
             ~                   Dump index and character on the stack.
              t                  Replace the string's element at that index with
                                 that character.
               ~                 Evaluate the resulting string.
                 {},         Filter the array to remove zeroes.
                    '+*      Join, using '+' as separator.
                       0e|   If the result is empty, replace it with 0.

Basado en la misma idea: r_ee\'0fe<f{\~t~}{},'+*0e|.
jimmy23013

@ jimmy23013 Wow, eso es corto! ¡Gracias!
Dennis

5

JavaScript (ES7), 102 bytes

n=>+n&&[...n.replace(/^\.0*|\./,"")].map(f=d=>10**p--*d,p=Math.floor(Math.log10(n))).filter(f).join`+`

Explicación

Requiere que el número se ingrese como una cadena sin ceros a la izquierda (a menos que el número sea, 0 por supuesto).

Nota: Debido a la rareza de punto flotante, algunos números (como .3) salen mal, pero en teoría esto funciona para cualquier número.

n=>                             // n = input number as string
  +n&&                          // return 0 if n = 0
  [...n.replace(/^\.0*|\./,"")] // remove leading zeroes after the decimal place
  .map(f=d=>                    // for each digit d in n
      10**p--*d,                // raise the digit to the correct power of 10
    p=Math.floor(Math.log10(n)) // p = power of 10 for the first digit, floor needs to be
  )                             //     used instead of |0 due to negative powers of 10 :(
  .filter(f)                    // remove zeroes, the map function is reused
  .join`+`                      // return the output numbers joined with +

Prueba

Prueba de uso en Math.powlugar de **compatibilidad del navegador.


Math.floor=> 0|...?
ETHproductions

@ETHproductions Si el número de entrada es menor de 1lo que se rompería porque Math.log10(n)devolvería un número negativo y se |0redondea a cero en lugar de piso.
user81655

¿Se puede usar en 0|Math.log10(n),p-=p<0lugar de Math.floor(Math.log10(n))?
Dom Hastings

1
@DomHastings Casi. Falla n<1porque 0|hará pigual 0para ambos 0.1y -0.1. La forma más corta que se me ocurre es p=Math.log10(n),p=p-(p<0)|0cuál es la misma longitud que usar Math.floor. :(
user81655

@DomHastings Todavía no funcionaría de n=0.1todos modos.
Neil

5

Retina , 86 77 75 bytes

El recuento de bytes supone que la fuente está codificada como ISO 8859-1.

S_`.(?<=(\.\d+))|(?=(\d*)).
Tm`d`0`\..+\B|(?<=^\d).+
¶([.0]+¶)*
+
^0.|\+0$

El avance de línea final es significativo.

Pruébalo en línea.

Explicación

S_`.(?<=(\.\d+))|(?=(\d*)).

Comenzamos convirtiendo la entrada en una lista separada de salto de línea de componentes, aunque solo el dígito inicial (o final) es correcto. Esto se hace abusando de una etapa dividida. En lugar de dividir la entrada, coincidimos con todos, por lo que los segmentos restantes están vacíos. Eliminamos esos segmentos vacíos con la _opción. El problema es que las etapas divididas también devuelven los valores de todos los grupos de captura. Por lo tanto, usamos una búsqueda anticipada en cada coincidencia para capturar la parte correcta de la cadena: primero intentamos encontrar una .izquierda de la coincidencia. Si ese es el caso, capturamos todo, desde.hasta e incluyendo el dígito que estamos haciendo coincidir. De lo contrario, debemos estar en la parte entera de la entrada, por lo que capturamos todos los números después de la coincidencia (incluida la coincidencia). También debemos deshacernos del punto decimal en sí mismo, por lo que la segunda captura es opcional. Si no hay \dque capturar, esto simplemente eliminará la coincidencia de la entrada.

Tm`d`0`\..+\B|(?<!=\d).+

Ahora usamos una etapa de transliteración para convertir todos menos los dígitos iniciales / finales en ceros. Hacemos coincidir un componente que es menor que 1 con \..+\Bdonde se \Basegura que detengamos la coincidencia un dígito antes del final, o hacemos coincidir una parte entera con (?<=^\d).+donde el mirar atrás asegura que comencemos un dígito en el número. La etapa de transliteración reemplazará los dígitos ( d) con ceros dentro de las coincidencias.

¶([.0]+¶)*
+

Ahora, el formato de salida real +no debe usar saltos de línea como separadores. El coincide con un salto de línea para hacer esa sustitución. Mientras estamos en eso, también eliminamos líneas que contienen solo 0sy .s.

^0.|\+0$

La etapa anterior no elimina un inicio o un final 0(porque esos no tienen un salto de línea antes y después de ellos), por lo que los eliminamos explícitamente.


4

Python 2, 216 210 196 175 bytes

Aquí hay un código ligeramente golfizado que jugaré más cuando tenga tiempo. Utiliza análisis de cadenas.

i=input().split(".")
I=i[0]
e=enumerate
o=[(k+len(I[j+1::])*"0") for j,k in e(I) if k!="0"] 
try:o+=["."+l*"0"+m for l,m in e(i[1]) if m!="0"]
except:0
print "+".join(o or"0")

Explicación

Entonces, la entrada se separa en una parte entera y decimal. Luego, hay una lista de comprensión de bucles. En la parte entera, la longitud de la cadena después de un carácter en el decimal se multiplica por "0" para obtener tantos ceros al final si ese carácter.

Para la parte decimal, el índice del carácter actual es el número de ceros que tiene delante y, por lo tanto, esa parte es simple.

El try and except se usa para determinar si tiene una parte decimal o no (usando un error).

El resultado final se une con signos más.

Pruébalo aquí!


2
Creo que o if o else ["0"]puede ser o or["0"].
lirtosiast

Tiene un espacio final en la línea cuatro que se suma a su recuento de bytes. En la línea cuatro solo necesitas un colon. Puede eliminar los espacios en los siguientes fragmentos: o=[(...)] for, e(I) if, e(i[1]) if, print "+", y el paréntesis exterior o=[(...), así, en realidad. Finalmente, puede eliminar el condicional final de la función de unión de esta manera: print"+".join(o)or"0"porque unir devolverá una lista vacía si oestá vacía, por lo que el condicional evaluará de la misma manera, lo que le ahorrará un byte.
Ogaday

3

Pyth, 30 bytes

L.xvbytb|j\+fT.eyXXzjkUT\0kbzz

Banco de pruebas

La solución básica aquí es reemplazar todos los dígitos en la entrada con 0, luego insertar cada dígito en la ubicación adecuada, evaluar, filtrar los ceros y unir en los más. Desafortunadamente, la función eval de Pyth no acepta ceros iniciales actualmente. Estaré trabajando para arreglar esto.

Para superar este problema, agregué una función auxiliar y, que reintenta recursivamente la evaluación hasta que no se produce ningún error, eliminando el primer dígito cada vez. Tenga en cuenta que esta función se repetirá infinitamente en una entrada no válida.

Además, se necesitaba un caso especial para la entrada 0.

En general, creo que el código es bastante bueno, pero las instalaciones del lenguaje podrían ser mejores. ¿Quién quiere errores?


3

Pitón 3, 138

Esto se basa libremente en el enfoque de TanMath / Ogaday de leer el número como una cadena y analizarlo de esa manera. Tengo que usar la asignación de estrellas ipara que maneje correctamente los enteros.

j,*i=input().split(".")
e=enumerate
z="0"
print("+".join([(x+len(j[y+1:])*z)for y,x in e(j)if x>z]+["."+o*z+p for o,p in e(i)if p>z]or z))

3

Python, 141 132 128 bytes

Este todavía es relativamente legible. Convierta a cadena y maneje los >1dígitos por separado de los <1dígitos. También tenemos un caso especial para cero. Podría eliminar dos espacios más a continuación, pero me gusta mantenerlo bonito.

La desventaja es que se desglosará para flotadores con más de 9 decimales.

x=str(int(a*1e9))
l=len(x)-10
z="0"
print"+".join([(j+z*(l-i))if l>=i
 else"."+z*(i-l-1)+j
 for i,j in enumerate(x)if j!=z]or z)

Debajo está el original. La primera edición fue acortar el caso especial de cero, la segunda edición fue eliminar el 0 antes del decimal, la tercera fue eliminar algunos paréntesis y espacios adicionales.

x=str(int(a*1e9))
l=len(x)-10
z="0"
print "+".join([(j+z*(l-i)) if l>=i
 else ("0."+z*(i-l-1)+j)
 for i,j in enumerate(x) if j!=z]) if a else z

Explicación:

x=str(int(a*1e9)) # Convert into a string with nine decimals
l=len(x)-10
z="0"
print "+".join([
 (j+z*(l-i)) if l>=i       # Print numbers greater than 1
 else ("0."+z*(i-l-1)+j)   # Print less than one
 for i,j in enumerate(x) if j!=z
]) if a else z             # Special case zero

No necesita incluir todas las revisiones de su código; Si queremos ver su progreso en el golf, podemos ver el historial de revisiones. Por cierto, ¡bienvenido a PPCG!
lirtosiast el

1
Acabo de descubrirlo ... ¡Voy a tener que intentar no pasar demasiado tiempo en este sitio!
Speedplane

2

Mathematica, 81 bytes

Inactive@Plus@@(10.^Range[#2-1,#2-Length@#,-1]#/.{0.->Nothing[]})&@@RealDigits@#&

Caso de prueba:

%[101.01]
(* 100. + 1. + 0.01 *)

3
No creo que se permita tener el punto decimal sobre las partes enteras.
Martin Ender

2

CJam, 44 bytes

r:TdLT'.-{'0f+IaaI~g*+}fI:dATW%'.##m]f/'+*e&

Pruébalo aquí

Falla el último caso de prueba y genera lo siguiente:

9000000+9e-7

Pero digamos que es demasiado preciso que CJam no puede manejarlo.

Explicación

r:Td
LT'.-         e# Remove the period if any.
{             e# For each character I:
  '0f+        e# Append 0 to each previous string.
  IaaI~g*+    e# Append I as a string if I isn't '0.
}fI
:d            e# Convert each string to float.
ATW%'.##      e# 10 to the kth power where k is the position of the period from the end.
m]            e# Round up, so it becomes 1 if no periods are found.
f/            e# Divide each float by this number.
'+*e&         e# Format and the 0 special case.

2

Python 3, 187 180 173 154 bytes

Se las arregló para jugar al golf con una buena cantidad de 19 bytes de descuento gracias a las sugerencias de @Thomas Kwa mencionadas anteriormente result or['0'], además de reorganizar algo de álgebra ( 154 bytes ):

def f(n):
 *m,=n;o='0'
 try:p=m.index('.');m.pop(p)
 except:p=len(m)
 return'+'.join([['.'+o*(i-p)+d,d+o*(p-i-1)][p>i]for i,d in enumerate(m)if d!=o])or o

Mi mejor intento hasta ahora ( 173 bytes ). Basado en un nuevo enfoque, vea la parte inferior de la publicación:

def f(n):
 *m,=n;o='0'
 try:p=m.index('.');m.pop(p)
 except:p=len(m)
 return(o,'+'.join([['.'+o*(-1*(p-i))+d,d+o*(p-i-1)][p-i>0]for i,d in enumerate(m)if d!=o]))[eval(n)!=0]

Golfé mi original hasta 180 bytes :

def f(n):x=n.split('.');a,b=(x+[''],x)[len(x)-1];e=enumerate;return('0',"+".join([d+'0'*i for i,d in e(a[::-1])if d!='0'][::-1]+['.'+'0'*i+d for i,d in e(b)if d!='0']))[eval(n)!=0]

¡Aprendí una nueva función de lenguaje hoy haciendo esto! Condicionales mediante indexación booleana. Puede que lo haya exagerado un poco.

Intenté resumir las comprensiones, pero no pude acortarlo ( 196 bytes ):

e=lambda s:[d+'0'*(len(s)-i-1) for i,d in enumerate(s) if eval(d)]
def f(n):x=n.split('.');a,b=(x+[''],x)[len(x)-1];return['0',"+".join(e(a)+['.'+d[::-1]for d in e(b[::-1])][::-1])][bool(eval(n))]

(¡Invertir secuencias es costoso!)

Mientras que la mía es más corto, por ahora, creo que TanMath lata campo de su abajo para que coincida con la mía: El uso e=enumerate, en sustitución passde 0, y usar '0'en su lugar de['0'] en la instrucción de retorno debe guardar 4 + 3 + 2 = 9 bytes! Bajándolo a 187. Estoy seguro de que se pueden eliminar otros pocos bytes en alguna parte ...

editar Nuevo enfoque ( 156 bytes ). Sin embargo, solo puede lidiar con una precisión de hasta 6dp similar a la entrada CJam de @ jimmy23013, por lo que falla la prueba final. No pude obligarlo a imprimir más ceros, tal vez alguien más pueda. En cambio, lo utilicé como la base de mi mejor intento hasta la fecha, ver arriba (Además, este enfoque imprime el 0 antes del decimal, pero eso también parece válido). Tomó el try:... except:...enfoque de TanMath:

def f(n):
 *m,=n
 try:p=m.index('.');m.pop(p)
 except:p=len(m)
 return('0','+'.join([str(eval(d)*10**(p-i-1))for i,d in enumerate(m)if d!='0']))[eval(n)!=0] 

Si está tratando de ayudarme con el golf, inclúyalos como comentarios a mi respuesta, no en su respuesta. No siempre veo sus respuestas, así que al escribir un comentario, recibiré una notificación y definitivamente la veré.
TanMath

2
Hola @TanMath Lo haría, pero todavía no tengo suficiente representante para comentar las publicaciones de otras personas. Una vez que obtenga algunos botes más, me aseguraré de dejar comentarios en los comentarios.
Ogaday

2

puro golpe, 210

o= a=${1%.*} b=${1#$a};while [ "$a" ];do c=${a:1};((${a%$c}>0))&&o+=${a%$c}${c//?/0}+;a=$c;done;[ "$b" ]&&{ b=${b#.} a=;while [ "$b" ];do c=${b:0:1};((c>0))&&o+=.$a$c+;b=${b:1};a+=0;done;};o=${o%+};echo ${o:-0}

o

o= a=${1%.*} b=${1#$a};while [ "$a" ];do c=${a:1};((${a%$c}>0))&&
o+=${a%$c}${c//?/0}+;a=$c;done;[ "$b" ]&&{ b=${b#.} a=;while [ "$b" ]
do c=${b:0:1};((c>0))&&o+=.$a$c+;b=${b:1};a+=0;done;};o=${o%+};echo ${o:-0}

Prueba:

exp() {
    o= a=${1%.*} b=${1#$a};while [ "$a" ];do c=${a:1};((${a%$c}>0))&&
    o+=${a%$c}${c//?/0}+;a=$c;done;[ "$b" ]&&{ b=${b#.} a=;while [ "$b" ]
    do c=${b:0:1};((c>0))&&o+=.$a$c+;b=${b:1};a+=0;done;};o=${o%+};echo ${o:-0}
}
while read num;do
    printf "%-12s => " $num
    exp $num
done <<<$'0\n6\n0.99\n24601\n6.283\n9000000.0000009\n3.1415\n.99'
0            => 0
6            => 6
0.99         => .9+.09
24601        => 20000+4000+600+1
6.283        => 6+.2+.08+.003
9000000.0000009 => 9000000+.0000009
3.1415       => 3+.1+.04+.001+.0005
.99          => .9+.09

2

Python, 131 bytes

f=lambda s,k=0,i=0,o="",z="0":s and f(s[1:],(s<z)+k,i+k,o+(s>="1")*([s[0]+~-(s+".").find(".")*z,"."+z*i+s[0]][k]+"+"))or o[:-1]or z

Una función recursiva muy, muy desordenada, probablemente no sea la mejor manera de hacerlo. Entrada como f("10.0203").


¿Es esto incluso Python? Quiéralo.
Ogaday

2

C, 155 153 161 bytes

+2 para vincular en la biblioteca matemática (la fuente en sí es 159).

main(d,v,p,q)char**v,*p,*q;{for(p=strchr(q=v[1],46),d=p?p-q:strlen(q);*q;++q)*q^46?printf(*q^48|q==v[1]?"%.*f%c":"",d<0?-d:0,(*q-48)*pow(10,--d),q[1]?43:0):0;}

Sin golf

int main(int d, char **v, char *p, char *q)
{
    for(q = v[1], /* Cache the input string */
        p = strchr(q,'.'), /* find the decimal */
        d = p ? p-q : strlen(q); /* calculate number of digits before decimal */
        *q; /* loop while still input data */
        ++q) /* iterate to next character */
    {
        *q^46 /* if not at the decimal point... */
            ? printf(*q^48 || q == v[1] /* if not a zero, or if the string itself is zero... */
                ? "%.f%c" /* print the digit */
                : "", /* else print nothing */
                d<0 ? -d : 0, /* Calculate number of places after decimal to print */
                (*q-48)*pow(10,--d), /* Calculate the digit at the desired power of 10 */
                q[1]?43:0) /* If the next character is still valid input, print the '+' */
            : 0 /* else, do nothing */
    }
}

2

Dyalog APL , 47 bytes

{×⍎⍵:1↓∊'+',¨0~⍨(⍎¨w)×10*(⍵⍳'.')-1+⍳≢w←⍵~'.'⋄0} 

Toma el número en forma de vector de caracteres, por ejemplo '123'.

Ejemplos:

      f←{×⍎⍵:1↓∊'+',¨0~⍨(⍎¨w)×10*(⍵⍳'.')-1+⍳≢w←⍵~'.'⋄0} 
      ↑⍕¨f¨,¨'0' '6' '0.99' '24601' '6.283' '900000.000009'
0                     
6                     
0.9 + 0.09            
20000 + 4000 + 600 + 1
6 + 0.2 + 0.08 + 0.003
900000 + 0.000009     

Notas:
○ La razón del último ejemplo modificado es que APL, como algunas de las otras presentaciones, por defecto cambiará a notación científica para tales números extremos.
○ La frase ↑⍕¨f¨,¨solo es necesaria para procesar todos los ejemplos a la vez.


1

Retina, 113 bytes

Actualmente es mucho más largo que la solución de Martin, pero utiliza un método diferente, así que decidí publicarlo.

^
x
S_`(?<=(.*)).(?=(.*))
x

¶\..*¶.*

$
¶
T`d`0`(?<=\d).*¶.*¶
(.*)¶(.*)¶
$2$1¶
(\..*?)0*¶
$1¶
\.?¶0*
¶
¶+
+
\+$
[empty line]

Pruébelo en línea aquí.


1

perl, 132 bytes

131 +1 para -pinterruptor.

Esto se basa en mi sedrespuesta anterior :

1while s/^([1-9]\d*)([1-9])(0*)([+.].*|)$/${1}0$3+$2$3$4/||s/([1-9]0*)\.([0-9])/$1+.$2/||s/\.(0*)([1-9])(\d*[1-9])$/.$1$2+.${1}0$3/

Banco de pruebas:

perl -pe'1while s/^([1-9]\d*)([1-9])(0*)([+.].*|)$/${1}0$3+$2$3$4/||
    s/([1-9]0*)\.([0-9])/$1+.$2/||s/\.(0*)([1-9])(\d*[1-9])$/.$1$2+.${1}0$3/
' <<<$'0\n6\n0.99\n24601\n6.283\n9000000.0000009\n3.1415'
0
6
0.9+.09
20000+4000+600+1
6+.2+.08+.003
9000000+.0000009
3+.1+.04+.001+.0005

1

Powershell - 172 166 193 bytes

Todo en una sola línea:

$z=([string]$args[0])-split"\.";$y=$z[0].length-1+0.6;($z|%{$x=[char[]]$_;if($y-gt0){($x|%{$_+"0"*(-1+$y--)})}else{($x|%{"0."+"0"*[math]::abs($y--)+$_})}}|?{-not($_-match'^[0.]+$')})-join' + '

Sin golf:

$z=([string]$args[0]) -split "\."
$y=$z[0].length-1+0.6
($z | %{
    $x=[char[]]$_
    if($y -gt 0) {
        ($x | %{$_+"0"*(-1+$y--)})
    } else {
        ($x | %{"0."+"0"*[math]::abs($y--)+$_})
    }
} | ?{ -not($_ -match '^[0.]+$')}) -join ' + '

Casos de prueba, más uno adicional:

PS> (0, 6, 0.99, 24601, 6.283, 9000000.0000009, [math]::pi) | %{.\expand.ps1 $_}

6
0.9 + 0.09
20000 + 4000 + 600 + 1
6 + 0.2 + 0.08 + 0.003
9000000 + 0.0000009
3 + 0.1 + 0.04 + 0.001 + 0.0005 + 0.00009 + 0.000002 + 0.0000006 + 0.00000005 + 0.000000003 + 0.0000000005 + 0.00 000000008 + 0.000000000009 + 0.0000000000007 + 0.00000000000009    
PS>



1

Perl, 248 bytes

Ew, soy novato en Perl golf.

@a=split/\./,<>;
@b=split``,$a[1];
@c=split``,$a[0];
for($i=0;$i<length$a[0];$i++){
   $_.=($c[$i]!=0)?$c[$i]."0"x((length$a[0])-$i-2)."+":"";
}
for($i=1;$i<=length$a[1];$i++){
   $_.=($b[$i-1]!=0)?"0."."0"x($i-1).$b[$i-1]."+":"";
}
chop;
($_=="")?print"0 ":print;

Pruébalo aquí


Esto parece no funcionar con números enteros.
F. Hauri

Puse el enlace de Ideone incorrecto. No tiene en cuenta los cambios realizados en el modo Editar. :( Debería funcionar ahora.
Paul Picard

Tienes un error en alguna parte: cuando lo ingreso 5, regreso 50.
F. Hauri

Extraño, ya que probé 5 con el enlace que proporcioné ayer después de que pusiste tu primer comentario. ¿Te importaría intentarlo ahora? (Cambié el enlace nuevamente)
Paul Picard

Acabo de probar su guión en mi intérprete perl (v5.20.2)
F. Hauri

1

Java, 284 244 243 bytes

String x(String s){int b=s.length(),d=(d=s.indexOf(46))<0?b:d,i=-1,k=0;String o="";for(char c;++i<b;)o+=(c=s.charAt(i))>48?(k++>0?" + ":"")+(d-i>0?c:"0.")+new String(new char[Math.abs(d-i)-1]).replace('\0','0')+(d-i>0?"":c):"";return b<2?s:o;}

Desafortunadamente, no pude encontrar una forma más corta de crear cadenas repetitivas que:

  • construir una char[]de la longitud requerida
  • utilizar Arrays.fillpara configurar los personajes
  • usar new Stringpara que se pueda concatenar

Con la inspiración de @Khaled A Khunaifer, podría eliminar 40 Bytes.

Editar: indexOftoma un int, por lo que podría reemplazar '.'con 46. Desafortunadamente, esto no parece ser posible conreplace .



@Khaled A Khunaifer Su solución parece tener problemas con casos de prueba de un solo dígito. Pero me gusta tu forma de generar los ceros.
ECS

corregir esta .replace('\0','0')función reemplazar esperar Stringno char, debería ser.replace("\0","0")
Khaled.K

@Khaled A Khunaifer Funciona en mis casos de prueba, también docs.oracle.com/javase/8/docs/api/java/lang/…
ECS

1

Python, 125 bytes

Después de eliminar mi primera respuesta (¡sry!) Que no podía manejar números pequeños debido a problemas con la máquina épsilon, encontré una solución diferente. Maneja tanto los flotantes como los enteros, ceros finales (!) Y se escribe como función.

¡Gracias a @ogaday por las sugerencias útiles y por el arreglo compacto '0'!

Golfizado:

def f(x):x+='.';i=x.find('.');z=list(x);del z[i];return'+'.join([str(int(o)*10**(i-j-1))for j,o in enumerate(z)if'0'<o])or'0'

Sin golf:

def f(x):
  x+='.'
  i=x.find('.')
  z=list(x)
  del z[i]   
  return '+'.join([str(int(o)*10**(i-j-1)) for j,o in enumerate(z) if '0'<o]) or '0'

Uso:

>>> f("0")
'0'

>>> f("32.005")
'30+2+0.005'

>>> f("100020003000009000000.0007")
'100000000000000000000+20000000000000000+3000000000000+9000000+0.0007'

>>> f("1000000000009000000.0007000000000000000002")
'1000000000000000000+9000000+0.0007+2e-22'

>>> f("0001.99")
'1+0.9+0.09'

1
Agradable. f('0')Sin embargo, falla el caso de prueba, y cuando copio y pego directamente en mi intérprete obtengo la notación científica (que creo que está bien). Además, list(c)es más corto. Si concatena el '.'antes de convertirlo en una lista, tampoco necesita agregarlo []. Usar en findlugar de índice en la cadena antes de convertirlo en una lista, después de agregar '.'también le ahorra un byte. Reordenar la desigualdad también le permite eliminar un espacio adicional:def f(x):x+='.';i=x.find('.');z=list(x);del z[i];return"+".join([str(int(o)*10**(i-j-1))for j,o in enumerate(z)if"0"<o])or'0'
Ogaday

1

CoffeeScript, 144 bytes

Solución directa:

X=(n)->[m,k]="#{n}".split '.';(c+Array(m.length-i).join 0for i,c of m when+c).concat(".#{Array(++i).join 0}"+c for i,c of k when+c).join('+')||0

Ejecutable:


1

Stax , 18 bytes

ºî≤FlφLfÜG→\ΦUq╜♥←

Ejecutar y depurarlo

Desempaquetado, sin golf y comentado, se ve así.

c           copy input
!C          terminate if input is falsy
y{          for each character in the string input...
  y.\d'0R   replace each digit in the input with "0"
  ia&       then replace the nth character back to its original value
  e         eval as float
m           map using block to produce array
{f          filter out zeroes
'+*         join with "+"

Ejecute este

Al igual que muchas de las otras soluciones publicadas, produce 9000000+9e-7para el último caso de prueba. Según el precedente establecido, esto está permitido porque el caso de prueba es demasiado preciso para el idioma.


0

Lua, 350 bytes

Creo que hay dos formas de jugarlo más:

  • Podría usar macro.definepara reemplazar algunas de las expresiones comunes (no puedo probar en este momento, y no estoy seguro de que me haga ganar algunos bytes)

  • Use dividir en el punto en lugar de iterar en toda la cadena. Una vez más, no estoy seguro de que reduciría el tamaño de esta función, ya que manipular cadenas en lua es bastante doloroso.

function f(s)v,r=s:find("%.")or#s+1,""if #s==1 then return s end for i=1,#s do a=""(v>i and s:sub(i,v-1)or s:sub(v,i)):gsub(".",function(c)a=a..(not a:find(c)and(c==s:sub(i,i)or c==".")and c or 0)end)s,r=v<i and s:sub(0,i-1).."0"..s:sub(i+1,#s)or s,r..((#a==a:find("%.")or tonumber(a)==0)and""or a:gsub("%.","0.")..(i~=#s and"+"or""))end return r end

Explicaciones

function f(s)
  v=s:find("%.")or #s+1               -- v=index of the dot in a decimal number
  r=""                                -- v=#s+1 when s is an integer(v=0 would screw sub())
  if #s==1 then return s end          -- exit if s is a single digit
  for i=1,#s                          -- iterate over s
  do
    a=""

    (v>i and s:sub(i,v-1)or s:sub(v,i)-- only send the integer OR decimal part to gsub
      ):gsub(".",function(c)          -- iterate over each character of s:sub()

    -- a contains the next number to be concatenated to the string r(the one to be returned)
      a=a..(not a:find(c)             -- we concatenate a with c if a doen't contains
        and(c==s:sub(i,i)or c==".")   -- c, and c is either a dot, or the next number
             and c or 0)              -- to be add, we put a 0 otherwise
    end)
    -- we concatenate the new a with the string already formed
    r=r..((#a==a:find("%.")           -- if a=="." or a's value is 0
            or tonumber(a)==0)and""   -- we concatenate an empty string
      or a:gsub("%.","0.")            -- else, we replace the (possible) leading dot by "0."
      ..(i~=#s and"+"or""))           -- and concatenate a "+" if it isn't the last number to be added

    s=v<i and s:sub(0,i-1)            -- We then replace the digit we have worked with
      .."0"..s:sub(i+1,#s)or s        -- to prevent duplicates
  end
  return r
end

Puede probar lua en línea y usar el siguiente código fuente para ejecutarlo con algunos casos de prueba

function f(s)v,r=s:find("%.")or#s+1,""if #s==1 then return s end for i=1,#s do a=""(v>i and s:sub(i,v-1)or s:sub(v,i)):gsub(".",function(c)a=a..(not a:find(c)and(c==s:sub(i,i)or c==".")and c or 0)end)s,r=v<i and s:sub(0,i-1).."0"..s:sub(i+1,#s)or s,r..((#a==a:find("%.")or tonumber(a)==0)and""or a:gsub("%.","0.")..(i~=#s and"+"or""))end return r end

print(f("3123.12333"))
print(f("9545"))
print(f("9000000.0000009"))
print(f("6"))

0

C, 253 bytes

m(char*i){int k,j=0,s=0,d=0;while(i[s])s++;while(i[d]!=46)d++;while(j<d){if(i[j]!=48){for(k=0;k<(d-j);k++)putchar(k?48:i[j]);putchar(43);}j++;}while(++j<s)if(i[j]!=48){putchar(46);for(k=0;k<(j-d);k++)putchar(k==(j-d-1)?i[j]:48);putchar(43);}putchar(8);}

Nota: putchar(8)debe realizar un retroceso.

 Input: 1230.0456
Output: 1000+200+30+.04+.005+.0006

Detallado , prueba aquí

while(i[s]) s++;
while(i[d]!=46) d++;

while (j<d)
{
    if (i[j]!='0')
    {
        for(k=0;k<(d-j);k++) putchar(k? '0': i[j]);
        putchar(43);
    }
    j++;
}

while (++j<s)
if (i[j]!='0')
{
    putchar(46);
    for(k=0; k<(j-d); k++) putchar(k==(j-d-1)? i[j]: '0');
    putchar(43);
}

putchar(8);

0

sed, 136 bytes

Reducido en 8 caracteres al dejar caer espacios e inútil 0.

:;s/^([1-9][0-9]*)([1-9])(0*)([+.].*|)$/\10\3+\2\3\4/;s/([1-9]0*)\.([0-9])/\1+.\2/;s/\.(0*)([1-9])([0-9]*[1-9])$/.\1\2+.\10\3/;t

Casos de prueba:

sed -r ':;
    s/^([1-9][0-9]*)([1-9])(0*)([+.].*|)$/\10\3+\2\3\4/;
    s/([1-9]0*)\.([0-9])/\1+.\2/;
    s/\.(0*)([1-9])([0-9]*[1-9])$/.\1\2+.\10\3/;
    t' <<<$'0\n6\n0.99\n24601\n6.283\n9000000.0000009\n3.1415'
0
6
0.9+.09
20000+4000+600+1
6+.2+.08+.003
9000000+.0000009
3+.1+.04+.001+.0005

0

JavaScript (ES7), 114 bytes

s=>(p=s.search(/.\b/),i=-1,[for(c of s)if((i++,c>0))(z=s.substring(i,p).replace(/d/g,0),i<p?c+z:z+c)].join`+`||s

Funciona con números de longitud arbitrarios porque utiliza la manipulación de cadenas en todo momento.

Sin la comprensión de la matriz (122 bytes):

s=>[...s].map((c,i)=>c<'1'?'':(z=s.substring(i,p).replace(/\d/g,0),i<p?c+z:z+c),p=s.search(/.\b/)).filter(x=>x).join`+`||s

Sin golf:

function expand(s) {
    zeros = s.replace(/\d/g, "0");
    point = s.indexOf(".");
    if (point < 0) point = s.length;
    result = [];
    for (i = 0; i < s.length; i++) {
        if (s[i] > "0") {
            if (i < point) result.push(s[i] + zeros.slice(i, point - 1));
            else result.push(zeros.slice(point - 1, i) + s[i]);
         }
     }
     return result.length ? result.join("+") : s;
}

Hasta donde sé, esta nueva sintaxis de comprensión de matriz es de ECMAScript 7.
manatwork

@manatwork Gracias, lo actualicé mientras agregaba la versión sin golf.
Neil

0

R - 133 bytes

Robusto, ignora Machine Epsilon y trabaja también con ceros finales.

a) Golfizado:

f=function(x)if(x=='0')x else{z=strsplit(x,'')[[1]];i=which(z=='.');n=as.numeric(z[-i])*10^(i-seq(z)[-1]);paste(n[n>0],collapse='+')}

Sin golf:

f=function(x)
  if(x=='0') 
    x 
  else {
    z=strsplit(x,'')[[1]]
    i=which(z=='.')   
    n=as.numeric(z[-i])*10^(i-seq(z)[-1])  
    paste(n[n>0],collapse='+')
  }

Uso:

f("900.008")
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.