Perluas jumlahnya


58

Anda mungkin ingat di kelas satu atau dua menggunakan formulir yang diperluas untuk belajar tentang nilai tempat angka. Lebih mudah dijelaskan dengan sebuah contoh, jadi pertimbangkan nomornya 123. Dalam bentuk diperluas itu diwakili sebagai 100 + 20 + 3, yang membantu pikiran muda memvisualisasikan nilai tempat. Ini mengingatkan pada bagaimana Anda mengatakannya: seratus (plus) dua puluh (plus) tiga.

Kami dapat memperluas ini melewati unit tempat dengan desimal: 2.718 => 2 + 0.7 + 0.01 + 0.008

Tantangan Anda adalah untuk menulis sebuah program atau fungsi yang mengambil angka floating point positif atau nol (anggap itu sama besar atau tepat seperti bahasa Anda dapat menangani; itu tidak akan dalam notasi ilmiah) atau string dan mencetak / mengembalikannya dalam bentuk diperluas seperti yang dijelaskan di atas.

Anda tidak perlu spasi antara +'s atau nol sebelum titik desimal, jadi contoh di atas bisa 2+.7+.01+.008. Nilai yang sama dengan nol harus dihilangkan ( 101.01 => 100 + 1 + 0.01) kecuali jika inputnya nol (lihat di bawah).

Nilai tidak boleh memiliki lebih dari satu nol di depan sebelum koma desimal atau nol di belakangnya setelah itu (no-no:) 0060, 0000.2, 30., 30.000, .0400. Masukan akan sesuai dengan ini juga.

Karena siswa kelas satu memiliki rentang perhatian yang pendek, kode Anda harus sesingkat mungkin.

Uji kasus

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 untuk "Karena siswa kelas satu memiliki rentang perhatian yang pendek, kode Anda harus sesingkat mungkin."
Downgoat

2
@ Jangan senang melihat meme masih berjalan.
kucing

4
Akan sangat lucu untuk melakukannya dengan cara yang sama seperti yang kita (Prancis) hitung, untuk melihat orang-orang berjuang dengan case of 97 (4 * 20 + 10 + 7) ^^
Katenkyo

2
@ jimmy23013 Ya, asalkan itu bekerja secara teori.
NinjaBearMonkey

1
@Ogaday, saya tidak tahu, ini hanya beberapa kasus tepi. Mungkin cara NBZ akan lebih baik, tapi tetap saja, jangan jika itu benar-benar menarik
Katenkyo

Jawaban:


6

CJam, 33 26 byte

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

Ini tidak akan berfungsi dengan penerjemah Java; itu mencetak mengapung berbeda. Cobalah dengan penerjemah CJam .

Cetakan tes terakhir 9000000+9e-7, yang telah dinyatakan valid oleh @NinjaBearMonkey .

Terima kasih kepada @ jimmy23013 untuk bermain golf 7 byte!

Bagaimana itu bekerja

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.

Berdasarkan ide yang sama: r_ee\'0fe<f{\~t~}{},'+*0e|.
jimmy23013

@ jimmy23013 Wow, itu singkat! Terima kasih!
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`+`

Penjelasan

Membutuhkan nomor menjadi masukan sebagai string tanpa nol terkemuka (kecuali nomor adalah 0 tentu saja).

Catatan: Karena keanehan floating-point beberapa angka (seperti .3) keluar salah, tetapi secara teoritis ini bekerja untuk nomor apa pun.

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 +

Uji

Penggunaan uji Math.powalih-alih **untuk kompatibilitas browser.


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

@ ETHproductions Jika nomor input kurang dari 1itu akan pecah karena Math.log10(n)akan mengembalikan angka negatif dan |0putaran ke nol bukannya lantai.
user81655

Bisakah Anda menggunakan 0|Math.log10(n),p-=p<0bukan Math.floor(Math.log10(n))?
Dom Hastings

