Espandi il numero


58

Potresti ricordare in prima o seconda elementare utilizzando la forma estesa per conoscere il valore del numero dei posti. È più facile da spiegare con un esempio, quindi considera il numero 123. In forma espansa è rappresentato come 100 + 20 + 3, il che aiuta una mente giovane a visualizzare il valore del luogo. Ricorda come lo dici: cento (più) venti (più) tre.

Possiamo estendere questo passato il posto delle unità con i decimali: 2.718 => 2 + 0.7 + 0.01 + 0.008

La tua sfida è scrivere un programma o una funzione che prenda un numero in virgola mobile positivo o zero (supponi che sia grande o preciso come la tua lingua può gestire; non sarà in notazione scientifica) o stringa e lo stampa / restituisce in forma espansa come spiegato sopra.

Non hai bisogno di spazi tra +'s né lo zero prima del punto decimale, quindi l'esempio sopra potrebbe essere 2+.7+.01+.008. I valori che sarebbero uguali a zero devono essere omessi ( 101.01 => 100 + 1 + 0.01) a meno che l'ingresso sia zero (vedere sotto).

I valori non devono avere più di uno zero iniziale prima del punto decimale o eventuali zero finali dopo di esso (no-no:) 0060, 0000.2, 30., 30.000, .0400. Anche l'input sarà conforme a questo.

Dal momento che gli alunni della prima elementare hanno brevi periodi di attenzione, il tuo codice dovrà essere il più breve possibile.

Casi test

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 per "Dato che gli alunni della prima elementare hanno brevi periodi di attenzione, il tuo codice dovrà essere il più breve possibile."
Downgoat,

2
@ Doᴡɴɢᴏᴀᴛ felice di vedere che il meme è ancora in esecuzione.
gatto

4
Sarebbe divertente farlo allo stesso modo in cui contiamo (in francese), vedere le persone lottare con il caso 97 (4 * 20 + 10 + 7) ^^
Katenkyo,

2
@ jimmy23013 Sì, purché funzioni in teoria.
NinjaBearMonkey il

1
@Ogaday non lo so, sono solo alcuni casi limite. Forse il modo NBZ sarebbe meglio, ma ancora no se fosse davvero interessante
Katenkyo,

Risposte:


6

CJam, 33 26 byte

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

Questo non funzionerà con l'interprete Java; stampa galleggia in modo diverso. Provalo con l' interprete CJam .

Viene stampato l'ultimo caso di test 9000000+9e-7, che è stato dichiarato valido da @NinjaBearMonkey .

Grazie a @ jimmy23013 per giocare a golf con 7 byte!

Come funziona

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.

Sulla base della stessa idea: r_ee\'0fe<f{\~t~}{},'+*0e|.
jimmy23013,

@ jimmy23013 Wow, è breve! Grazie!
Dennis,

5

JavaScript (ES7), 102 byte

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

Spiegazione

Richiede che il numero sia inserito come stringa senza zeri iniziali (a meno che il numero non sia 0 ovviamente).

Nota: a causa della stranezza in virgola mobile alcuni numeri (come .3) risultano errati, ma in teoria questo funziona per qualsiasi numero.

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 +

Test

Test utilizza Math.powinvece che **per la compatibilità del browser.


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

@ETHproductions Se il numero di input è inferiore a quello 1che si spezzerebbe perché Math.log10(n)restituirebbe un numero negativo e si |0arrotonda verso zero invece di pavimentazione.
user81655

Puoi usare 0|Math.log10(n),p-=p<0invece di Math.floor(Math.log10(n))?
Dom Hastings,

1
@DomHastings Quasi. Non riesce n<1perché 0|farà puguali 0per entrambi 0.1e -0.1. Il modo più breve a cui riesco a pensare p=Math.log10(n),p=p-(p<0)|0è la stessa lunghezza dell'uso Math.floor. :(
user81655

@DomHastings Ancora non funzionerebbe n=0.1comunque.
Neil,

5

Retina , 86 77 75 byte

Il conteggio dei byte presuppone che la sorgente sia codificata come ISO 8859-1.

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

L'alimentazione di linea finale è significativa.

Provalo online.

Spiegazione

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

