ขยายจำนวน


58

คุณอาจจำได้ในชั้นประถมศึกษาปีที่หนึ่งหรือสองโดยใช้แบบฟอร์มขยายเพื่อเรียนรู้เกี่ยวกับค่าของตัวเลข 123มันง่ายที่จะอธิบายด้วยตัวอย่างเพื่อพิจารณาจำนวน ในรูปแบบที่ขยายจะแสดงเป็น100 + 20 + 3ซึ่งช่วยให้จิตใจเด็กเห็นภาพสถานที่ มันชวนให้นึกถึงวิธีที่คุณพูดมัน: หนึ่งร้อย (บวก) ยี่สิบ (บวก) สาม

เราสามารถขยายที่ผ่านมานี้หน่วยที่มีทศนิยม: 2.718 => 2 + 0.7 + 0.01 + 0.008

ความท้าทายของคุณคือการเขียนโปรแกรมหรือฟังก์ชั่นที่ใช้จำนวนจุดลอยตัวที่เป็นบวกหรือเป็นศูนย์ (สมมติว่ามันมีขนาดใหญ่หรือแม่นยำที่สุดเท่าที่ภาษาของคุณสามารถจัดการได้มันจะไม่เป็นเครื่องหมายทางวิทยาศาสตร์) หรือสตริงและพิมพ์ / ส่งคืน ตามที่อธิบายไว้ข้างต้น

คุณจำเป็นต้องมีช่องว่างระหว่างค่า+'s 2+.7+.01+.008หรือศูนย์ก่อนจุดทศนิยมดังนั้นตัวอย่างข้างต้นอาจจะ ค่าที่จะเท่ากับศูนย์จะต้องละเว้น ( 101.01 => 100 + 1 + 0.01) เว้นแต่อินพุตเป็นศูนย์ (ดูด้านล่าง)

ค่าไม่ควรมีมากกว่าหนึ่งศูนย์นำก่อนจุดทศนิยมหรือเลขท้ายใด ๆ หลังจากที่มัน (ไม่มีไม่มีของ: 0060, 0000.2, 30., 30.000, .0400) อินพุตจะสอดคล้องกับสิ่งนี้ด้วย

เนื่องจากนักเรียนระดับแรกมีช่วงความสนใจสั้นรหัสของคุณจะต้องสั้นที่สุด

กรณีทดสอบ

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 สำหรับ "เนื่องจากนักเรียนระดับประถมแรกมีช่วงความสนใจสั้นรหัสของคุณจะต้องสั้นที่สุด"
Downgoat

2
@ Doᴡɴɢᴏᴀᴛดีใจที่เห็นmemeยังคงทำงานอยู่
แมว

4
มันคงเป็นเรื่องตลกที่จะทำแบบเดียวกันกับที่เรา (คนฝรั่งเศส) นับเพื่อดูคนที่ต้องดิ้นรนกับคดี 97 (4 * 20 + 10 + 7) ^^
Katenkyo

2
@ jimmy23013 ใช่ตราบใดที่มันทำงานในทฤษฎี
NinjaBearMonkey

1
@Ogaday ฉันไม่รู้มันเป็นเพียงบางกรณีขอบ บางทีวิธี NBZ อาจจะดีกว่า แต่ก็ยังไม่ได้ถ้ามันจะน่าสนใจจริง ๆ
Katenkyo

คำตอบ:


6

CJam, 33 26 ไบต์

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

สิ่งนี้จะไม่ทำงานกับล่าม Java มันพิมพ์ลอยตัวแตกต่างกัน ลองทดลองกับล่าม CJam

สุดท้ายพิมพ์กรณีทดสอบ9000000+9e-7ซึ่งได้รับการปกครองที่ถูกต้องโดย @NinjaBearMonkey

ขอบคุณ @ jimmy23013 สำหรับการเล่นกอล์ฟขนาด 7 ไบต์!

มันทำงานอย่างไร

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.

