Expanda o número


58

Você pode se lembrar da primeira ou da segunda série usando o formulário expandido para aprender sobre o valor de posição dos números. É mais fácil explicar com um exemplo, então considere o número 123. Em forma expandida, é representado como 100 + 20 + 3, o que ajuda uma mente jovem a visualizar o valor do local. É uma reminiscência de como você diz: cento (mais) vinte (mais) três.

Podemos estender isso além do local das unidades com decimais: 2.718 => 2 + 0.7 + 0.01 + 0.008

Seu desafio é escrever um programa ou função que tenha um número de ponto flutuante positivo ou zero (suponha que seja tão grande ou preciso quanto o seu idioma possa suportar; não será em notação científica) ou string e o imprime / retorna em formato expandido como explicado acima.

Você não precisa de espaços entre +zero e zero antes da vírgula decimal, portanto o exemplo acima pode ser 2+.7+.01+.008. Valores que seriam iguais a zero devem ser omitidos ( 101.01 => 100 + 1 + 0.01), a menos que a entrada seja zero (veja abaixo).

Os valores não devem ter mais de um zero inicial antes do ponto decimal ou qualquer zero posterior a ele (não-não:) 0060, 0000.2, 30., 30.000, .0400. A entrada também estará em conformidade com isso.

Como os alunos da primeira série têm curtos períodos de atenção, seu código deve ser o mais curto possível.

Casos de teste

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 "Como os alunos da primeira série têm curtos períodos de atenção, seu código deve ser o mais curto possível".
Downgoat 9/01/16

2
@ Doᴡɴɢᴏᴀᴛ feliz em ver o meme ainda está em execução.
gato

4
Seria engraçado fazê-lo da mesma maneira que nós (franceses) contamos, ver as pessoas lutando com o caso de 97 (4 * 20 + 10 + 7) ^^ #
23416

2
@ jimmy23013 Sim, desde que funcione em teoria.
precisa saber é o seguinte

1
@ Hoje não sei, são apenas alguns casos extremos. Talvez o caminho do NBZ fosse melhor, mas ainda assim, não, se isso realmente seria interessante #
21416

Respostas:


6

CJam, 33 26 bytes

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

Isso não funcionará com o intérprete Java; a impressão flutua de maneira diferente. Experimente com o intérprete CJam .

O último caso de teste é impresso 9000000+9e-7, que foi considerado válido por @NinjaBearMonkey .

Graças a @ jimmy23013 por jogar fora 7 bytes!

Como 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.

Com base na mesma ideia: r_ee\'0fe<f{\~t~}{},'+*0e|.
precisa saber é o seguinte

@ jimmy23013 Uau, isso é curto! Obrigado!
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`+`

Explicação

Requer que o número seja inserido como uma sequência sem zeros à esquerda (a menos que o número seja 0 claro).

Nota: Devido à estranheza de ponto flutuante, alguns números (como .3) saem errados, mas teoricamente isso funciona para qualquer 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 +

Teste

O teste usa em Math.powvez de **compatibilidade com o navegador.


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

@ETHproductions Se o número de entrada for menor do 1que seria quebrado Math.log10(n), retornaria um número negativo e |0arredondaria para zero em vez de para o piso.
user81655

Você pode usar em 0|Math.log10(n),p-=p<0vez de Math.floor(Math.log10(n))?
Dom Hastings

