近似胶号


24

挑战

塑料数是相关的黄金比例的数,有许多有趣的数学性质。因此,有许多方法可用于计算数量。

为了精确地为挑战指定数字,我们将使用以下定义(尽管有很多等效定义,并且您可以使用任何希望的定义,只要它涉及相同的数字):

塑料数目是一个实数ρ,使得ρ ³= ρ 1。

您面临的挑战是编写一个程序或函数,该程序或函数将整数x作为输入(x > 1),并生成与ρ近似的输出,因此x的值越大,输出越接近ρ(例外情况最多为几个;为此,保持在与“ closer”相同的值),并且对于任何正数δ,您的程序中都有一些输入x产生的输出在ρδ内。

澄清说明

  • 如果您通过固有地输出字符串的方法(例如标准输出流)进行输出,则可以将输出格式化为十进制(例如1.3247179572),或者以两个整数/之间的一个字符的比率进行格式化。
  • 如果要在编程语言中作为值输出(例如,从函数返回),则该值必须为定点,浮点或有理类型。(特别是,您不能使用符号存储数据的数据类型,除非它们仅用于保存两个整数的比率。因此,如果您使用的是Mathematica或类似的语言,则需要包括实际生成输出数字的代码。)
  • 您的答案必须使用您的语言的一种假设变体,其中整数可以任意大,并且内存(包括堆栈)是无限的。您可能不会假设您的语言中的浮点算术是任意准确的,而是必须使用其实际精度(这意味着仅在可以使用浮点数精度的语言中才可以输出浮点数。在运行时进行控制)。
  • x可以具有您想要的任何含义(只要增加它可以提供更准确的输出)。我想大多数提交将控制它产生的输出位数,或程序用于收敛到可塑数的算法迭代次数,但其他含义也可以接受。

测试用例

这是塑料编号的前几位数:

1.32471795724474602596090885

OEIS上有更多数字可用。

胜利条件

,以字节为单位,越短越好。但是,请随意发布答案,即使它们没有获胜,只要它们在现有答案中添加一些内容(例如,不同的语言或不同的算法)即可。


1
嗯,(cbrt(108 + 12 * sqrt(69))+ cbrt(108-12 * sqrt(69)))/ 6这似乎是使用Drake近似的好时机:sqrt(69)= 8。一些bit.ly/2rCqedX ^ _ ^
DrQuarius

2
我们还可以假设递归/堆栈深度是无限的吗?
xnor

为了阐明第二点,我们可以使用任意精度的库(例如Python中的mpmath)吗?它们使用辅助数据类型,但是您是否认为这是“象征性地”存储事物?
蝙蝠侠

1
好吧,至少我希望答案能收敛到ρ。另外,“诚实”的解决方案很容易使测试x> y-> |ρx-ρ|失败> |ρy-ρ| 有限数量的(x,y)对。如果不可接受,我认为应该在规范中对此进行更明确的说明。
丹尼斯,

6
许多答题者陷入了计算ρ的x位数逼近的陷阱(?),问题是可能存在无限多个x,使得(x +1)位数逼近并不比x位数逼近更好。您可能应该澄清您是否打算允许这样做。如果不这样做,则将“ closer”替换为“ strictly close”;如果您这样做,“至少接近”,或其他。您还可以考虑宽松的要求,即序列收敛到ρ,这将另外允许xnor的答案。
Anders Kaseorg

Answers:


10

Python 2,49个字节

n=x=input()
while n**3/x/x<n+x:n+=1
print n,'/',x

在线尝试!

这样做是为了表达ρρ³=ρ+1一个分数n/x,其分母x是输入精度参数。我们采用(n/x)³=n/x+1并清除分母来获得n³=x²(x+n)

由于LHS的增长n速度快于RHS,因此我们可以将等式点近似n为最小值n³≥x²(x+n)。在n这种情况下,代码一直递增计数,从此开始x较小。

一个小字节的保存是将写入双方分开n³/x²≥x+nwhile条件否定)。这是代码中的底数划分,但是丢失的小数部分可以忽略不计。

相反,将相同长度的替代项x作为分子:

Python 2,49个字节

n=x=input()
while x**3/n/n<n+x:n-=1
print x,'/',n

在线尝试!