Iniziamo trasformando l'input in un elenco separato di componenti di avanzamento riga, sebbene solo la cifra iniziale (o finale) sia corretta. Questo viene fatto abusando di una fase divisa. Invece di dividere l'input, ne abbiniamo tutto, quindi i segmenti rimanenti sono tutti vuoti. Rimuoviamo quei segmenti vuoti con l' _opzione. Il problema è che le fasi divise restituiscono anche i valori di tutti i gruppi di acquisizione. Quindi utilizziamo un lookahead ad ogni partita per catturare la parte corretta della stringa: prima proviamo a trovare una .sinistra della partita. In tal caso, catturiamo tutto dal.fino alla cifra che stiamo attualmente abbinando inclusa. Altrimenti, dobbiamo essere nella parte intera dell'input, quindi acquisiamo tutti i numeri dopo la corrispondenza (inclusa la corrispondenza). Dobbiamo anche eliminare il punto decimale stesso, quindi la seconda acquisizione è facoltativa. Se non è \dnecessario acquisire, ciò rimuoverà semplicemente la corrispondenza dall'input.

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

Ora usiamo una fase di traslitterazione per trasformare tutti tranne le cifre iniziali / finali in zero. O abbiniamo un componente che è inferiore a 1 con il \..+\Bquale \Bgarantisce che interrompiamo la corrispondenza di una cifra prima della fine, oppure (?<=^\d).+abbiniamo una parte intera con la quale il lookbehind assicura che iniziamo una cifra nel numero. La fase di traslitterazione sostituirà quindi qualsiasi cifra ( d) con zero all'interno delle partite.

¶([.0]+¶)*
+

Ora il formato di output effettivo dovrebbe utilizzare +non linefeed come separatori. L' corrisponde un avanzamento riga per farlo sostituzione. Mentre noi siamo, togliamo anche le linee che contengono solo 0S e .s.

^0.|\+0$

La fase precedente non rimuove un inizio o una fine 0(perché quelli non hanno un avanzamento di riga prima e dopo di essi), quindi li rimuoviamo esplicitamente.


4

Python 2, 216 210 196 175 byte

Ecco qualche codice leggermente golfato che giocherò ulteriormente quando avrò tempo. Utilizza l'analisi delle stringhe.

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

Spiegazione

Pertanto, l'input è separato in un numero intero e in una parte decimale. Quindi, c'è una comprensione dell'elenco di loop. Nella parte intera, la lunghezza della stringa dopo un carattere in decimale viene moltiplicata per "0" per ottenere tanti zeri alla fine se quel carattere.

Per la parte decimale, l'indice del carattere corrente è il numero di zeri prima di esso e quindi quella parte è semplice.

Il tentativo e salvo è usato per determinare se ha una parte decimale o meno (usando un errore).

Il risultato finale è unito a segni più.

Provalo qui!


2
Penso che o if o else ["0"]possa essere o or["0"].
Lirtosiast

Hai uno spazio finale sulla riga quattro che si aggiunge al conteggio dei byte. Alla quarta riga hai bisogno solo di due punti. È possibile eliminare gli spazi nei seguenti frammenti: o=[(...)] for, e(I) if, e(i[1]) if, print "+", e la parentesi esterno o=[(...)come pure, in realtà. Infine, puoi togliere il condizionale finale dalla funzione join in questo modo: print"+".join(o)or"0"poiché join restituirà un elenco vuoto se oè vuoto, quindi il condizionale valuterà allo stesso modo risparmiando un byte.
Ogaday,

3

Pyth, 30 byte

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

Suite di test

La soluzione di base qui è sostituire tutte le cifre nell'input con 0, quindi inserire ogni cifra nella posizione corretta, valutare, filtrare gli zeri e unire i vantaggi. Sfortunatamente, la funzione eval di Pyth al momento non accetta zeri iniziali. Lavorerò per risolvere questo problema.

Per ovviare a questo problema, ho aggiunto una funzione di supporto y, che riprova in modo ricorsivo eval fino a quando non viene generato alcun errore, rimuovendo la prima cifra ogni volta. Si noti che questa funzione eseguirà il ciclo all'infinito su input non validi.

Inoltre, era necessario un caso speciale per l'input 0.

Tutto sommato, penso che il codice sia abbastanza buono, ma le strutture linguistiche potrebbero essere migliori. Chi vuole errori?


3

Python 3, 138

Questo è vagamente basato sull'approccio di TanMath / Ogaday di leggere il numero come una stringa e analizzarlo in quel modo. Devo usare l'assegnazione delle stelle in imodo che gestisca correttamente i numeri interi.

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 byte

Questo è ancora relativamente leggibile. Converti in stringa e gestisci le >1cifre separatamente dalle <1cifre. Abbiamo anche un caso speciale per zero. Potrei rimuovere altri due spazi in basso, ma mi piace tenerlo carino.

Il rovescio della medaglia è che si romperà per i float con più di 9 decimali.

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)

