Rozwiń liczbę

58

Możesz pamiętać w pierwszej lub drugiej klasie, używając rozszerzonej formy, aby dowiedzieć się o wartości miejsca liczb. Łatwiej to wyjaśnić na przykładzie, więc zastanów się nad liczbą 123. W rozszerzonej formie jest reprezentowany jako 100 + 20 + 3, co pomaga młodemu umysłowi wizualizować wartość miejsca. Przypomina to, jak to mówisz: sto (plus) dwadzieścia (plus) trzy.

Możemy przedłużyć tę jednostkę o miejsca po przecinku: 2.718 => 2 + 0.7 + 0.01 + 0.008

Twoim wyzwaniem jest napisanie programu lub funkcji, która przyjmuje dodatnią liczbę zmiennoprzecinkową lub zero (zakładając, że jest tak duża lub precyzyjna, jak twój język może to obsłużyć; nie będzie w notacji naukowej) lub ciąg znaków i drukuje / zwraca ją w rozszerzonej formie jak wyjaśniono powyżej.

Nie potrzebujesz spacji między +zerami ani zerem przed kropką dziesiętną, więc powyższy przykład może być 2+.7+.01+.008. Wartości, które byłyby równe zeru, należy pominąć ( 101.01 => 100 + 1 + 0.01), chyba że wartością wejściową jest zero (patrz poniżej).

