扩大数量


58

您可能还记得在一年级或二年级时使用扩展形式来了解数字的位数。举个例子更容易解释,所以考虑数字123。以扩展形式表示为100 + 20 + 3,可帮助年轻的头脑可视化地方价值。这让人想起你怎么说:一百(加)二十(加)三。

我们可以将其扩展到小数点后的单位位置: 2.718 => 2 + 0.7 + 0.01 + 0.008

您面临的挑战是编写一个程序或函数,该程序或函数的浮点数应为正数或零(假设它的大小等于您的语言可以处理的大小或精确度;它不会采用科学计数法)或字符串,然后以扩展形式打印/返回它如上所述。

+小数点前的或零之间都不需要空格,因此上面的示例可能是2+.7+.01+.008101.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ᴡɴɢᴏᴀᴛ很高兴看到模因还在运行。

4
以我们(法国)计数的相同方式来做,看到人们在97(4 * 20 + 10 + 7)的情况下苦苦挣扎是一件很有趣的事
Katenkyo

2
@ jimmy23013是的,只要它在理论上起作用即可。
NinjaBearMonkey

1
@Ogaday我不知道,这只是一些极端情况。也许NBZ方式会更好,但是,如果真的很有趣,那就不要了
Katenkyo

Answers:


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 '16

@ jimmy23013哇,太短了!谢谢!
丹尼斯

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 2016年

@ETHproductions如果输入数字小于该数字1,则将中断,因为Math.log10(n)将返回负数并|0四舍五入而不是四舍五入。
user81655 '16

可以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 '16

@DomHastings仍然n=0.1不管用。
尼尔

5

视网膜86 77 75字节

字节计数假定源已编码为ISO 8859-1。

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

尾随换行很重要。

在线尝试。

说明

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

尽管只有前导(或尾随)数字是正确的,但我们首先将输入变成一个单独的换行符列表。这是通过滥用拆分阶段来完成的。我们不对输入进行拆分,而是对所有输入进行匹配,因此其余部分均为空。我们使用_选项删除了这些空段。问题在于拆分阶段还返回所有捕获组的值。因此,我们在每个匹配项中使用前瞻性来捕获字符串的正确部分:首先,我们尝试找到.匹配项的左侧。如果是这种情况,我们将从.直到并包括我们当前匹配的数字。否则,我们必须位于输入的整数部分,因此我们将捕获匹配项之后的所有数字(包括匹配项)。我们还必须摆脱小数点本身,因此第二个捕获是可选的。如果没有\d要捕获的内容,则只会从输入中删除匹配项。

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

现在,我们使用音译阶段将除了前导/尾随数字之外的所有数字都变为零。我们可以匹配一个小于1的部分,\..+\B\B确保在结尾处停止一位数字的匹配,或者匹配一个整数部分,(?<=^\d).+其后向确保我们以数字开头的一位。然后音译阶段将d比赛中的所有数字()替换为零。

¶([.0]+¶)*
+

现在,实际的输出格式不应使用+换行符作为分隔符。本场比赛换行做替换。在执行此操作时,我们还将删除仅包含0s和.s的行。

^0.|\+0$

上一阶段不会删除开头或结尾0(因为它们前后没有换行符),因此我们明确删除了它们。


4

Python 2中,216个 210 196 175字节

这是一些打高尔夫球的代码,我在有空的时候会进一步打高尔夫球。它使用字符串分析。

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

说明

因此,输入被分为整数和小数部分。然后,有一个for循环列表理解。在整数部分,十进制字符后的字符串长度乘以“ 0”,如果该字符末尾有那么多的零。

对于小数部分,当前字符的索引是它前面的零个数,因此该部分很简单。

try和except用于确定它是否具有小数部分(使用错误)。

最终结果加上加号。

在这里尝试!


2
我认为o if o else ["0"]可以o or["0"]
lirtosiast '16

