加号和时代,一个人和一个人


18

将该递归关系实现为输入和输出非负整数的函数或程序:

  • F(0)= 0

  • F(N)=大于F(N-1)的最小整数,以使其基数10的总和和/或乘积为N

N是程序的输入,而F(N)是程序的输出。

要清楚的是,像913这样的数字中的数字总和为9 + 1 + 3 = 13。乘积为9×1×3 = 27。对于一位数字,总和与乘积是相同的数字。包含0的数字当然具有乘积0。

通过F(70)得出的结果是:

N F(N)
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 19
11 29
12 34
13 49
14 59
15 69
16 79
17 89
18 92
19 199
20 225
21 317
22 499
23 599
24 614
25 799
26 899
27 913
28 1147
29 2999
30 3125
31 4999
32 5999
33 6999
34 7999
35 8999
36 9114
37 19999
38 29999
39 39999
40 41125
41 59999
42 61117
43 79999
44 89999
45 91115
46 199999
47 299999
48 311128
49 499999
50 511125
51 699999
52 799999
53 899999
54 911116
55 1999999
56 2111147
57 3999999
58 4999999
59 5999999
60 6111125
61 7999999
62 8999999
63 9111117
64 11111188
65 29999999
66 39999999
67 49999999
68 59999999
69 69999999
70 71111125

以字节为单位的最短代码获胜。如果可以证明您的代码利用了某些效率,则表示荣誉。



1
顺序不正确。
加尔文的爱好

Answers:


4

05AB1E20 12字节

由于Osable,节省了8个字节!

µNSDOsP‚¾>å½

使用CP-1252编码。在线尝试!


是否需要长度测试?我想出了µNSDOsP‚¾>å½。它似乎适用于随机选择的数字。
2016年

@Osable Ahh当然,你是个天才!我什至不知道为什么要包括在内。
阿德南

令人惊讶的是,您如何突然将20字节的程序减少40%...
NikoNyrh,2016年

3

Mathematica,71个字节,68个字符

±0=0;±n_:=(For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];x)

仅再增加4个字节,这是一个存储的值的版本±n

±0=0;±n_:=(For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)

对于后一种版本,在评估之前±nPlusMinus将有两个下降值:

In[2]:= DownValues@PlusMinus
Out[2]= {HoldPattern[±0] :> 0, HoldPattern[±n_] :> (For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)}

现在,如果我们评估±20

In[3]:= ±20
In[3]:= 225

In[4]:= DownValues@PlusMinus
Out[4]= {HoldPattern[±0] :> 0, HoldPattern[±1] :> 1, HoldPattern[±2] :> 2, HoldPattern[±3] :> 3, HoldPattern[±4] :> 4, HoldPattern[±5] :> 5, HoldPattern[±6] :> 6, HoldPattern[±7] :> 7, HoldPattern[±8] :> 8, HoldPattern[±9] :> 9, HoldPattern[±10] :> 19, HoldPattern[±11] :> 29, HoldPattern[±12] :> 34, HoldPattern[±13] :> 49, HoldPattern[±14] :> 59, HoldPattern[±15] :> 69, HoldPattern[±16] :> 79, HoldPattern[±17] :> 89, HoldPattern[±18] :> 92, HoldPattern[±19] :> 199, HoldPattern[±20] :> 225, HoldPattern[±n_] :> (For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)}

这大大加快了未来的计算,因为数学将不再计算的值020递归。随着时间的n增加,节省的时间更加戏剧化:

In[5]:= Quit[]

In[1]:= ±0=0;±n_:=(For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)

In[2]:= AbsoluteTiming[±60]
Out[2]= {23.0563, 6111125}

In[3]:= AbsoluteTiming[±60]
Out[3]= {9.89694*10^-6, 6111125}

从F(N-1)开始,而不是F(N-1)+1;复发率必须严格提高。
LegionMammal978 '16

2

C#,155个 159 135字节

a=n=>{if(n<1)return 0;int i=n,s=0,p=1,N=a(n-1);for(;;){s=0;p=1;foreach(var c in++i+""){s+=c-48;p*=c-48;}if(i>N&(s==n|p==n))return i;}};

超低效,仅需很长时间N>=14。会尝试获得更有效但更长的解决方案。