1
@DomHastings Quase. Ele falha n<1porque o 0|fará pigual 0para ambos 0.1e -0.1. A maneira mais curta que consigo pensar é p=Math.log10(n),p=p-(p<0)|0qual é o mesmo comprimento que o uso Math.floor. :(
user81655

@DomHastings Ainda não funcionaria de n=0.1qualquer maneira.
Neil

5

Retina , 86 77 75 bytes

A contagem de bytes assume que a fonte está codificada como ISO 8859-1.

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

O avanço de linha à direita é significativo.

Experimente online.

Explicação

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

Começamos transformando a entrada em uma lista separada de componentes de alimentação de linha, embora apenas o dígito inicial (ou final) esteja correto. Isso é feito abusando de um estágio dividido. Em vez de dividir a entrada, combinamos tudo, de modo que os segmentos restantes estão todos vazios. Removemos esses segmentos vazios com a _opção O problema é que os estágios divididos também retornam os valores de todos os grupos de captura. Por isso, usamos um lookahead em cada partida para capturar a parte correta da string: primeiro tentamos encontrar a .esquerda da partida. Se for esse o caso, capturamos tudo, desde o.até e incluindo o dígito que estamos correspondendo no momento. Caso contrário, devemos estar na parte inteira da entrada, portanto capturamos todos os números após a correspondência (incluindo a correspondência). Também devemos nos livrar do próprio ponto decimal, para que a segunda captura seja opcional. Se não houver \dcaptura, isso simplesmente removerá a correspondência da entrada.

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

Agora usamos um estágio de transliteração para transformar todos, exceto os dígitos iniciais / finais, em zeros. Combinamos um componente menor que 1 com \..+\Bonde \Bgarante que paramos a correspondência de um dígito antes do final, ou uma parte inteira com (?<=^\d).+a aparência da parte traseira garante que iniciemos um dígito no número. O estágio de transliteração substituirá quaisquer dígitos ( d) por zeros nas correspondências.

¶([.0]+¶)*
+

Agora, o formato de saída real +não deve usar alimentações de linha como separadores. As partidas um avanço de linha para fazer essa substituição. Enquanto estamos nisso, também removemos linhas que contêm apenas 0s e .s.

^0.|\+0$

O estágio anterior não remove um avanço ou um resultado final 0(porque eles não têm um avanço de linha antes e depois deles), portanto, nós os removemos explicitamente.


4

Python 2, 216 210 196 175 bytes

Aqui está um código levemente golfe que eu vou jogar ainda mais quando tiver tempo. Ele usa análise de strings.

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

Explicação

Portanto, a entrada é separada em uma parte inteira e decimal. Depois, existe uma compreensão da lista de loop for. Na parte inteira, o comprimento da sequência após um caractere no decimal é multiplicado por "0" para obter tantos zeros no final, se esse caractere.

Para a parte decimal, o índice do caractere atual é o número de zeros antes dele e, portanto, essa parte é simples.

A tentativa e a exceção são usadas para determinar se ela possui uma parte decimal ou não (usando um erro).

O resultado final é acompanhado por sinais de mais.

Experimente aqui!


2
Eu acho que o if o else ["0"]pode ser o or["0"].
precisa saber é o seguinte

Você tem um espaço à direita na linha quatro que aumenta sua contagem de bytes. Na linha quatro, você precisa apenas de dois pontos. Você pode excluir os espaços nos seguintes trechos: o=[(...)] for, e(I) if, e(i[1]) if, print "+", e o parêntese exterior o=[(...), bem como, na verdade. Finalmente, você pode tirar o condicional final da função de junção da seguinte maneira: print"+".join(o)or"0"porque o join retornará uma lista vazia se oestiver vazia; portanto, o condicional avaliará da mesma maneira que economiza um byte.
Ogaday

3

Pitão, 30 bytes

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

Suíte de teste

A solução básica aqui é substituir todos os dígitos da entrada por e 0, em seguida, inserir cada dígito no local apropriado, avaliar, filtrar os zeros e juntar-se às vantagens. Infelizmente, a função de avaliação de Pyth não aceita zeros à esquerda atualmente. Eu vou trabalhar para corrigir isso.

Para superar esse problema, adicionei uma função auxiliar y, que tenta recursivamente a avaliação até que nenhum erro seja gerado, removendo o primeiro dígito toda vez. Observe que esta função fará um loop infinito na entrada inválida.

Além disso, era necessário um caso especial para a entrada 0.

Em suma, acho que o código é muito bom, mas as instalações de idiomas podem ser melhores. Quem quer erros?


3

Python 3, 138

Isso é vagamente baseado na abordagem de TanMath / Ogaday de ler o número como uma string e analisá-lo dessa maneira. Eu tenho que usar a atribuição de estrelas ipara que ele manipule corretamente números inteiros.

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 ainda é relativamente legível. Converta em string e manipule os >1dígitos separadamente dos <1dígitos. Também temos um caso especial para zero. Eu poderia remover mais dois espaços abaixo, mas eu gosto de mantê-lo bonito.

A desvantagem é que ele será dividido em carros alegóricos com mais de 9 casas decimais.

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)

Abaixo está o original. A primeira edição foi encurtar o caso especial zero, a segunda edição foi remover o 0 antes do decimal, a terceira foi remover alguns parênteses e espaços extras.

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

Explicação:

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

Você não precisa incluir todas as revisões do seu código; se quisermos ver seu progresso no golfe, podemos ver o histórico de revisões. A propósito, bem-vindo ao PPCG!
precisa saber é o seguinte

1
Acabei de descobrir ... Vou ter que tentar não gastar muito tempo neste site!
speedplane

2

Mathematica, 81 bytes

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

Caso de teste:

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

3
Eu não acho que ter o ponto decimal sobre as partes inteiras é permitido.
Martin Ender

2

CJam, 44 bytes

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

Experimente aqui.

Ele falha no último caso de teste e gera o seguinte:

9000000+9e-7

Mas digamos que seja muito preciso que o CJam não possa lidar com isso.

Explicação

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

Consegui jogar uns bons 19 bytes de golfe graças às sugestões de @Thomas Kwa acima result or['0'], além de reorganizar uma á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

Minha melhor tentativa até agora ( 173 bytes ). Com base na nova abordagem, consulte o final da postagem:

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]