1
@HomHastings Almost. Gagal n<1karena 0|akan membuat ppersamaan 0untuk keduanya 0.1dan -0.1. Cara terpendek yang bisa saya pikirkan adalah p=Math.log10(n),p=p-(p<0)|0panjang yang sama dengan menggunakan Math.floor. :(
user81655

@HomHastings Masih tidak akan bekerja untuk apa pun n=0.1.
Neil

5

Retina , 86 77 75 byte

Hitungan byte mengasumsikan bahwa sumber dikodekan sebagai ISO 8859-1.

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

Linefeed tambahan sangat penting.

Cobalah online.

Penjelasan

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

Kami mulai dengan mengubah input ke daftar komponen terpisah, meskipun hanya digit terdepan (atau trailing) yang benar. Ini dilakukan dengan menyalahgunakan split stage. Alih-alih memisahkan input, kami mencocokkan semua itu, sehingga segmen yang tersisa semuanya kosong. Kami menghapus segmen kosong itu dengan _opsi. Tangkapannya adalah bahwa tahap-tahap pemisahan juga mengembalikan nilai semua kelompok tangkapan. Jadi kami menggunakan lookahead di setiap pertandingan untuk menangkap bagian string yang benar: pertama kami mencoba menemukan bagian .kiri dari pertandingan. Jika itu masalahnya, kami menangkap semuanya dari.hingga dan termasuk digit yang saat ini kami cocokkan. Kalau tidak, kita harus berada di bagian integer dari input, jadi kami menangkap semua angka setelah pertandingan (termasuk pertandingan). Kita juga harus menghilangkan titik desimal itu sendiri, sehingga penangkapan kedua adalah opsional. Jika tidak ada yang \dakan ditangkap, ini hanya akan menghapus kecocokan dari input.

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

Sekarang kita menggunakan tahap transliterasi untuk mengubah semua kecuali digit awal / akhir menjadi nol. Kami mencocokkan komponen yang kurang dari 1 dengan \..+\Btempat \Bmemastikan bahwa kami menghentikan kecocokan satu digit sebelum akhir, atau kami mencocokkan bagian bilangan bulat dengan (?<=^\d).+tempat tampilan di belakang memastikan bahwa kami mulai satu digit ke dalam angka. Tahap transliterasi kemudian akan mengganti angka ( d) dengan nol di dalam pertandingan.

¶([.0]+¶)*
+

Sekarang format output aktual seharusnya menggunakan +bukan linefeeds sebagai pemisah. The pertandingan linefeed untuk melakukan substitusi itu. Sementara kami melakukannya, kami juga menghapus garis yang hanya berisi 0s dan .s.

^0.|\+0$

Tahap sebelumnya tidak menghapus arahan atau jejak 0(karena mereka tidak memiliki umpan baris sebelum dan sesudahnya), jadi kami menghapusnya secara eksplisit.


4

Python 2, 216 210 196 175 byte

Berikut adalah beberapa kode sedikit golf yang akan saya golf lebih jauh ketika saya punya waktu. Ini menggunakan analisis string.

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

Penjelasan

Jadi, input dipisahkan menjadi bagian integer dan desimal. Kemudian, ada pemahaman daftar loop. Pada bagian integer, panjang string setelah karakter dalam desimal dikalikan dengan "0" untuk mendapatkan banyak nol pada akhirnya jika karakter itu.

Untuk bagian desimal, indeks karakter saat ini adalah jumlah nol sebelum dan sehingga bagian itu sederhana.

Coba dan kecuali digunakan untuk menentukan apakah ia memiliki bagian desimal atau tidak (menggunakan kesalahan).

Hasil akhir digabungkan dengan tanda plus.

Coba di sini!


2
Saya pikir o if o else ["0"]bisa o or["0"].
lirtosiast

Anda memiliki ruang tambahan di baris empat yang menambah jumlah byte Anda. Pada baris empat Anda hanya perlu satu titik dua. Anda dapat menghapus spasi dalam cuplikan berikut: o=[(...)] for, e(I) if, e(i[1]) if, print "+", dan kurung luar dalam o=[(...)juga, sebenarnya. Akhirnya, Anda dapat mengambil syarat akhir dari fungsi bergabung seperti ini: print"+".join(o)or"0"karena bergabung akan mengembalikan daftar kosong jika okosong sehingga persyaratan akan mengevaluasi dengan cara yang sama yang menghemat satu byte.
Ogaday

3

Pyth, 30 byte

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

Suite uji

Solusi dasar di sini adalah mengganti semua digit dalam input dengan 0, lalu masukkan setiap digit di lokasi yang tepat, eval, saring angka nol, dan gabung dengan plus. Sayangnya, fungsi eval Pyth tidak menerima angka nol di depan saat ini. Saya akan bekerja untuk memperbaikinya.

Untuk mengatasi masalah ini, saya menambahkan fungsi pembantu y, yang secara berulang mencoba ulang eval hingga tidak ada kesalahan yang dilemparkan, menghapus digit pertama setiap kali. Perhatikan bahwa fungsi ini akan berulang tanpa henti pada input yang tidak valid.

Juga, kasus khusus diperlukan untuk input 0.

Secara keseluruhan, saya pikir kodenya cukup bagus, tetapi fasilitas bahasanya bisa lebih baik. Siapa yang mau kesalahan?


3

Python 3, 138

Ini secara longgar didasarkan pada pendekatan TanMath / Ogaday dalam membaca angka sebagai string dan menguraikannya seperti itu. Saya harus menggunakan tugas bintang pada isehingga menangani bilangan bulat dengan benar.

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

Yang ini masih relatif mudah dibaca. Konversikan ke string dan pegang >1digit secara terpisah dari <1digit. Kami juga memiliki kasus khusus untuk nol. Saya bisa menghapus dua ruang lagi di bawah, tapi saya suka menjaganya tetap cantik.

The downside adalah bahwa itu akan rusak untuk mengapung dengan lebih dari 9 tempat desimal.

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 bawah ini adalah yang asli. Sunting pertama adalah untuk mempersingkat nol kasus khusus, sunting kedua adalah untuk menghapus 0 sebelum desimal, ketiga adalah untuk menghapus beberapa tanda kurung tambahan dan spasi.

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

Penjelasan:

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

Anda tidak perlu memasukkan setiap revisi kode Anda; jika kami ingin melihat perkembangan golf Anda, kami dapat melihat riwayat revisi. Omong-omong, selamat datang di PPCG!
lirtosiast

1
Baru saja menemukannya ... Saya harus mencoba untuk tidak menghabiskan terlalu banyak waktu di situs ini!
speedplane

2

Mathematica, 81 byte

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

Kasus cobaan:

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

3
Saya tidak berpikir memiliki titik desimal di atas bagian integer diperbolehkan.
Martin Ender

2

CJam, 44 byte

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

Coba di sini.

Gagal uji kasus terakhir, dan menghasilkan yang berikut:

9000000+9e-7

Tapi katakanlah itu terlalu tepat sehingga CJam tidak bisa menanganinya.

Penjelasan

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

Berhasil bermain golf 19 byte berkat terima kasih atas saran @Thomas Kwa di atas result or['0'], ditambah pengaturan ulang beberapa aljabar ( 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

Upaya terbaik saya sejauh ini ( 173 bytes ). Berdasarkan pendekatan baru, lihat bawah posting:

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]

pangkas aslinya hingga 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]

Saya belajar fitur bahasa baru hari ini! Persyaratan melalui pengindeksan boolean. Saya mungkin telah sedikit berlebihan.

Saya mencoba mengabstraksi pemahaman, tetapi saya tidak bisa membuatnya lebih pendek ( 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))]