ตามแนวคิดเดียวกัน: r_ee\'0fe<f{\~t~}{},'+*0e|.
jimmy23013

@ jimmy23013 ว้าวนั่นสั้นมาก! ขอขอบคุณ!
Dennis

5

JavaScript (ES7), 102 ไบต์

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

คำอธิบาย

ต้องใช้จำนวนที่จะป้อนข้อมูลเป็นสตริงโดยไม่ต้องนำเลขศูนย์ (ยกเว้นกรณีที่ตัวเลขเป็น 0ของหลักสูตร)

หมายเหตุ: เนื่องจากความแปลกจุดลอยตัวตัวเลขบางอย่าง (เช่น.3) ออกมาผิด แต่ในทางทฤษฎีแล้วสิ่งนี้ใช้ได้กับหมายเลขใด ๆ

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 +

ทดสอบ

ทดสอบใช้Math.powแทน**เพื่อความเข้ากันได้ของเบราว์เซอร์


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

@ETHproductions หากจำนวนที่ป้อนน้อยกว่า1มันจะแตกเพราะMath.log10(n)จะคืนค่าจำนวนลบและ|0ปัดเศษเป็นศูนย์แทนการปูพื้น
user81655

คุณสามารถใช้0|Math.log10(n),p-=p<0แทนได้Math.floor(Math.log10(n))หรือไม่?
Dom Hastings