好的,现在好多了,但是要多4个字节。哦,我N<=50现在可以很快做。感谢@milk节省24个字节!


-2个字节,用替换for for(;;)和foreach foreach(var c in++i+"")。-22个字节替换int.Parse(c+"")c-48
牛奶

2

Pyth- 18 17字节

感谢@Jakube,节省了一个字节!

使用减少做递归的事情。

uf}HsM*FBjT;hGSQZ

测试套件


sM*FBjT;还会生成数字和和乘积,且短1个字节。
雅库布

@Jakube ooh好招
Maltysen

1

R,124112字节

f=function(N){y=x=`if`(N-1,f(N-1),0);while(N!=prod(y)&N!=sum(y)){x=x+1;y=as.double(el(strsplit(c(x,""),"")))};x}

在N = 45时失败,因为R坚持将10.000写为1e + 05 as.numeric(),这并不为所赞赏,这可以通过使用as.integer()12字节的代价来修复:

f=function(N){y=x=`if`(N-1,f(N-1),0);while(N!=prod(y)&N!=sum(y)){x=x+1;y=as.double(el(strsplit(c(as.integer(x),""),"")))};x}

作为一种统计编程语言,R具有令人讨厌的冗长的方式,将数字分为数字向量。特别是因为必须将所有内容从字符串显式转换回数字值。

多亏了Billywob,节省了12个字节。


1
您可以用于as.double(el(strsplit(c(x,""),"")))将整数拆分为其数字的向量。但是,你仍然会碰到的格式化问题,但可以作为你的答案被解决as.integer()
Billywob

哦,强制将x转换为字符串的巧妙方法:o
JAD

您也可以改用sprintf()直接将整数格式化为不带尾随零的字符串:as.double(el(strsplit(sprintf("%1.f",x),"")))并跳过使用as.integer()
Billywob

@ LegionMammal978它在while循环中所做的第一件事是,x=x+1并且保证它会被评估一次,因为在开始时y=F(N-1)肯定不等于N
2016年

@JarkoDubbeldam糟糕,P
LegionMammal978,2013年

1

的JavaScript(ES6)109 107 105 91 89个字节

f=n=>n&&eval(`for(i=f(n-1);++i,${x="[...i+''].reduce((r,v)=>"}+r+ +v)-n&&${x}r*v)-n;);i`)



console.log(f.toString().length + 2); 
console.log(f(25));
console.log(f(13));
console.log(f(8));                                  


1

JavaScript(ES6),84 86

编辑:2字节保存thx @Arnauld

f=n=>eval("for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);v")

测试注释超过50,它将占用您过多的CPU,请点击“隐藏结果”以免为时已晚

f=n=>eval("for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);v")

out=x=>O.textContent=x+'\n'+O.textContent

i=0
step=_=>out(i+' '+f(i),++i,setTimeout(step,i*10))

step()
<pre id=O></pre>


我认为for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);v应该保存2个字节。我怀疑它可以再缩短一些,但是到目前为止我还无法弄清楚。
Arnauld

@Arnauld我期望重复的浮点除法会出现一些问题
edc65 '16

我们唯一的要求是p /= dd实际上是的除数时产生精确的结果p。除非我弄错了,否则任何情况都是如此d <= p <= Number.MAX_SAFE_INTEGER。当时p % d != 0,我们会得到浮点舍入错误,但这应该是安全的。
Arnauld 2016年

@darrylyeo不要给您建议您不要尝试一下(尝试eval`1+1` )(这就是为什么codegolf.stackexchange.com/a/52204/21348:阅读第一个评论)
edc65

1

Mathematica,67个字节