(Urutan membalikkan itu mahal!)

Sementara milik saya lebih pendek untuk saat ini, saya pikir TanMath dapat golf turun untuk mencocokkan milik saya: Menggunakan e=enumerate, mengganti passdengan 0, dan menggunakan '0'di tempat ['0']dalam pernyataan kembali harus menyimpan 4 + 3 + 2 = 9 byte! Mengambilnya ke 187. Saya yakin beberapa byte lainnya dapat dicukur di suatu tempat ...

edit Pendekatan baru ( 156 byte ). Namun, itu hanya dapat menangani presisi hingga 6dp mirip dengan entri CJam @ jimmy23013, sehingga gagal pada tes akhir. Saya tidak bisa memaksanya untuk mencetak lebih banyak 0s, mungkin orang lain bisa. Alih-alih, saya menggunakannya sebagai dasar upaya terbaik saya, lihat di atas (Juga, pendekatan ini mencetak 0 sebelum tempat desimal, tapi itu tampaknya juga valid.). Mengambil try:... except:...pendekatan dari 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] 

Jika Anda mencoba memberikan bantuan golf kepada saya, harap sertakan mereka sebagai komentar untuk jawaban saya, bukan dalam jawaban Anda. Saya tidak selalu melihat jawaban Anda, jadi dengan menulis komentar, saya akan mendapat notifikasi dan pasti melihatnya.
TanMath