Di seguito è riportato l'originale. La prima modifica è stata per abbreviare il caso speciale zero, la seconda modifica è stata quella di rimuovere lo 0 prima del decimale, il terzo è stato quello di rimuovere alcune parentesi e spazi extra.

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

Spiegazione:

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

Non è necessario includere ogni revisione del codice; se vogliamo vedere i tuoi progressi nel golf, possiamo guardare la cronologia delle revisioni. A proposito, benvenuto in PPCG!
lirtosiast

1
L'ho appena scoperto ... Proverò a non passare troppo tempo su questo sito!
speedplane il

2

Mathematica, 81 byte

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

Caso di prova:

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

3
Non penso che sia consentito il punto decimale sopra le parti intere.
Martin Ender

2

CJam, 44 byte

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

Provalo qui.

Non supera l'ultimo caso di test e genera quanto segue:

9000000+9e-7

Ma diciamo che è troppo preciso che CJam non può gestirlo.

Spiegazione

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 byte

Gestito a golf con ben 19 byte di sconto grazie ai suggerimenti di @Thomas Kwa sopra result or['0'], oltre a riorganizzare l'algebra ( 154 byte ):

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

Il mio miglior tentativo finora ( 173 byte ). Basato sul nuovo approccio, vedi in fondo al post:

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]

golfato il mio originale fino a 180 byte :

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]

Oggi ho imparato una nuova funzione linguistica facendo questo! Condizionali tramite indicizzazione booleana. Potrei averlo leggermente esagerato.

Ho provato a sottrarre le comprensioni, ma non sono riuscito a renderlo più breve ( 196 byte ):

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

(Invertire le sequenze è costoso!)

Mentre il mio è più breve, per ora, penso TanMath può golf il suo giù per abbinare la mia: Utilizzando e=enumerate, sostituendo passcon 0, ed usando '0'al posto di['0'] nell'istruzione return dovrebbe salvare 4 + 3 + 2 = 9 byte! Portandolo a 187. Sono sicuro che altri byte possono essere rasati da qualche parte ...

modifica Nuovo approccio ( 156 byte ). Tuttavia, può gestire solo una precisione fino a 6dp simile alla voce CJam di @ jimmy23013, quindi non supera il test finale. Non potrei forzarlo per stampare più 0, forse qualcun altro può. Invece l'ho usato come base del mio miglior tentativo ancora, vedi in alto (Inoltre, questo approccio stampa lo 0 prima del decimale, ma sembra valido anche questo.). Ha preso l' try:... except:...approccio da 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 stai cercando di darmi un aiuto nel golf, ti preghiamo di includerli come commenti alla mia risposta, non nella tua risposta. Non vedo sempre le tue risposte, quindi scrivendo un commento, riceverò una notifica e sicuramente la vedrò.
TanMath,

2
Ciao @TanMath. Lo farei, ma non ho abbastanza rappresentante per commentare i post di altre persone. Una volta che avrò qualche altro upboat mi assicurerò di lasciare un feedback nei commenti.
Ogaday,

2

bash puro, 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}

Test:

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 byte

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 funzione ricorsiva davvero disordinata, probabilmente non è il modo migliore per farlo. Inserisci come f("10.0203").


Anche questo è Python? Lo adoro.
Ogaday,

2

C, 155 153 161 byte