Wartości nie powinny mieć więcej niż jednego zera wiodącego przed kropką dziesiętną ani żadnych zera końcowego po nim (no-no's 0060, 0000.2, 30., 30.000, .0400:). Dane wejściowe również będą zgodne z tym.

Ponieważ pierwszoklasiści mają krótki czas koncentracji, twój kod będzie musiał być jak najkrótszy.

Przypadki testowe

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
NinjaBearMonkey
źródło
22
+1 dla „Ponieważ pierwszoklasiści mają krótki czas koncentracji, Twój kod będzie musiał być jak najkrótszy”.
Downgoat
2
@ Nie cieszę się, że mem wciąż działa.
cat
4
Byłoby zabawnie zrobić to w ten sam sposób, w jaki my (Francuzi) liczymy, aby zobaczyć ludzi zmagających się ze sprawą 97 (4 * 20 + 10 + 7) ^^
Katenkyo
2
@ jimmy23013 Tak, o ile działa w teorii.
NinjaBearMonkey
1
@Ogaday Nie wiem, to tylko niektóre przypadki krawędzi. Może sposób NBZ byłby lepszy, ale nie, jeśli to naprawdę byłoby interesujące
Katenkyo

Odpowiedzi:

6

CJam, 33 26 bajtów

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

To nie będzie działać z interpreterem Java; druk pływa inaczej. Wypróbuj z interpreterem CJam .

Zostanie wydrukowany ostatni przypadek testowy 9000000+9e-7, który został uznany za ważny przez @NinjaBearMonkey .

Dzięki @ jimmy23013 za grę w golfa poza 7 bajtami!

Jak to działa

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.
Dennis
źródło
Oparte na tej samej idei: r_ee\'0fe<f{\~t~}{},'+*0e|.
jimmy23013
@ jimmy23013 Wow, to jest krótkie! Dziękuję Ci!
Dennis
5

JavaScript (ES7), 102 bajty

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

Wyjaśnienie

Wymaga wprowadzenia liczby jako ciągu bez zer wiodących (chyba że liczba jest 0 oczywiście).

Uwaga: Z powodu dziwnego zmiennoprzecinkowego niektóre liczby (jak .3) wychodzą źle, ale teoretycznie działa to na dowolną liczbę.

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

Testowe zastosowania Math.powzamiast **zgodności przeglądarki.

użytkownik 81655
źródło
Math.floor=> 0|...?
ETHproductions
@ETHproductions Jeśli liczba wejściowa jest mniejsza niż 1ulegnie zerwaniu, ponieważ Math.log10(n)zwróci liczbę ujemną i |0zaokrągli się do zera zamiast podłogi.
user81655,
Czy możesz użyć 0|Math.log10(n),p-=p<0zamiast Math.floor(Math.log10(n))?
Dom Hastings,
1
@DomHastings Prawie. To się nie udaje, n<1ponieważ 0|będzie prówna 0dla obu 0.1i -0.1. Najkrótszym sposobem, jaki mogę wymyślić, p=Math.log10(n),p=p-(p<0)|0jest taka sama długość jak używanie Math.floor. :(
user81655
@DomHastings Wciąż i tak by nie działał n=0.1.
Neil,
5

Retina , 86 77 75 bajtów

Liczba bajtów zakłada, że ​​źródło jest zakodowane jako ISO 8859-1.

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

Końcowe podawanie linii jest znaczące.

Wypróbuj online.

Wyjaśnienie

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

Zaczynamy od przekształcenia danych wejściowych w osobną listę komponentów podawaną przez wiersz, chociaż poprawna jest tylko cyfra wiodąca (lub końcowa). Odbywa się to poprzez nadużywanie podzielonego etapu. Zamiast dzielić dane wejściowe, dopasowujemy je wszystkie, więc pozostałe segmenty są puste. Usuwamy puste segmenty z _opcją. Problem polega na tym, że podzielone etapy zwracają również wartości wszystkich grup przechwytywania. Dlatego używamy lookahead przy każdym dopasowaniu, aby uchwycić prawidłową część ciągu: najpierw staramy się znaleźć .lewą stronę dopasowania. W takim przypadku rejestrujemy wszystko z.aż do cyfry, którą aktualnie dopasowujemy. W przeciwnym razie musimy znajdować się w części liczbowej wejściowej, więc przechwytujemy wszystkie liczby po dopasowaniu (w tym dopasowanie). Musimy także pozbyć się kropki dziesiętnej, więc drugie przechwytywanie jest opcjonalne. Jeśli nie ma \dprzechwytywania, spowoduje to po prostu usunięcie dopasowania z danych wejściowych.

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

Teraz używamy etapu transliteracji, aby przekształcić wszystkie cyfry oprócz wiodących / końcowych w zera. Albo dopasowujemy komponent, który jest mniejszy niż 1, \..+\Bgdzie \Bzapewnia, że ​​zatrzymamy dopasowywanie jednej cyfry przed końcem, lub dopasowujemy część całkowitą, w (?<=^\d).+której to lookbehind zapewnia, że ​​zaczynamy jedną cyfrę od liczby. Etap transliteracji zastąpi następnie wszelkie cyfry ( d) zerami w dopasowaniach.

¶([.0]+¶)*
+

Teraz rzeczywisty format wyjściowy +nie powinien wykorzystywać kanałów jako separatorów. W dopasowuje wysuwu wiersza do zrobienia, że podstawienie. W tym momencie usuwamy również wiersze zawierające tylko 0s i .s.

^0.|\+0$

Poprzedni etap nie usuwa wiodącego ani końcowego 0(ponieważ nie mają one linii przed i po nich), więc usuwamy je jawnie.

Martin Ender
źródło
4

Python 2, 216 210 196 175 bajtów

Oto trochę lekko golfowy kod, który będę grać w golfa, kiedy będę miał czas. Wykorzystuje analizę ciągów.

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

Wyjaśnienie

Tak więc wejście jest podzielone na liczbę całkowitą i dziesiętną. Następnie istnieje lista pętli for. W części całkowitej długość łańcucha po znaku dziesiętnym jest mnożona przez „0”, aby uzyskać tyle zer na końcu, jeśli ten znak.

W przypadku części dziesiętnej indeks bieżącego znaku to liczba zer przed nim, więc ta część jest prosta.

Try i wyjątek służy do ustalenia, czy ma część dziesiętną, czy nie (za pomocą błędu).

Ostateczny wynik jest połączony ze znakami plus.

Wypróbuj tutaj!

TanMath
źródło
2
Myślę, że o if o else ["0"]może być o or["0"].
lirtosiast
W czwartym wierszu masz spację końcową, która zwiększa liczbę bajtów. W czwartej linii potrzebujesz tylko jednego jelita grubego. Można usunąć spacje w następujących fragmentów: o=[(...)] for, e(I) if, e(i[1]) if, print "+", i zewnętrznej w nawiasie o=[(...), a także, w rzeczywistości. Na koniec możesz usunąć końcową funkcję warunkową z funkcji łączenia w następujący sposób: print"+".join(o)or"0"ponieważ sprzężenie zwróci pustą listę, jeśli ojest pusta, więc warunek oceni ten sam sposób, który pozwoli Ci zaoszczędzić jeden bajt.
Ogaday
3

Pyth, 30 bajtów

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

Zestaw testowy

Podstawowym rozwiązaniem jest zastąpienie wszystkich cyfr na wejściu 0, a następnie wstawienie każdej cyfry w odpowiednim miejscu, ewaluacja, odfiltrowanie zer i połączenie plusów. Niestety, funkcja evalu Pytha nie akceptuje obecnie wiodących zer. Będę pracował, aby to naprawić.

Aby obejść ten problem, dodałem funkcję pomocnika y, która rekurencyjnie ponawia próbę ewaluacji, dopóki nie zostanie zgłoszony błąd, usuwając za każdym razem pierwszą cyfrę. Zauważ, że ta funkcja będzie się zapętlać w nieskończoność przy nieprawidłowym wejściu.

Potrzebny był również specjalny przypadek dla danych wejściowych 0.

Podsumowując, uważam, że kod jest całkiem dobry, ale możliwości językowe mogą być lepsze. Kto chce błędów?

isaacg
źródło
3

Python 3, 138

Jest to luźno oparte na podejściu TanMath / Ogaday polegającym na odczytywaniu liczby jako ciągu i analizowaniu jej w ten sposób. Muszę użyć przypisania do gwiazdy, iaby poprawnie obsługiwała liczby całkowite.

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))
Morgan Thrapp
źródło
3

Python, 141 132 128 bajtów

Ten jest nadal stosunkowo czytelny. Konwertuj na ciąg i przetwarzaj >1cyfry oddzielnie od <1cyfr. Mamy też specjalny przypadek zerowy. Mógłbym usunąć jeszcze dwie spacje poniżej, ale lubię to utrzymywać.

Minusem jest to, że spowoduje awarię pływaków z więcej niż 9 miejscami po przecinku.

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)