a@0=0;a@b_:=NestWhile[#+1&,a[b-1]+1,+##!=b&&1##!=b&@*IntegerDigits]

函数名为a。将数字作为输入并返回数字作为输出。受之前的Mathematica解决方案启发,但使用了不同的循环机制。


1

C,240字节

int f(char n){int q[19],i=19,r=n%9,j=9,*p=q,c=n/9;while(i)q[--i]=0;if(c){if(!r){r=9;c--;}q[9]=c;if(!(n%r)){n/=r;while((j-1)*(n-1)*c){if(n%j)j--;else{c--;q[9+j]++;n/=j;}}q[10]=c;if(1==n)p+=9;}while(++i<10){while(p[i]--)r=r*10+i;}}return(r);}

尝试利用序列的一些数学属性。


0

PowerShell v3 +,114字节

param($n)$i=,0;$l=1;1..$n|%{for(;$_-notin((($b=[char[]]"$l")-join'+'|iex)),(($b-join'*'|iex))){$l++}$i+=$l};$i[$n]

迭代解决方案,没有简单的方法可以将数字转换为数字的总和/乘积,因此比JavaScript的答案要长得多。

取输入$n,套$i与只是一个阵列0(这是收集F(),并设置$l等于1(这是最新的F从)。然后,我们环向上1$n,每次迭代执行for循环。

for循环的条件取$lATEST数目,在一个字符串"$l",然后投射,作为一个char-array,并且存储阵列到临时变量$b。然后,我们将-join这些数字与一起+并将其输送到iex(简称,Invoke-Expression与相似eval)。此外,我们也对进行类似操作*。这两个数字被封装在parens中,并作为-notin运算符针对$_外部循环当前数的数组参数(即,for循环运行的时间只要两者中的一个都不同+*并且不同于$_)。for循环的主体只是递增$l++

一旦走出内for循环,我们将$lon 添加为的新元素$i。一旦我们完全完成了范围循环,就可以放置$i[$n]在管道上,并且输出是隐式的。

NB- 20仅仅由于循环结构,在about左右执行起来会非常缓慢。例如,N=40在我的机器上花费大约两分钟,而我什至没有打扰测试N>50


0

Pyke,17个字节

t.fY'Bs]~ohR{Io(e

在这里尝试!

或13个字节不竞争

first_n现在将已找到的项目数量加上一个(i如果使用)。

Q.fY'Bs]iR{)e

在这里尝试!

Q.f        )  -  first_n(input, start=1)
   Y          -   digits(^)
    'Bs]      -   [sum(^), product(^)]
         R}   -   V in ^
        i     -    len(results)+1
            e - ^[-1]


0

不可思议,49个字节

f\.{0\0@(:>@(| =#1sum#0)=#1prod#0)(dp +1f -#0 1)N

模式匹配!用法:

f\.{0\0@(:>@(| =#1sum#0)=#1prod#0)(dp +1f -#0 1)N}; f 10

更具可读性:

f\.{
  0\0
  @(
    find @(or = #1 sum #0) = #1 prod #0
  ) (dp + 1 (f -#0 1)) N
}

这基本上只是规范的逐字实现。


0

BASH,107个字节

折叠+粘贴+公元前

for ((;n<=$1;z++)){
p(){ fold -1<<<$z|paste -sd$1|bc;}
[ `p +` = $n -o `p \*` = $n ]&&((z-->n++))
}
echo $z

0

Befunge,101个字节

&20p>:000pv
>\1+^vp011<
| >.@>:55+%:00g+00p10g*v>10g-*
::\$_^#!:/+55p01*!`"~":<^\-g00
< |!-g02
+1< v\

在线尝试!但是请注意,一旦进入四十多岁,它将变得非常缓慢。如果要测试整个范围,则确实需要使用Befunge编译器。

说明

&20p           Read N and save for later.

>              Start of main loop; current target and test number on stack, initially 0.
:              Duplicate the test number so we can manipulate it.
000p           Initialise the sum to 0.
110p           Initialise the product to 1.

>              Start of inner loop.
:55+%:         Modulo 10 of the test number to get the first digit.
00g+00p        Add to the sum.
10g*           Multiply by the product.
:"~"`!*        If greater than 126, set to 0 to prevent overflows - it'll never match.
10p            Update the product variable.
55+/           Divide the test number by 10 to get the next digit.
:!_            If not zero, repeat the inner loop

$              Drop the zero left over from the loop.
\::00g-\10g-   Compare the sum and product with the current target.
*|             Multiply the two diffs and branch; up if no match, down if either match.
\1+^           On no match, we increment the test number and repeat the main loop.
:>20g-!|       With a match, we compare the current target with the saved N.
1+\v           If that doesn't match, increment the current target and restart main loop.
\>.@           If it does match, we've got our result; output it and exit.

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.