2
Hai @TanMath. Ya, tapi saya belum punya cukup perwakilan untuk mengomentari posting orang lain. Setelah saya mendapatkan beberapa perahu lagi saya akan memastikan untuk meninggalkan umpan balik dalam komentar.
Ogaday

2

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

atau

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}

Uji:

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

Fungsi rekursif yang benar-benar berantakan, mungkin bukan cara terbaik untuk melakukannya. Masukan seperti f("10.0203").


Apakah ini Python? Suka.
Ogaday

2

C, 155 153 161 byte

+2 untuk terhubung di perpustakaan matematika (sumbernya sendiri adalah 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;}

Tidak disatukan

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} 

Membawa angka dalam bentuk vektor karakter, mis '123'.

Contoh:

      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     

Catatan:
○ Alasan untuk contoh terakhir yang dimodifikasi adalah bahwa APL, seperti beberapa kiriman lainnya, secara default akan beralih ke notasi ilmiah untuk angka ekstrem tersebut.
○ Frasa ↑⍕¨f¨,¨ini hanya diperlukan untuk memproses semua contoh sekaligus.


1

Retina, 113 byte

Saat ini jauh lebih lama daripada solusi Martin tetapi menggunakan metode yang berbeda jadi saya memutuskan untuk mempostingnya.

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

¶\..*¶.*

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

Cobalah online di sini.


1

perl, 132 byte

131 +1 untuk -psakelar.

Ini berdasarkan jawaban saya sebelumnyased :

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/

Test suite:

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

Semua dalam satu baris:

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

Tidak Disatukan:

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

Test case, plus satu tambahan:

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

Ew, saya noobish di 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;

Coba di sini.


Ini sepertinya tidak berfungsi dengan angka integer.
F. Hauri