尽管此输出收敛到ρ(∀ε> 0∃x₀∀x≥x₀| f(x)-ρ| <ε),但它不满足“ x的值越大,输出越接近ρ (最多有限地例外)”(∃x₀∀x≥x₀| f(x + 1)-ρ| <| f(x)-ρ|)。
Anders Kaseorg

这个问题可以通过使用2**input()而不是仅仅解决input(); 然后,每个近似值都将至少比以前近似。

10

Mathematica,20个字节

#^3-#-1&~Root~1~N~#&

Mathematica的内置Root函数为多项式方程式提供了解决方案f[x] == 0

说明

#^3-#-1&~Root~1~N~#&
                   &  (* Function *)
#^3-#-1&              (* A pure-function polynomial, x^3-x-1 *)
        ~Root~1       (* Find the first root *)
               ~N~#   (* approximate to (input) digits *)

样品I / O

In[1]:= f=#^3-#-1&~Root~1~N~#&;
        f[1]

Out[1]= 1.

In[2]:= f[9]

Out[2]= 1.32471796

In[3]:= f[100]

Out[3]= 1.324717957244746025960908854478097340734404056901733364534015050302827851245547594054699347981787280

PS:对于相同的字节数Root[x^3-x-1,1]~N~#&,可以正常工作(尽管不告诉它x是变量)。
格雷格·马丁

@AndersKaseorg:我更改了该规则,因为它显然被打破了。没有有效答案无效,但是一些答案(如此答案)变为有效。

6

Mathematica,27个字节

x/.Solve[x^3==x+1>2,x]~N~#&

Martin的
-1个字节-ovs的2个字节

输入

[27]

输出

{1.32471795724474602596090885}


Solve[x^3==x+1>2,x]~N~#&24字节
ovs

1
结果是这样{{x -> 1.32...}}。您可能要用ais检查这是否是有效的输出格式。
Martin Ender

确定..所有固定我猜
J42161217

它仍然{1.32...}是实际的,但是这种格式的争议可能较小。
Martin Ender

1
我对挑战进行了更笼统的描述,以使之有效,但这并不是要禁止“前x位数字”解决方案。因此,即使以前没有,现在也有效。

6

sed67 60(59 + 1)个字节

s,^,1/1/1 ,
:;s,(1*/(1*)/(1*).*)1$,\2\3/\1,
t
s,(/1*).*,\1,

在线尝试!

-E标记为+1 (ERE而不是BRE)。输入和输出都是一元的:x = 5的输入11111例如,输出是两个一元数的分数:前面提到的11111输入产生输出11111/1111(十进制5/4)。

将塑性数近似为Padovan序列的连续元素之间的分数。


1
FWIW,b命令后不需要空格,但是您可以通过使用空标签(:并且b不带参数)来使其更短。tio.run/#%23K05N@f@/…–
乔丹

太好了 而且我可以使用t代替来保存另外4个字节b,因此这是一个非常不错的保存。谢谢:)
FireFly

5

Mathematica,27个字节

Nest[(1+#)^(1/3)&,1,#]~N~#&

使用嵌套立方根形式³√(1 +³√(1 +³√(1 + ...)))的截断近似值。尽管输出将始终具有x-1个小数位,但结果实际上却不那么精确,因为每次迭代表达式的收敛速度都慢于一位数字(x还用作计算嵌套式部首的数量)。例如x = 100给出

_________________________________________________________________________
1.324717957244746025960908854478097340734404056901733364534015050302827850993693624204577670741656151

上划线部分正确的地方。


我原本打算在中编写此算法dc,但由于事实证明它没有多维数据集根运算而受到了阻碍,并且将幂raising提高一个数字也不起作用:-(至少您总能指望Mathematica具有适当的内置

3
@ ais523实际上有,CubeRoot但没有人为此得到字节。
Martin Ender

4

八度,50字节

@(n)char(digits(n)*0+vpasolve(sym('r^3-r-1'))(1));

在线尝试!

定义一个匿名函数,并n具有所需的输出位数。

此答案滥用,它digits以可变精度算术返回当前位数的设置。这意味着我们可以在匿名函数中使用它,而不会出现“输出参数过多”的错误。

除此之外,它非常简单:vpasolve可变精度算术求解的缩写,精度由上次调用来设置digits。由于vpa是Octave中的Symbolic数据类型,根据规范已被禁止,因此我们只包装整个函数char(...)以获取字符串输出。需要注意的是在solvevpasolve中,f==0是隐含的,所以r^3==r+1已被取代r^3-r-1 (==0)


我去了并更改了问题,以免它不允许这样的回答(这不是故意的)。

@ ais523感谢您的通知!
Sanchises

4

MATL(27 28字节)

7BG:"t@)y@Q)+h]tG3+)yG2+)/

我的第一个解决方案(27字节)

在线尝试!

当然这不是最佳选择,我仍然习惯于MATL。

说明:

我创建了一个Padovan序列,直到input + 3,然后找到最后两个数字的比率。

7B     % Turn 7 into binary to give 1 1 1 
G:"    % For k=1:input do...
t@)    % Existing sequence member k
y@1+)  % Existing sequence member k+1
+h     % Add them together and concatenate to the sequence array
]      % End loop
tG3+)  % Final sequence member
yG2+)  % Second last sequence member
/      % Divide to approximate ρ