reduziu o meu original até 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]

Eu aprendi um novo recurso de idioma hoje fazendo isso! Condicionais via indexação booleana. Eu posso ter exagerado um pouco.

Tentei abstrair as compreensões, mas não consegui reduzi-las ( 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))]

(Inverter sequências é caro!)

Enquanto o meu é mais curto por agora, acho que TanMath pode golfe seu baixo para coincidir com o meu: Usando e=enumerate, substituindo passcom 0, e usar '0'no lugar de ['0']na instrução de retorno deve salvar 4 + 3 + 2 = 9 bytes! Levando-o para 187. Tenho certeza de que mais alguns bytes podem ser removidos em algum lugar ...

editar Nova abordagem ( 156 bytes ). No entanto, ele só pode lidar com precisão de até 6dp, semelhante à entrada CJam de @ jimmy23013, por isso falha no teste final. Não consegui forçá-lo a imprimir mais 0s, talvez alguém possa. Em vez disso, usei-o como base da minha melhor tentativa até o momento, veja top (Além disso, essa abordagem imprime o 0 antes da casa decimal, mas isso também parece válido.). try:... except:...Adotou a abordagem do 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] 

Se você está tentando me ajudar no golfe, inclua-os como comentários à minha resposta, não na sua resposta. Eu nem sempre vejo suas respostas, então, escrevendo um comentário, receberei uma notificação e definitivamente a veremos.
precisa saber é o seguinte

2
Olá @TanMath. Eu gostaria, mas ainda não tenho representante suficiente para comentar as postagens de outras pessoas. Depois que eu conseguir mais alguns upboats, deixarei comentários nos comentários.
Ogaday

2

festa pura, 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}

ou

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}

Teste:

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

Uma função recursiva muito, muito bagunçada, provavelmente não é a melhor maneira de fazer isso. Entrada como f("10.0203").


Isso é mesmo Python? Adoro.
Ogaday

2

C, 155 153 161 bytes

+2 para vincular na biblioteca de matemática (a fonte em si é 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;}

Ungolfed

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 número na forma de vetor de caracteres, por exemplo '123'.

Exemplos:

      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:
○ O motivo do último exemplo modificado é que o APL, como alguns dos outros envios, por padrão mudará para notação científica para números tão extremos.
○ A frase ↑⍕¨f¨,¨é necessária apenas para processar todos os exemplos de uma só vez.


1

Retina, 113 bytes

Atualmente muito mais tempo que a solução de Martin, mas usa um método diferente, então decidi publicá-la.

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

¶\..*¶.*

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

Experimente online aqui.


1

perl, 132 bytes

131 +1 para -pswitch.

Isso é baseado na minha sedresposta 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/

Suíte de teste:

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

Tudo em uma única linha:

$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' + '

Ungolfed:

$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 teste, mais um 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

Ei, eu sou noobish no golfe Perl.

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

Experimente aqui.


Isso parece não funcionar com números inteiros.
F. Hauri

Coloquei o link Ideone errado. Ele não leva em consideração as alterações feitas no modo de edição. :( Deve funcionar agora.
Paul Picard

Você tem um erro em algum lugar: quando eu entrar 5, retorne 50.
F. Hauri 20/01

Estranho, desde que testei 5 com o link que forneço ontem depois de colocar seu primeiro comentário. Mente tentando agora? (Alterei o link novamente)
Paul Picard

Acabei de testar seu script no meu 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;}

Infelizmente, não foi possível encontrar uma maneira mais curta de criar Strings repetidas do que:

  • construir um char[]do comprimento necessário
  • use Arrays.fillpara definir os caracteres
  • use new Stringpara que possa ser concatenado

Com inspiração de @Khaled A Khunaifer, eu poderia economizar 40 bytes.

Edit: indexOfleva um int, então eu poderia substituir '.'por 46. Infelizmente, isso não parece ser possível com replace.


Eu consegui reduzi
Khaled.K

@Khaled A Khunaifer Sua solução parece ter problemas com casos de teste de um dígito. Mas eu gosto da sua maneira de gerar os zeros.
ECS

corrigir esta .replace('\0','0')função substituir Stringnão esperar char, deve ser.replace("\0","0")
Khaled.K

@Khaled A Khunaifer Funciona nos meus casos de teste, também docs.oracle.com/javase/8/docs/api/java/lang/…
ECS

1

Python, 125 bytes

Depois de excluir minha primeira resposta (sry!), Que não conseguia lidar com pequenos números devido a problemas de epsilon da máquina, encontrei uma solução diferente. Ele lida com float e números inteiros, zeros à direita (!) E é escrito como função.

Obrigado ao @ogaday pelas dicas úteis e pela compacta correção '0'!

Golfe:

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'

Ungolfed:

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
Agradável. f('0')No entanto, falha no caso de teste e, quando copio e colo diretamente no meu intérprete, recebo a notação científica (que acho que está bem). Além disso, list(c)é mais curto. Se você concatenar o '.'antes de transformá-lo em uma lista, também não precisará adicionar []. Usar em findvez do índice na cadeia de caracteres antes de transformá-la em uma lista, depois de adicionar, '.'também economiza um byte. Reordenar a desigualdade também permite que você remova um espaço 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 26/01

1

CoffeeScript, 144 bytes

Solução direta:

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

Executável:


1

Stax , 18 bytes

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

Execute e depure

Descompactado, não jogado e comentado, parece com isso.

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 "+"

Execute este

Como muitas das outras soluções postadas, ela produz 9000000+9e-7para o último caso de teste. De acordo com o precedente estabelecido, isso é permitido porque o caso de teste é muito preciso para o idioma.


0

Lua, 350 bytes

Eu acho que há duas maneiras de jogar ainda mais:

  • Eu poderia fazer uso de macro.define para substituir algumas expressões comuns (não posso testar agora e não tenho certeza se isso me faria ganhar alguns bytes)

  • Use divisão no ponto em vez de iterar em toda a cadeia. Mais uma vez, não tenho certeza se isso reduziria o tamanho dessa função, pois manipular string em lua é 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

Explicações

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

Você pode testar o lua online e usar o seguinte código-fonte para executá-lo com alguns casos de teste

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)deve executar um backspace.

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

Detalhado , tente aqui

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 128 bytes

Reduzido em 8 caracteres, largando espaços 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 teste:

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 com números arbitrários de comprimento, porque usa manipulação de strings por toda parte.

Sem a compreensão da 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

Ungolfed:

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

Tanto quanto eu sei, esta nova sintaxe de matriz compreensão é de ECMAScript 7.
manatwork

@manatwork Obrigado, eu atualizei enquanto adicionava a versão não-destruída.
Neil

0

R - 133 bytes

Robusto, ignora o Machine Epsilon e funciona também com zeros à direita.

a) Golfe:

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='+')}

Ungolfed:

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")
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.