您在第四行上有一个尾随空格,这增加了您的字节数。在第四行,您只需要一个冒号。您可以在下面的代码片段删除空格:o=[(...)] fore(I) ife(i[1]) ifprint "+",并在外层的括号o=[(...)为好,其实。最后,您可以像这样从join函数中取出最后一个条件:print"+".join(o)or"0"因为join如果o为空,将返回一个空列表,因此该条件将以与节省一个字节相同的方式求值。
Ogaday'1

3

Pyth,30个字节

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

测试套件

此处的基本解决方案是用替换输入中的所有数字0,然后将每个数字插入适当的位置,求值,滤除零,然后加上加号。不幸的是,Pyth的eval函数当前不接受前导零。我将努力解决此问题。

为了解决这个问题,我添加了一个辅助函数,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

Python,第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
刚发现它...我将不得不尝试不要在此站点上花费太多时间!
speedplane

2

Mathematica,81个字节

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

测试用例:

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

3
我认为小数点不能超过整数部分。
马丁·恩德

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字节

感谢@Thomas Kwa的上述建议,成功地将高尔夫球打了19个字节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]

将我的原始文件压缩到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可以与我的比赛相提并论:在return语句中使用e=enumerate,替换pass0,并使用'0'代替['0']应该节省4 + 3 + 2 = 9字节!将其降低到187。我敢肯定,可以在某个地方将其他几个字节切掉...

编辑新方法(156字节)。但是,它只能处理高达6dp的精度,类似于@ jimmy23013的CJam条目,因此它无法通过最终测试。我不能强迫它打印更多的0,也许其他人可以。取而代之的是,我将其用作我的最佳尝试的基础,请参见top(此外,此方法在小数点后输出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'1

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


这甚至是Python吗?爱它。
Ogaday'1

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

不打高尔夫球

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

取消高尔夫:

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

您的正则表达式会过滤掉$args = 0这是一个简单的错误修复程序,也节省了3个字节
Veskah


1

Perl,248个字节

嗯,我对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;

在这里尝试。


这似乎不适用于整数。
F. Hauri

我放错了Ideone链接。它没有考虑在“编辑”模式下所做的更改。:(这应该现在的工作。
保罗·皮卡德

您在某个地方出错:当我输入5它时,return 50
F. Hauri

奇怪,因为在您发表第一个评论后,我用昨天提供的链接测试了5。现在想尝试吗?(我再次更改了链接)
保罗·皮卡德

我刚刚在我的perl解释器(v5.20.2)上测试了您的脚本
F. Hauri

1

Java 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需要一个int,所以我可以替换'.'46。不幸的是,使用似乎无法实现replace


我设法将其缩小到250,请查看ideone.com/HqLnMo
Khaled.K

@Khaled A Khunaifer您的解决方案似乎有单位测试用例的问题。但我喜欢您生成零的方式。
ECS

修复此.replace('\0','0')功能替换为Stringnot not not char应该是.replace("\0","0")
Khaled.K,2016年

@Khaled A Khunaifer在我的测试用例中也可以使用docs.oracle.com/javase/8/docs/api/java/lang/…–
ECS

1

Python,125个字节

删除由于机器epsilon问题而无法处理少量数字的第一个答案(很抱歉!)后,我找到了另一种解决方案。它处理浮点数和整数,后跟零(!),并作为函数编写。

感谢@ogaday提供有用的提示和紧凑的“ 0”修复!

打高尔夫球:

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'

取消高尔夫:

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)更短。如果'.'在将串联到列表之前将其串联起来,则无需添加[]任何一个。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'
排列

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╜♥←

运行并调试

拆开包装,松开包装并进行评论,看起来像这样。

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来替换一些公用表达式(目前无法测试,并且不确定是否会使我获得一些字节)

  • 在点上使用split而不是遍历整个字符串。再一次,我不确定是否会减小此函数的大小,因为在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,136128字节

通过减少空格和无用减少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

取消高尔夫:

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
manatwork

@manatwork谢谢,我在添加非高尔夫版本时对其进行了更新。
尼尔

0

R-133字节

健壮性,忽略Machine Epsilon并与尾随零​​一起工作。

a)打高尔夫球:

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=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")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.