正确的分数输出(35个字节)(28个字节,@ Sanchises):

但是,第一个解决方案不能满足默认MATL设置的浮点数限制对任意精度的需求。因此,而不是增加几个字节来扩展这个精度,这是更简单的,以采取适当的分数路径和写最后两个整数的第(N-1)的馏分和N 截短帕序列的元素。

例如“ 114/86”

7BG:“ t @)y @ 1 +)+ h] tG3 +)V'/'YcyG2 +)VYc

7BG:"t@tQh)sh]tJ)V47hyJq)Vh&

由用户@Sanchises提供。:)

在线尝试!

非迭代评估:

值得注意的是,我对“精确”版本的最短代码是(23个字节):

1-1h69X^12**108+1I/^6/s

在线尝试!

...但是没有给出任意精度。我想知道是否有人可以调整它来满足规则(使用输入等)并且仍然添加少于5个字节?:P


1
1+考虑到Q这一点,您可以将Just替换@)y@1+)+@tQh)s。此外,您可以使用J来指示数组的结尾。最后,MATL不能区分普通数组和字符数组,因此可以替换Ych(不需要的额外功能Yc)。这仅提供28个字节:(请7BG:"t@tQh)sh]tJ)V47hyJq)Vh&注意,&以防止多余的输出,并替换'/'为47)。
Sanchises

1
荣誉的7B,虽然,远好于天真的推动lllv
Sanchises

1
@DrQuarius最新版本始终可以在此GitHub链接中
Luis Mendo

1
@DrQuarius不,我通常使用的相当老的MATL规范中存在此行为。您应该真正检查一下表3。剪贴板不仅J默认包含1j,而且剪贴板L还包含许多有用的索引功能(请注意,MATL 中的1jequals end)。
Sanchises

1
另外,不用担心,我是机械工程师。我认为MATL(AB)在科学环境以外的用途很少,因此我想大多数MATL(AB)/ Octave高尔夫球手都来自CS以外。
Sanchises

4

M15 14字节

²×3’
*3Ḥ‘÷Ç
Ç¡

在线尝试!

算法

这使用了理性和牛顿的方法。具体而言,输入X,该第一X与起始值的迭代X被施加。

我们正在尝试找到多项式p(t)=t³-t-1的特定根。牛顿法通过采用一个足够接近ρ的起始值t 0并通过t n + 1 = t n -p(t n)/ p'(t n递归地定义一个序列来实现这一点。

因为P'(T)=3t²-1,我们得到
N + 1 = T ñ - (叔Ñ ³ -吨ñ - 1)/(3T ñ ² - 1)=(3T Ñ ³ -吨ñ -吨Ñ ³+吨ñ + 1)/(3T ñ ² - 1)=(2T ñ ³+ 1)/(3T ñ ² - 1)

注意,随着x的增加,初始近似值x逐渐变差。尽管x = 3的输出的精度比x = 2的输出稍差,但由于牛顿方法二次收敛到ρ,因此对于大x值不应该成为问题。

怎么运行的

Ç¡    Main link. Argument: x

Ç¡    Call the second helper link x times, which initial argument x.


*3Ḥ‘÷Ç  Second helper link. Argument: t

*3      Compute t³.
  Ḥ     Unhalve; yield 2t³.
   ‘    Increment; yield 2t³+1.
     Ç  Call the first helper link with argument t.
    ÷   Divide the left result by the right one.


²×3’    First helper link. Argument: t

²       Compute t².
 ×3     Compute 3t².
   ’    Decrement; yield 3t²-1.

太糟糕了,你不能使用... µ¡...
埃里克Outgolfer



1

木炭,28字节

AIθθAθνW‹∕∕Xν³θθ⁺νθA⁺ν¹νI∕νθ

在线尝试!链接到详细模式。此外,我显然是搞砸了DivideIntDivide:|
使用与Python和JavaScript答案相同的方法。


1

NewStack,14个字节

¹Fᵢ{E2x³⁺÷3x²⁻

分解:

¹                Add arbitrary number 1 to the stack.
 Fᵢ{             Define for loop with a user's input amount of itterations.
    E            Define new edit for element 0 (element 0 being the 1 added. earlier).
     2x³⁺÷3x²⁻   update x to equal (2x^3+1)/(3x^2-1). (x = element 0).

怎么运行的:

公式(2x 3 +1)/(3x 2 -1)来自对等式x 3 = x + 1 的牛顿方法的简化。你可以在这里找到它。重复此过程,无穷的时间收敛到可塑性数。它的收敛速度相当快,每次迭代大约为2.6个小数。

INPUT ITERATION >> VALUE
0 >> 1
1 >> 1.5
2 >> 1.3478260869565217
3 >> 1.325200398950907
4 >> 1.3247181739990537
5 >> 1.3247179572447898
6 >> 1.324717957244746    <- 16 decimal precision in 6 iterations!
...
100 >> 1.324717957244746

Padovan序列替代,27 25 17字节

¹Fᵢ{[ƨ2+ƨ3]ℲƤƨ/ƨ2

分解:

¹                  Append first element of Padovan sequence.
 Fᵢ{       Ⅎ       Define for loop of user's input amount of iterations.
    [ƨ2+ƨ3]        Append sum second and third to last elements.
            Ƥƨ/ƨ2  Print ratio of last two elements.

通过选择更好的打印策略来获得-2字节

通过选择更好的索引堆栈方式来获得-8个字节

怎么运行的:

随着帕多万序列的继续,最后两个元素的比率收敛到可塑性数。

INPUT ITERATION >> VALUE
0 >> 1
1 >> 2
...
10 >> 1.3157894736842106
...
89 >> 1.324717957244746    <- 16 decimal precision in 89 iterations
...
100> > 1.324717957244746

0

Clojure,46个字节

#(nth(iterate(fn[i](Math/pow(inc i)(/ 3)))1)%)

使用迭代的立方根公式。这有点有趣,但是更长:

(def f #(apply comp(repeat %(fn[i](Math/pow(inc i)(/ 3))))))

((f 10)1)
1.3247179361449652

“您可能认为您的语言中的浮点算术是任意准确的,而是必须使用其实际的准确性(这意味着仅在可以使用浮点数的精度的语言中,才可以输出浮点数。 ”)
Anders Kaseorg

哦,我没有注意到,真可惜。用BigDecimal实现立方根似乎很棘手。
NikoNyrh

0

Javascript,36个字节

f=(x,n=x)=>n**3/x/x<n+x?f(x,++n):n/x

与顶级python答案相同。否console.log包括在内,因为如果您f(x)在控制台中运行,它将被自动记录。

f=(x,n=x)=>n**3/x/x<n+x?f(x,++n):n/x
console.log(f(300))


0

> <>,38 + 3 = 41字节

11\n;
?!\}2,:01{::::}**-+0(?$-{+{1-:}

期望输入在程序启动时出现在堆栈上,因此该-v标志为+3个字节。

在线尝试!

有效地执行二进制搜索以缩小输出值。增加会x增加要执行的迭代次数。

编辑:略微重构计算以节省1个字节,以前的版本:

11\n;
?!\}2,:0{::::}**$-1-0)?$-{+{1-:}


0

TI-BASIC,21字节

:Prompt X //Prompt for input, 3 bytes
:While X  //While X, 3 bytes
:³√(1+Y→Y //Calculate cube root of 1+Y and store to Y, 7 bytes
:DS<(X,0  //Decrement X and skip next command (which doesn't do anything), 5 bytes
:End      //End While loop, 2 bytes
:Y        //Display Y, 1 byte

使用此递归公式

有趣的是,对数字进行硬编码并四舍五入得到相同的字节数:

TI-BASIC,21字节

:Prompt X    //Prompt for input, 3 bytes
:.5√(3       //Store √(3)/2 to Ans, 5 bytes
:Ansֿ¹cosh(3ֿ¹coshֿ¹(3Ans //Store the plastic number to Ans, 9 bytes
:round(Ans,X //Round the plastic number X decimal digits, 4 bytes

使用此三角公式


我认为您不能在此处使用TI-BASIC的浮动对象:Your answer must work in a hypothetical variant of your language in which integers can be arbitrarily large, and memory (including stack) is unlimited. You may not assume that floating-point arithmetic in your language is arbitrarily accurate, but must instead use its actual accuracy (meaning that outputting a floating-point number is only going to be possible in languages where the accuracy of floating-point numbers can be controlled at runtime).
lirtosiast

0

C#,317字节

using m=System.Math;a=x=>{if(a==0)return "1/1";var d=a(x-1).Split('/');var b=int.Parse(d[0]);var c=int.Parse(d[1]);return string.Format("{0}/{1}",(2*m.Pow(b,3)+m.Pow(c,3)).ToString(new string('#',int.MaxValue.ToString().Length)),(3*m.Pow(b,2)*c-m.Pow(c,3)).ToString(new string('#',int.MaxValue.ToString().Length)));};

它以分数形式返回结果。

说明

它使用带有x次迭代的牛顿法来找到多项式p ^ 3-p-1 = 0的根。公式为x_n = 1-(f(x_(n-1)))/(f'(x_(n-1)))),x_0是起点。

多项式的导数为3p ^ 2-1,假设x_(n-1)= b / c。然后,通过使用以上公式,我们得到x_n =(2 b ^ 3 + c ^ 3)/(3 b ^ 2 cc ^ 3)。还要说,我们从1开始,因为x> 1,并且是整数,所以当x = 2时会发生这种情况。标识并注释了代码:

using System;
string PlasticNumber(int x)
{
    if (x == 2) 
        return "1/1";                 

//If x=2, we return our starting value, but we need to return it as a fraction

    var d = PlasticNumber(x - 1).Split('/');
    var b = System.Convert.ToInt32(d[0]);
    var c = int.Parse(d[1]);

//We parse the previous value of the fraction, and put it into two variables

    return string.Format("{0}/{1}", 
        (2 * Math.Pow(b, 3) + Math.Pow(c, 3))
        .ToString(new string('#', int.MaxValue.ToString().Length)),
        (3 * Math.Pow(b, 2) * c - Math.Pow(c, 3))
        .ToString(new string('#', int.MaxValue.ToString().Length)));

//We return the result as a fraction, but it's important not to return it in
  scientific notation, because that will cause issues in the parsing process 

}


0

公理,96字节

h(n:NNI):Float==(n>1.E5=>-1;n:=n+1;j:=digits(n::PI);r:=solve(x^3-x=1,10.^-n);digits(j);rhs(r.1))

结果

(31) -> [h(i) for i in 0..10]
   (31)
   [1.0, 1.3, 1.33, 1.325, 1.3247, 1.32472, 1.324718, 1.324718, 1.32471796,
    1.324717957, 1.3247179572]
                                                         Type: List Float

您怎么看h(2)应该是1.32而不是1.33,所以最后几位有误

然后会有110个字节中的一个

g(n:NNI):Float==(n>1.E5=>-1;n:=n+1;j:=digits(n::PI);x:=sqrt(23./108);r:=(.5+x)^(1/3)+(.5-x)^(1/3);digits(j);r)

在q ^ 2-p ^ 3> = 0时m = sqrt(q ^ 2- p ^ 3)和x =(q + m)^(1/3)+(qm)^(1/3)

在我们的情况下r ^ 3-r-1 = 0可以写成r ^ 3-3 *(1/3)r-2 *(1/2)= 0,所以p = 1/3 q = 1/2 m = 1 / 4-1 / 27 = 23/108 x =(0.5 + m)^(1/3)+(0.5-m)^(1/3)

这个以牛顿迭代为起点r = 1的模型

f(n:NNI):Float==(n>1.E5=>-1;n:=n+1;j:=digits(n::PI);e:=10^-n;r:=1.;repeat(v:=(r^3-r-1)/(3*r^2-1);abs(v)<e=>break;r:=r-v);digits(j);r)

它在函数中的变化,数字值用于在浮点数之后获得n + 1个数字的一​​个obj。最后,将digits()值分配回前一个值。


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.