Saya menempatkan tautan Ideone yang salah. Itu tidak memperhitungkan perubahan akun yang dibuat dalam mode Edit. :( Seharusnya bekerja sekarang.
Paul Picard

Anda memiliki kesalahan di suatu tempat: ketika saya memasukkannya 5kembali 50.
F. Hauri

Aneh, karena saya menguji 5 dengan tautan yang saya berikan kemarin setelah Anda memberikan komentar pertama Anda. Pikiran mencoba sekarang? (Saya mengubah lagi tautannya)
Paul Picard

Saya baru saja menguji skrip Anda pada penerjemah perl saya (v5.20.2)
F. Hauri

1

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

Sayangnya, saya tidak dapat menemukan cara yang lebih singkat untuk membuat Strings berulang:

  • membangun char[]panjang yang dibutuhkan
  • gunakan Arrays.filluntuk mengatur karakter
  • gunakan new Stringsehingga bisa digabungkan

Dengan inspirasi oleh @Khaled A Khunaifer, saya bisa mencukur 40 Bytes.

Sunting: indexOfmembutuhkan int, jadi saya bisa menggantinya '.'dengan 46. Sayangnya, ini sepertinya tidak mungkin dilakukan replace.


Saya berhasil mengecilkan turun ke 250, memeriksa ideone.com/HqLnMo
Khaled.K

@ Khaled A Khunaifer Solusi Anda tampaknya memiliki masalah dengan kasus uji satu digit. Tapi saya suka cara Anda menghasilkan nol.
ECS

memperbaiki .replace('\0','0')fungsi ini, ganti berharap Stringtidak char, itu harus.replace("\0","0")
Khaled.K

@Khaled A Khunaifer Ini berfungsi dalam kasus pengujian saya, juga docs.oracle.com/javase/8/docs/api/java/lang/…
ECS

1

Python, 125 byte

Setelah menghapus jawaban pertama saya (sry!) Yang tidak dapat menangani sejumlah kecil karena masalah mesin epsilon, saya menemukan solusi yang berbeda. Ini menangani float serta integer, trailing zero (!) Dan ditulis sebagai fungsi.

Terima kasih kepada @ogaday untuk petunjuk yang bermanfaat dan untuk perbaikan '0' yang ringkas!

Golf:

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

Tidak Disatukan:

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'

Pemakaian:

>>> 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
Bagus. Namun gagal pada f('0')kasus uji, dan ketika saya menyalin dan menempel langsung ke penerjemah saya, saya mendapatkan notasi ilmiah (yang saya pikir baik-baik saja). Juga, list(c)lebih pendek. Jika Anda menggabungkan '.'sebelum mengubahnya menjadi daftar, Anda tidak perlu menambahkan []keduanya. Menggunakan findbukannya indeks pada string sebelum mengubahnya menjadi daftar, setelah menambahkan '.'juga menghemat satu byte. Menyusun ulang ketimpangan memungkinkan Anda untuk menghapus ruang tambahan juga: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

Solusi lurus ke depan:

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

Dapat dieksekusi:


1

Stax , 18 byte

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

Jalankan dan debug itu

Dibongkar, tidak diserang, dan dikomentari, sepertinya ini.

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

Jalankan yang ini

Seperti banyak dari solusi lain yang diposting, itu menghasilkan 9000000+9e-7kasus uji terakhir. Menurut preseden yang sudah ada, ini diperbolehkan karena test case terlalu tepat untuk bahasanya.


0

Lua, 350 Bytes

Saya pikir ada dua cara untuk menurunkannya:

  • Saya dapat menggunakan macro.defineuntuk mengganti beberapa ekspresi commons (tidak dapat menguji sekarang, dan tidak yakin itu akan membuat saya mendapatkan beberapa byte)

  • Gunakan split pada titik alih-alih iterasi pada seluruh string. Sekali lagi, saya tidak yakin ini akan mengurangi ukuran fungsi ini, karena memanipulasi string dalam lua cukup menyakitkan.

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

Penjelasan

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

Anda dapat menguji lua online dan menggunakan kode sumber berikut untuk menjalankannya dengan beberapa kasus uji

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

Catatan: putchar(8)harus melakukan backspace.

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

Detail , coba di sini

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

Dikurangi oleh 8 karakter dengan menjatuhkan spasi dan tidak berguna 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

Kasus uji:

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

Bekerja dengan angka panjang yang berubah-ubah karena menggunakan manipulasi string di seluruh.

Tanpa pemahaman 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

Tidak Disatukan:

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

Sejauh yang saya tahu, sintaks pemahaman array baru ini berasal dari ECMAScript 7.
manatwork

@manatwork Terima kasih, saya memperbaruinya ketika saya menambahkan versi yang tidak diklik.
Neil

0

R - 133 byte

Kuat, mengabaikan Mesin Epsilon dan bekerja juga dengan nol tambahan.

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

Tidak Disatukan:

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

Pemakaian:

f("900.008")
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.