1
@ DomHastings เกือบ มันล้มเหลวn<1เพราะ0|จะทำให้pเท่าเทียมกัน0สำหรับทั้งสองและ0.1 -0.1ทางที่สั้นที่สุดที่ฉันสามารถคิดมีที่ซึ่งเป็นระยะเวลาเดียวกับการใช้p=Math.log10(n),p=p-(p<0)|0 Math.floor:(
user81655

@DomHastings ยังไม่สามารถใช้งานn=0.1ได้
Neil

5

เรติน่า , 86 77 75 ไบต์

จำนวนไบต์สันนิษฐานว่าแหล่งที่มานั้นถูกเข้ารหัสตาม ISO 8859-1

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

ตัวป้อนบรรทัดต่อท้ายมีความสำคัญ

ลองออนไลน์

คำอธิบาย

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

เราเริ่มต้นด้วยการเปลี่ยนอินพุตให้เป็นรายการแยกส่วนประกอบของตัวป้อนบรรทัด แต่มีเพียงตัวเลขนำหน้า (หรือต่อท้าย) เท่านั้นที่ถูกต้อง สิ่งนี้ทำได้โดยใช้เวทีแยก แทนที่จะแยกอินพุตที่เราจับคู่ทั้งหมดดังนั้นส่วนที่เหลือจะว่างเปล่าทั้งหมด เราลบกลุ่มที่ว่างเปล่าเหล่านั้นด้วย_ตัวเลือก การจับคือสเตจแยกจะส่งคืนค่าของกลุ่มการดักจับทั้งหมด ดังนั้นเราจึงใช้ lookahead ในการแข่งขันแต่ละนัดเพื่อจับส่วนที่ถูกต้องของสตริง: อันดับแรกเราพยายามค้นหา.ทางซ้ายของการแข่งขัน หากเป็นเช่นนั้นเราจะจับทุกอย่างจาก.มากถึงและรวมถึงตัวเลขที่เรากำลังจับคู่อยู่ในขณะนี้ มิฉะนั้นเราจะต้องอยู่ในส่วนจำนวนเต็มของอินพุตดังนั้นเราจึงจับตัวเลขทั้งหมดหลังการแข่งขัน (รวมถึงการแข่งขัน) เราต้องกำจัดจุดทศนิยมเองดังนั้นการจับภาพที่สองจึงเป็นทางเลือก หากไม่มี\dการจับภาพสิ่งนี้จะเป็นการลบการแข่งขันออกจากอินพุต

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

ตอนนี้เราใช้เวทีการถอดเสียงเพื่อเปลี่ยนทั้งหมดยกเว้นตัวเลขนำหน้า / ต่อท้ายให้เป็นศูนย์ เราจับคู่ส่วนประกอบที่น้อยกว่า 1 กับ\..+\Bที่\Bทำให้มั่นใจได้ว่าเราจะหยุดการแข่งขันหนึ่งหลักก่อนที่จะสิ้นสุดหรือเราจับคู่ส่วนจำนวนเต็มกับ(?<=^\d).+ที่ lookbehind ทำให้มั่นใจว่าเราเริ่มตัวเลขหนึ่งหลักเป็นจำนวน ขั้นตอนการถอดเสียงจะแทนที่ตัวเลขใด ๆ ( d) ด้วยศูนย์ภายในการแข่งขัน

¶([.0]+¶)*
+

ตอนนี้รูปแบบเอาต์พุตจริงควรใช้+ไม่ใช่ linefeeds เป็นตัวคั่น การจับคู่ linefeed ทำสิ่งทดแทน ขณะที่เราอยู่ที่นี่เรายังลบบรรทัดที่มีเพียง0s และ.s เท่านั้น

^0.|\+0$

ขั้นตอนก่อนหน้านี้ไม่ได้ลบส่วนนำหรือส่วนท้าย0(เนื่องจากสิ่งเหล่านั้นไม่มีตัวป้อนบรรทัดก่อนและหลัง) ดังนั้นเราจึงลบสิ่งเหล่านั้นออกอย่างชัดเจน


4

Python 2, 216 210 196 175 ไบต์

นี่คือรหัส golfed เล็กน้อยที่ฉันจะเล่นกอล์ฟต่อไปเมื่อฉันมีเวลา มันใช้การวิเคราะห์สตริง

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

คำอธิบาย

ดังนั้นอินพุตจะแยกเป็นส่วนจำนวนเต็มและทศนิยม จากนั้นมีความเข้าใจในรายการลูป ในส่วนจำนวนเต็มความยาวของสตริงหลังอักขระในทศนิยมจะถูกคูณด้วย "0" เพื่อรับค่าศูนย์จำนวนมากที่ท้ายถ้าอักขระนั้น

สำหรับส่วนทศนิยมดัชนีของตัวละครปัจจุบันคือจำนวนศูนย์ก่อนและเพื่อให้ส่วนนั้นง่าย

ความพยายามและการยกเว้นจะใช้เพื่อตรวจสอบว่ามีส่วนทศนิยมหรือไม่ (ใช้ข้อผิดพลาด)

ผลสุดท้ายจะรวมกับเครื่องหมายบวก

ลองที่นี่!


2
ผมคิดว่าอาจจะเป็นo if o else ["0"] o or["0"]
lirtosiast

คุณมีช่องว่างต่อท้ายบรรทัดที่สี่ซึ่งเพิ่มลงในจำนวนไบต์ของคุณ ในบรรทัดที่สี่คุณต้องการเพียงหนึ่งโคลอน คุณสามารถลบช่องว่างในตัวอย่างต่อไปนี้: o=[(...)] for, e(I) if, e(i[1]) if, print "+"และวงเล็บด้านนอกในo=[(...)ได้เป็นอย่างดีจริง ในที่สุดคุณสามารถนำเงื่อนไขสุดท้ายออกจากฟังก์ชั่นการเข้าร่วมเช่นนี้: print"+".join(o)or"0"เนื่องจากการเข้าร่วมจะส่งคืนรายการว่างเปล่าหากoว่างเปล่าดังนั้นเงื่อนไขจะประเมินแบบเดียวกับที่จะช่วยคุณประหยัดหนึ่งไบต์
Ogaday

3

Pyth, 30 ไบต์

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

ชุดทดสอบ

วิธีแก้ปัญหาพื้นฐานที่นี่คือการแทนที่ตัวเลขทั้งหมดในอินพุตด้วย0จากนั้นใส่แต่ละหลักในตำแหน่งที่เหมาะสม eval กรองค่าศูนย์และเข้าร่วมกับ pluses น่าเสียดายที่ฟังก์ชัน Eval ของ Pyth ไม่ยอมรับค่าศูนย์นำหน้าในขณะนี้ ฉันจะทำงานเพื่อแก้ไขปัญหานี้

เพื่อแก้ไขปัญหานี้ฉันได้เพิ่มฟังก์ชั่นตัวช่วยyซึ่งพยายามลองวนซ้ำจนกว่าจะไม่มีข้อผิดพลาดเกิดขึ้นให้ลบตัวเลขตัวแรกทุกครั้ง โปรดทราบว่าฟังก์ชั่นนี้จะวนซ้ำในอินพุตที่ไม่ถูกต้อง

0นอกจากนี้ยังเป็นกรณีพิเศษที่จำเป็นสำหรับการป้อนข้อมูล

สรุปแล้วฉันคิดว่ารหัสนั้นดี แต่สิ่งอำนวยความสะดวกด้านภาษาน่าจะดีกว่า ใครต้องการข้อผิดพลาด


3

Python 3, 138

สิ่งนี้อิงจากแนวทางของ TanMath / Ogaday ในการอ่านตัวเลขเป็นสตริงและแยกวิเคราะห์แบบนั้น ฉันต้องใช้การกำหนดดาวบนiเพื่อให้สามารถจัดการจำนวนเต็มได้อย่างถูกต้อง

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

งูหลาม 141 132 128 ไบต์

อันนี้ยังค่อนข้างอ่านได้ แปลงเป็นสตริงและจัดการ>1ตัวเลขแยกจาก<1ตัวเลข เรามีกรณีพิเศษสำหรับศูนย์ ฉันสามารถลบช่องว่างอีกสองช่องด้านล่างได้

ข้อเสียคือมันจะพังทลายสำหรับลอยที่มีมากกว่า 9 ตำแหน่งทศนิยม

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)

ด้านล่างเป็นต้นฉบับ การแก้ไขครั้งแรกคือการตัดให้สั้นลงเป็นศูนย์กรณีพิเศษการแก้ไขที่สองคือการลบ 0 ก่อนที่จะมีทศนิยมทศนิยมที่สามคือการลบวงเล็บพิเศษและช่องว่าง

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

คำอธิบาย:

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

คุณไม่จำเป็นต้องรวมการแก้ไขโค้ดของคุณทุกครั้ง หากเราต้องการเห็นความคืบหน้าการเล่นกอล์ฟของคุณเราสามารถดูประวัติการแก้ไขได้ ยังไงก็ตามยินดีต้อนรับสู่ PPCG!
lirtosiast

1
เพิ่งค้นพบมัน ... ฉันจะต้องพยายามไม่ใช้เวลามากเกินไปในเว็บไซต์นี้!
เพลท

2

Mathematica, 81 ไบต์

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

กรณีทดสอบ:

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

3
ฉันไม่คิดว่าจะอนุญาตให้มีจุดทศนิยมเหนือส่วนจำนวนเต็มได้
Martin Ender

2

CJam, 44 ไบต์

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

ลองที่นี่

มันล้มเหลวกรณีทดสอบล่าสุดและส่งออกต่อไปนี้:

9000000+9e-7

แต่สมมุติว่ามันแม่นยำเกินไปที่ CJam ไม่สามารถจัดการได้

คำอธิบาย

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 ไบต์

จัดการกับสนามกอล์ฟได้ดี 19 ไบต์ด้วยคำแนะนำของ @Thomas Kwa ด้านบนresult or['0']และจัดเรียงพีชคณิตบางส่วน ( 154 ไบต์ ):

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

จนถึงตอนนี้ความพยายามที่ดีที่สุดของฉัน ( 173 ไบต์ ) ขึ้นอยู่กับวิธีการใหม่ให้ดูที่ด้านล่างของโพสต์:

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]