Poniżej znajduje się oryginał. Pierwsza edycja miała na celu skrócenie zerowego przypadku specjalnego, druga edycja polegała na usunięciu zera przed przecinkiem, trzecia na usunięciu dodatkowych nawiasów i spacji.

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

Wyjaśnienie:

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
szybowiec
źródło
Nie musisz dołączać każdej wersji kodu; jeśli chcemy zobaczyć twoje postępy w golfa, możemy spojrzeć na historię zmian. Przy okazji, witamy w PPCG!
lirtosiast
1
Właśnie to odkryłem ... Będę musiał spróbować nie spędzać zbyt wiele czasu na tej stronie!
speedplane
2

Mathematica, 81 bajtów

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

Przypadek testowy:

%[101.01]
(* 100. + 1. + 0.01 *)
njpipeorgan
źródło
3
Nie sądzę, aby kropka dziesiętna nad częściami całkowitymi była dozwolona.
Martin Ender
2

CJam, 44 bajty

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

Wypróbuj tutaj.

Nie powiedzie się w ostatnim przypadku testowym i wyświetla następujące wyniki:

9000000+9e-7

Ale powiedzmy, że to zbyt precyzyjne, że CJam nie może sobie z tym poradzić.

Wyjaśnienie

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.
jimmy23013
źródło
2

Python 3, 187 180 173 154 bajtów

Udało się zagrać w golfa o 19 bajtów więcej dzięki powyższym sugestiom @Thomas Kwa result or['0'], a także przestawić algebrę ( 154 bajty ):

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

Moja najlepsza jak dotąd próba ( 173 bajtów ). W oparciu o nowe podejście, patrz na dole postu:

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]

grałem w golfa mój oryginalny do 180 bajtów :

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]

Nauczyłem się dziś nowej funkcji języka! Warunki warunkowe za pomocą indeksowania logicznego. Być może nieco go przesadziłem.

Próbowałem wyodrębnić wyrażenia, ale nie mogłem go skrócić ( 196 bajtów ):

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

(Sekwencje cofania są drogie!)

Choć kopalnia jest krótszy teraz, myślę TanMath może golf His w dół, aby dopasować moje: Używanie e=enumerate, zastępując passz 0, i stosując '0'w miejsce ['0']w zestawieniu powrotnej powinien zapisać 4 + 3 + 2 = 9 bajtów! Sprowadza się to do 187. Jestem pewien, że gdzieś można zgolić kolejne kilka bajtów ...