+2 per il collegamento nella libreria matematica (la fonte stessa è 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 byte

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

Prende il numero in forma di carattere vettoriale, ad es '123'.

Esempi:

      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     

Note:
○ Il motivo dell'ultimo esempio modificato è che l'APL, come alcuni degli altri invii, passa automaticamente alla notazione scientifica per tali numeri estremi.
○ La frase ↑⍕¨f¨,¨è necessaria solo per elaborare tutti gli esempi contemporaneamente.


1

Retina, 113 byte

Attualmente molto più lungo della soluzione di Martin, ma utilizza un metodo diverso, quindi ho deciso di pubblicarlo.

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

¶\..*¶.*

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

Provalo online qui.


1

perl, 132 byte

131 +1 per -pinterruttore.

Questo si basa sulla mia sedrisposta precedente :

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/

Suite di test:

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 byte

Tutto su un'unica riga:

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

Casi di prova, più un ulteriore:

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 byte

Eh, io sono noobish al golf 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;

Provalo qui.


Questo sembra non funzionare con numeri interi.
F. Hauri,

Ho inserito il link Ideone sbagliato. Non tiene conto delle modifiche apportate in modalità Modifica. :( Ora dovrebbe funzionare.
Paul Picard,

Hai un errore da qualche parte: quando entro 5, ritorna 50.
F. Hauri,

Strano, dal momento che ho provato 5 con il link che ho fornito ieri dopo aver inserito il tuo primo commento. Ti dispiace provare ora? (Ho cambiato di nuovo il link)
Paul Picard,

Ho appena testato la tua sceneggiatura sul mio interprete perl (v5.20.2)
F. Hauri,

1

Giava, 284 244 243 byte

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

Sfortunatamente, non sono riuscito a trovare un modo più breve di creare stringhe ripetute rispetto a:

  • costruire una char[]della lunghezza richiesta
  • usare Arrays.fillper impostare i personaggi
  • utilizzare in new Stringmodo che possa essere concatenato

Con l'ispirazione di @Khaled A Khunaifer, ho potuto radere via 40 byte.

Modifica: indexOfprende un int, quindi potrei sostituirlo '.'con 46. Sfortunatamente, questo non sembra essere possibile con replace.


Sono riuscito a ridurlo a 250, controlla ideone.com/HqLnMo
Khaled.K

@Khaled A Khunaifer La tua soluzione sembra avere problemi con i casi di test a una cifra. Ma mi piace il tuo modo di generare gli zeri.
ECS

correggere questa .replace('\0','0')funzione sostituire aspettarsi di Stringno char, dovrebbe essere.replace("\0","0")
Khaled.K

@Khaled A Khunaifer Funziona nei miei casi di test, anche docs.oracle.com/javase/8/docs/api/java/lang/…
ECS

1

Python, 125 byte

Dopo aver eliminato la mia prima risposta (sry!) Che non riusciva a gestire piccoli numeri a causa di problemi con la macchina epsilon, ho trovato una soluzione diversa. Gestisce float e numeri interi, zeri finali (!) Ed è scritto come funzione.

Grazie a @ogaday per i suggerimenti utili e per la compatta correzione '0'!

golfed:

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
Bello. f('0')Tuttavia, non riesce il caso di test e quando copio e incrocio direttamente nel mio interprete ottengo la notazione scientifica (che penso vada bene). Inoltre, list(c)è più corto. Se si concatena il '.'prima di trasformarlo in un elenco, non è necessario aggiungere []neanche. L'utilizzo findanziché l'indice sulla stringa prima di trasformarla in un elenco, dopo l'aggiunta, '.'consente di risparmiare anche un byte. Il riordino della disuguaglianza ti consente di rimuovere anche uno spazio aggiuntivo: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 byte

Soluzione semplice:

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

eseguibile:


1

Stax , 18 byte

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

Esegui ed esegui il debug

Disimballato, non golfato e commentato, sembra così.

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

Esegui questo

Come molte delle altre soluzioni pubblicate, produce 9000000+9e-7per l'ultimo caso di test. In base al precedente stabilito ciò è consentito perché il test case è troppo preciso per la lingua.


0

Lua, 350 byte

Penso che ci sia un altro modo per giocare a golf più in basso:

  • Potrei usare macro.defineper sostituire alcune delle espressioni comuni (non posso testare in questo momento, e non sono sicuro che mi farebbe guadagnare qualche byte)

  • Usa la divisione sul punto anziché l'iterazione sull'intera stringa. Ancora una volta, non sono sicuro che ridurrebbe le dimensioni di questa funzione, poiché manipolare le stringhe in lua è piuttosto 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

spiegazioni

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

Puoi testare lua online e utilizzare il seguente codice sorgente per eseguirlo con alcuni casi di test

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 byte

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)dovrebbe eseguire un backspace.

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

Dettagliato , prova qui

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 byte

Ridotto di 8 caratteri facendo cadere spazi e inutile 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

Casi test:

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 byte

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

Funziona con numeri di lunghezza arbitrari perché utilizza la manipolazione di stringhe in tutto.

Senza la comprensione dell'array (122 byte):

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

Per quanto ne so, questa nuova sintassi di comprensione dell'array proviene da ECMAScript 7.
Manatwork

@manatwork Grazie, l'ho aggiornato mentre stavo aggiungendo la versione non golfata.
Neil,

0

R - 133 byte

Robusto, ignora Machine Epsilon e funziona anche con zeri finali.

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

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")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.