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.