edytować Nowe podejście ( 156 bajtów ). Jednak może poradzić sobie tylko z precyzją do 6dp, podobną do wpisu CJam @ jimmy23013, więc nie przejdzie ostatniego testu. Nie mogłem go zmusić do wydrukowania więcej zer, może ktoś inny może. Zamiast tego użyłem go jako podstawy mojej najlepszej jak dotąd próby, patrz góra (również to podejście wypisuje 0 przed miejscem dziesiętnym, ale wydaje się to również poprawne). Wziął try:... except:...podejście od 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] 
Ogaday
źródło
Jeśli próbujesz mi pomóc w grze w golfa, dołącz je jako komentarze do mojej odpowiedzi, a nie w swojej odpowiedzi. Nie zawsze widzę twoje odpowiedzi, więc pisząc komentarz, otrzymam powiadomienie i na pewno je zobaczę.
TanMath,
2
Cześć @TanMath. Chciałbym, ale nie mam jeszcze wystarczającej liczby przedstawicieli, aby komentować posty innych osób. Gdy dostanę jeszcze kilka łodzi, dodam opinię w komentarzach.
Ogaday,
2

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

lub

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
F. Hauri
źródło
2

Python, 131 bajtów

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

Naprawdę, bardzo niechlujna funkcja rekurencyjna, prawdopodobnie nie jest to najlepszy sposób na rozwiązanie tego problemu. Dane wejściowe jak f("10.0203").

Sp3000
źródło
Czy to w ogóle Python? Kocham to.
Ogaday
2

C, 155 153 161 bajtów

+2 do linku w bibliotece matematycznej (samo źródło to 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;}

Nie golfił

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 */
    }
}
Cole Cameron
źródło
2

Dyalog APL , 47 bajtów

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

Pobiera liczbę w postaci wektora znaków, np '123'.

Przykłady:

      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     

Uwagi:
○ Powodem zmodyfikowanego ostatniego przykładu jest to, że APL, podobnie jak niektóre inne zgłoszenia, domyślnie przełącza się na notację naukową dla takich ekstremalnych liczb.
○ Fraza ↑⍕¨f¨,¨jest potrzebna tylko do przetworzenia wszystkich przykładów jednocześnie.

Adám
źródło
1

Siatkówka, 113 bajtów

Obecnie znacznie dłużej niż rozwiązanie Martina, ale używa innej metody, więc postanowiłem to opublikować.

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

¶\..*¶.*

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

Wypróbuj online tutaj.

randomra
źródło
1

perl, 132 bajty

131 +1 dla -pprzełącznika.

Jest to oparte na mojej poprzedniej sedodpowiedzi :

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/

Zestaw testowy:

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
F. Hauri
źródło
1

PowerShell - 172 166 193 bajtów

Wszystko w jednym wierszu:

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

Nie golfowany:

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

Przypadki testowe oraz jeden dodatkowy:

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>
Chris J
źródło
Twoje wyrażenie regularne zostanie odfiltrowane $args = 0. Oto prosta poprawka błędu, która oszczędza również 3 bajty
Veskah
1

Perl, 248 bajtów

Ew, jestem noobish w golfie 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;

Wypróbuj tutaj.