golfed ต้นฉบับของฉันลงไปที่180 ไบต์ :

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]

ฉันเรียนรู้คุณลักษณะภาษาใหม่วันนี้! เงื่อนไขผ่านการจัดทำดัชนีบูลีน ฉันอาจจะมากเกินไปเล็กน้อย

ฉันพยายามสรุปความเข้าใจ แต่ฉันไม่สามารถทำให้สั้นลง ( 196 ไบต์ ):

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

(ลำดับการย้อนกลับมีราคาแพง!)

ขณะที่เหมืองสั้นสำหรับตอนนี้ผมคิดว่า TanMath สามารถกอล์ฟของเขาลงเพื่อให้ตรงกับเหมือง: การใช้e=enumerateแทนที่passด้วย0และการใช้'0'ในสถานที่ของ['0']ในคำสั่งกลับควรบันทึก 4 + 3 + 2 = 9 ไบต์! ลดลงเหลือ 187 ฉันแน่ใจว่าสามารถลบข้อมูลบางส่วนออกจากที่อื่นได้ ...

แก้ไขวิธีการใหม่ ( 156 ไบต์ ) อย่างไรก็ตามมันสามารถจัดการกับความแม่นยำสูงถึง 6dp คล้ายกับรายการ CJam ของ @ jimmy23013 ดังนั้นจึงล้มเหลวในการทดสอบขั้นสุดท้าย ฉันไม่สามารถบีบบังคับให้พิมพ์ 0s ได้มากกว่านี้บางทีอาจมีคนอื่นทำได้ แต่ฉันใช้มันเป็นพื้นฐานของความพยายามที่ดีที่สุดของฉันดูด้านบน (เช่นกันวิธีการนี้จะพิมพ์ 0 ก่อนตำแหน่งทศนิยม แต่ดูเหมือนจะใช้ได้เช่นกัน) ใช้try:... except:...แนวทางจาก 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] 