Paul Picard
źródło
To wydaje się nie działać z liczbami całkowitymi.
F. Hauri
Umieściłem zły link Ideone. Nie uwzględnia zmian dokonanych w trybie edycji. :( Powinno już działać.
Paul Picard,
Gdzieś masz błąd: kiedy wejdę 5, wróć 50.
F. Hauri
Dziwne, ponieważ przetestowałem 5 z linkiem, który podałem wczoraj po tym, jak umieściłeś swój pierwszy komentarz. Masz teraz ochotę? (Ponownie zmieniłem link)
Paul Picard
Właśnie przetestowałem twój skrypt na moim interpretatorze perla (v5.20.2)
F. Hauri
1

Jawa, 284 244 243 bajtów

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

Niestety nie mogłem znaleźć krótszego sposobu tworzenia powtarzalnych ciągów niż:

  • zbuduj char[]wymaganą długość
  • za pomocą Arrays.fillustawić znaki
  • użyj, new Stringaby można było połączyć

Dzięki inspiracji @Khaled A Khunaifer mogłem ogolić 40 bajtów.

Edit: indexOftrwa int, więc mogę wymienić '.'z 46. Niestety nie wydaje się to możliwe replace.

ECS
źródło
Udało mi się zmniejszyć go do 250, sprawdź ideone.com/HqLnMo
Khaled.K
@Khaled A Khunaifer Twoje rozwiązanie wydaje się mieć problemy z jednocyfrowymi przypadkami testowymi. Ale podoba mi się twój sposób generowania zer.
ECS
napraw tę .replace('\0','0')funkcję zamień, Stringnie oczekuj char, powinno być.replace("\0","0")
Khaled.K
@Khaled A Khunaifer Działa w moich przypadkach testowych, również docs.oracle.com/javase/8/docs/api/java/lang/…
ECS
1

Python, 125 bajtów

Po usunięciu mojej pierwszej odpowiedzi (sry!), Która nie mogła poradzić sobie z małymi liczbami z powodu problemów z epsilon maszyny, znalazłem inne rozwiązanie. Obsługuje zarówno liczby zmiennoprzecinkowe, jak i liczby całkowite, końcowe zera (!) I jest zapisywany jako funkcja.

Dzięki @ogaday za przydatne wskazówki i kompaktową poprawkę „0”!

Gra w golfa:

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'

Nie golfowany:

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'

Stosowanie:

>>> 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'
lambruscoAcido
źródło
1
Miły. Nie powiedzie się f('0')jednak przypadek testowy, a kiedy kopiuję i wklejam bezpośrednio do mojego tłumacza, otrzymuję notację naukową (co moim zdaniem jest w porządku). Jest także list(c)krótszy. Jeśli połączysz '.'przed przekształceniem go w listę, nie musisz go dodawać []. Użycie findzamiast indeksu w ciągu przed przekształceniem go w listę, po dodaniu '.'również oszczędza bajt. 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'
Zmiana kolejności
1

CoffeeScript, 144 bajty

Proste rozwiązanie:

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

Plik wykonywalny:

metalim
źródło
1

Stax , 18 bajtów

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

Uruchom i debuguj

Rozpakowane, niepolowane i skomentowane, wygląda to tak.

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

Uruchom ten

Podobnie jak wiele innych opublikowanych rozwiązań, produkuje 9000000+9e-7dla ostatniego przypadku testowego. Zgodnie z ustalonym precedensem jest to dozwolone, ponieważ przypadek testowy jest zbyt precyzyjny dla języka.

rekurencyjny
źródło
0

Lua, 350 bajtów

Myślę, że są dwa sposoby na dalszą grę w golfa:

  • Mógłbym użyć macro.definedo zastąpienia niektórych wspólnych wyrażeń (nie mogę teraz przetestować i nie jestem pewien, czy to sprawi, że zyskam trochę bajtów)

  • Użyj podziału na kropce zamiast iteracji na całym ciągu. Po raz kolejny nie jestem pewien, czy zmniejszyłoby to rozmiar tej funkcji, ponieważ manipulowanie łańcuchem w lua jest dość bolesne.

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

Objaśnienia

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

Możesz przetestować lua online i użyć następującego kodu źródłowego, aby uruchomić go z niektórymi przypadkami testowymi

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"))
Katenkyo
źródło
0

C, 253 bajtów

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

Uwaga: putchar(8)należy wykonać backspace.

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

Szczegółowe , spróbuj tutaj

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);
Khaled.K
źródło
0

sed, 136 128 bajtów

Zmniejszony o 8 znaków przez upuszczanie spacji i bezużyteczny 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

Przypadki testowe:

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
F. Hauri
źródło
0

JavaScript (ES7), 114 bajtów

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

Działa z dowolnymi liczbami długości, ponieważ używa manipulacji ciągami w całym tekście.

Bez zrozumienia tablicy (122 bajty):

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

Nie golfowany:

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;
}
Neil
źródło
O ile mi wiadomo, ta nowa składnia zrozumienia tablic pochodzi z ECMAScript 7.
manatwork
@manatwork Dzięki, zaktualizowałem go podczas dodawania wersji bez golfa.
Neil
0

R - 133 bajty

Solidny, ignoruje Machine Epsilon i działa również z końcowymi zerami.

a) Gra w golfa:

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

Nie golfowany:

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

Stosowanie:

f("900.008")
lambruscoAcido
źródło