หากคุณกำลังพยายามที่จะให้ความช่วยเหลือกอล์ฟกับฉันโปรดรวมพวกเขาเป็นความคิดเห็นคำตอบของฉันไม่ได้อยู่ในคำตอบของคุณ ฉันไม่เห็นคำตอบของคุณเสมอดังนั้นโดยการเขียนความคิดเห็นฉันจะได้รับการแจ้งเตือนและเห็นอย่างแน่นอน
TanMath

2
สวัสดี @ TanMath ฉันต้องการ แต่ฉันมีตัวแทนไม่เพียงพอที่จะแสดงความคิดเห็นในโพสต์ของคนอื่น เมื่อฉันได้รับการขึ้นอีกสองสามครั้งฉันจะทำให้แน่ใจว่าได้แสดงความคิดเห็นในความคิดเห็น
Ogaday

2

ทุบตีบริสุทธิ์ 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= 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}

ทดสอบ:

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 ไบต์

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

ฟังก์ชั่นการเรียกซ้ำแบบยุ่ง ๆ จริงๆอาจไม่ใช่วิธีที่ดีที่สุดในการทำสิ่งนี้ f("10.0203")การป้อนข้อมูลเช่น


นี่มันแม้แต่งูใหญ่ไหม? รักมัน
Ogaday

2

C, 155 153 161 ไบต์

+2 เพื่อเชื่อมโยงในไลบรารีคณิตศาสตร์ (แหล่งที่มาคือ 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 ไบต์

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

'123'ใช้เวลาจำนวนในรูปแบบเวกเตอร์ของตัวละครเช่น

ตัวอย่าง:

      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     

หมายเหตุ:
○เหตุผลสำหรับตัวอย่างล่าสุดที่แก้ไขคือ APL เช่นเดียวกับการส่งอื่น ๆ โดยค่าเริ่มต้นจะเปลี่ยนเป็นสัญกรณ์ทางวิทยาศาสตร์สำหรับจำนวนที่มากที่สุด
○วลี↑⍕¨f¨,¨นี้จำเป็นสำหรับการประมวลผลตัวอย่างทั้งหมดในครั้งเดียวเท่านั้น


1

เรติน่า, 113 ไบต์

ปัจจุบันใช้เวลานานกว่าโซลูชันของ Martinแต่ใช้วิธีการอื่นดังนั้นฉันจึงตัดสินใจโพสต์

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

¶\..*¶.*

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

ลองออนไลน์ได้ที่นี่


1

perl, 132 ไบต์

131 +1 สำหรับ-pสวิตช์

นี่เป็นไปตามคำตอบก่อนหน้าของฉันsed :

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/

ชุดทดสอบ:

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 ไบต์

ทั้งหมดในบรรทัดเดียว:

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

กรณีทดสอบรวมอีกหนึ่งกรณี:

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 ไบต์

ใช่ฉันเป็นคนขี้เกียจที่เพิร์ลกอล์ฟ

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

ลองที่นี่


ดูเหมือนจะไม่ทำงานกับตัวเลขจำนวนเต็ม
F. Hauri

ฉันใส่ผิดลิงค์ Ideone ไม่คำนึงถึงการเปลี่ยนแปลงบัญชีที่ทำในโหมดแก้ไข :( มันควรจะใช้ได้แล้ว
พอลปิคาร์ด

คุณมีข้อผิดพลาดบางแห่ง: เมื่อฉันใส่มันกลับมา5 50
F. Hauri

แปลกเนื่องจากฉันทดสอบ 5 ด้วยลิงก์ที่ฉันให้ไว้เมื่อวานนี้หลังจากที่คุณใส่ความคิดเห็นแรกของคุณ ลองตอนนี้ (ฉันเปลี่ยนลิงค์อีกครั้ง)
Paul Picard

ฉันเพิ่งทดสอบสคริปต์ของคุณในล่ามภาษา perl (v5.20.2) ของฉัน
F. Hauri

1

ชวา 284 244 243 ไบต์

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

น่าเสียดายที่ฉันไม่สามารถหาวิธีที่สั้นกว่าในการสร้างสตริงซ้ำซ้ำกว่า:

  • สร้างchar[]ความยาวที่ต้องการ
  • ใช้Arrays.fillสำหรับตั้งค่าตัวละคร
  • ใช้new Stringเพื่อให้สามารถต่อกันได้

ด้วยแรงบันดาลใจจาก @Khaled A Khunaifer ฉันสามารถโกน 40 ไบต์ได้

แก้ไข: indexOfใช้เวลานานดังนั้นฉันสามารถแทนที่'.'ด้วย แต่น่าเสียดายที่นี้ไม่ได้ดูเหมือนจะเป็นไปได้ด้วย46replace


ฉันจัดการเพื่อลดขนาดลงเหลือ 250 ตรวจสอบideone.com/HqLnMo
Khaled.K

@ Khaled A Khunaifer ทางออกของคุณดูเหมือนจะมีปัญหากับกรณีทดสอบหลักเดียว แต่ฉันชอบวิธีสร้างศูนย์
ECS

แก้ไข.replace('\0','0')ฟังก์ชั่นนี้แทนที่คาดว่าจะStringไม่charควร.replace("\0","0")
Khaled.K

@ Khaled A Khunaifer มันใช้งานได้ในกรณีทดสอบของฉันเช่นdocs.oracle.com/javase/8/docs/api/java/lang/…
ECS

1

Python ขนาด 125 ไบต์

หลังจากลบคำตอบแรกของฉัน (sry!) ซึ่งไม่สามารถจัดการกับตัวเลขขนาดเล็กได้เนื่องจากปัญหา epsilon ของเครื่องฉันพบวิธีแก้ไขปัญหาอื่น มันจัดการลอยเช่นเดียวกับจำนวนเต็มต่อท้ายศูนย์ (!) และเขียนเป็นฟังก์ชั่น

ขอบคุณ @ogaday สำหรับคำแนะนำที่เป็นประโยชน์และสำหรับ '0'-fix ขนาดกะทัดรัด!

แข็งแรงเล่นกอล์ฟ:

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'

การใช้งาน:

>>> 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
ดี f('0')อย่างไรก็ตามกรณีทดสอบล้มเหลวและเมื่อฉันคัดลอกและวางลงในล่ามของฉันโดยตรงฉันจะได้รับสัญลักษณ์ทางวิทยาศาสตร์ (ซึ่งฉันคิดว่าใช้ได้) นอกจากนี้list(c)จะสั้นกว่า หากคุณ concatenate '.'ก่อนที่จะเปลี่ยนมันเป็นรายการที่คุณไม่จำเป็นต้องเพิ่ม[]อย่างใดอย่างหนึ่ง ใช้findแทนดัชนีบนสตริงก่อนที่จะเปลี่ยนเป็นรายการหลังจากเพิ่ม'.'ยังช่วยให้คุณประหยัดไบต์ การจัดระเบียบความไม่เท่าเทียมกันใหม่ช่วยให้คุณสามารถลบพื้นที่เพิ่มเติมได้เช่นกัน: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 ไบต์

โซลูชั่นตรงไปข้างหน้า:

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

ปฏิบัติการ:


1

Stax , 18 ไบต์

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

เรียกใช้และแก้ไขข้อบกพร่อง

คลายกล่อง ungolfed และแสดงความคิดเห็นมันมีลักษณะเช่นนี้

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

เรียกใช้อันนี้

เช่นเดียวกับโซลูชันอื่น ๆ มากมายที่โพสต์ไว้สร้างขึ้น9000000+9e-7สำหรับกรณีทดสอบล่าสุด ตามแบบอย่างที่จัดตั้งขึ้นสิ่งนี้ได้รับอนุญาตเพราะกรณีทดสอบนั้นแม่นยำเกินไปสำหรับภาษา


0

Lua, 350 ไบต์

ฉันคิดว่ามันมีวิธีตีกอล์ฟสองทางเพิ่มเติม:

  • ฉันสามารถใช้macro.defineเพื่อแทนที่นิพจน์ทั่วไป (ไม่สามารถทดสอบได้ในตอนนี้และไม่แน่ใจว่ามันจะทำให้ฉันได้รับไบต์)

  • ใช้การแบ่งบนจุดแทนการวนซ้ำบนสตริงทั้งหมด อีกครั้งฉันไม่แน่ใจว่ามันจะลดขนาดของฟังก์ชั่นนี้เนื่องจากการจัดการสตริงใน lua ค่อนข้างเจ็บปวด

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

คำอธิบาย

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

คุณสามารถทดสอบ lua ออนไลน์และใช้ซอร์สโค้ดต่อไปนี้เพื่อเรียกใช้กับกรณีทดสอบบางกรณี

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 ไบต์

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

หมายเหตุ: putchar(8)ควรทำการแบ็คสเปซ

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

รายละเอียด , พยายามที่นี่

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

ลดลง 8 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

กรณีทดสอบ:

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 ไบต์

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

ทำงานร่วมกับตัวเลขความยาวโดยพลการเพราะใช้การจัดการสตริงตลอด

ไม่มีความเข้าใจของอาร์เรย์ (122 ไบต์):

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

เท่าที่ฉันรู้ไวยากรณ์ความเข้าใจอาร์เรย์ใหม่นี้มาจาก ECMAScript 7
จัดการ

@ การจัดการขอบคุณฉันอัปเดตในขณะที่ฉันกำลังเพิ่มเวอร์ชันที่ไม่ได้อัปโหลด
Neil

0

R - 133 ไบต์

ทนทานละเว้น Machine Epsilon และทำงานกับศูนย์ต่อท้าย

a) Golfed:

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

การใช้งาน:

f("900.008")
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.