AGM系列孔1:计算算术-几何平均值


26

这个问题的灵感来自于总部

关于系列

这个问题现在是有关AGM方法的系列文章的一部分。本系列的第一篇文章将关于实际计算AGM。您可以像对待其他任何代码高尔夫挑战赛一样对待它,并回答它而不必担心系列赛。但是,在所有挑战中都有排行榜。

什么是算术几何均值

两个数的算术几何均值定义为反复采用算术和几何均值收敛的数。您的任务是在一些n迭代后找到该数字。

澄清说明

  • 您可以a, b, n采用任何合理格式的三个数字。
  • 对于n迭代,取算术和几何平均值a,并b与设置那些ab
  • 对于两个数字ab,算术平均值被定义为(a + b) / 2
  • 几何平均值定义为√(a * b)
  • a并且b应该互相接近。
  • 然后,输出ab
  • 您不必担心浮动不精确等问题。
  • 这是因此以字节为单位的最短代码胜出!

测试用例

[0, [24, 6]] -> [24, 6]    
[1, [24, 6]] -> [15.0, 12.0]
[2, [24, 6]] -> [13.5, 13.416407864998739]
[5, [24, 6]] -> [13.458171481725616, 13.458171481725616]
[10, [100, 50]] -> [72.83955155234534, 72.83955155234534]

The next one is 1/Gauss's Constant:
[10, [1, 1.41421356237]] -> [1.198140234734168, 1.1981402347341683]

排行榜

被马丁的系列偷走了。

以下代码片段将在该系列的所有挑战中产生一个排行榜。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头每个答案:

# Language Name, N bytes

其中N是您提交的文件的大小。如果您提高了分数,则可以通过打败旧分数来保持标题。例如:

# Ruby, <s>104</s> <s>101</s> 96 bytes


1
初始数字是正整数吗?
xnor 2015年

2
两者” a还是b “-”,哪个?两者还是其中之一?
门把手

@Doorknob -_-两者都有。
Maltysen,2015年

1
@xnor不。查看最后一个测试用例。
Maltysen,2015年

5
将这部分内容作为系列的一部分会导致一种不幸的情况。这很简单,解决方案看起来都非常相似。并且,人们普遍不赞成以已经使用的语言发布类似的解决方案。我写了大约2分钟的解决方案,但是它使用的是已经使用的语言,并且长度相同。如果我遵循典型的张贴礼节,将无法参加该系列活动。
Reto Koradi 2015年

Answers:



9

Dyalog APL22 21 15字节

.5∘(+.×,×.*⍨)⍣⎕

将(ab)作为正确的参数,并提示输入n

(

  +.× 0.5和正确参数的点积

, 其次是

  ×.*⍨“点动力”右边的参数和0.5 *

)⍣⎕ 应用的数字提示时间。

* “点幂”类似于点积,但使用乘法和幂而不是加法和乘法,如下所示:

      n
A ×.*⍨ B B i A = B 1 A B 2 A
      i = 1

-3个字节感谢ngn。


旧版:

{((+/÷≢),.5*⍨×/)⍣⍺⊢⍵}

注意到n左参数,a b作为右边的参数。

⊢⍵在RIGHTARG
(...... )⍣⍺重新计算LEFTARG次
(+/÷≢)总和除以相符
,,随后
.5*⍨×/该产品的平方根。

所有测试用例:

      f←{((.5×+/),.5*⍨×/)⍣⍺⊢⍵}
      0 1 2 5 10 10 f¨ (24 6)(24 6)(24 6)(24 6)(100 50)(1,2*.5)
┌────┬─────┬────────────────┬───────────────────────┬───────────────────────┬───────────────────────┐
│24 6│15 12│13.5 13.41640786│13.45817148 13.45817148│72.83955155 72.83955155│1.198140235 1.198140235│
└────┴─────┴────────────────┴───────────────────────┴───────────────────────┴───────────────────────┘

您是f⍣⍺⊢⍵专业使用过的惯用语吗?
lirtosiast 2015年

@ThomasKwa是的,见例如Of⍣core⊢TREEmiserver.dyalog.com(点击大“d”和滚动到行[266])。
2015年

7

TI-BASIC,22字节

Input N
For(I,1,N
{mean(Ans),√(prod(Ans
End
Ans

完全按照算法说的去做。从提示中获取N,并从A和B Ans作为两个元素的列表。

如果N为0,For(则完全跳过循环。



6

MATLAB / Octave,69 65字节

function [a,b]=r(a,b,n)
for i=1:n;j=(a+b)/2;b=(a*b)^.5;a=j;end

1
您可以b=(a*b).^5直接执行此操作,因为您无需b在该迭代中再次重用并节省4个字节。
Brain Guider 2015年

6

果冻,无竞争

9个字节 该答案是非竞争性的,因为它使用了挑战后的功能。

SH;P½¥ðṛ¡

在线尝试!

怎么运行的

SH;P½¥ðṛ¡    Input: x (vector) -- y (repetitions)

SH           Take the sum (S) of x and halve (H) the result.
   P½        Take the product (P) of x and the square root (½) of the result.
     ¥       Combine the last two instructions in a dyadic chain.
  ;          Concatenate the results to the left and to the right.
      ð      Push the preceding, variadic chain; begin a new, dyadic chain.
       ṛ     Return the right argument (y).
        ¡    Repeat the pushed chain y times.

5

严重的是11个字节

,p`;π√@æk`n

十六进制转储:

2c70603be3fb40916b606e

在线尝试

说明:

,                    Read in the list as [n,a,b]
 p                   pop list to yield: n [a,b]
  `      `n          Push a quoted function and run it n times.
   ;                 Duplicate [a,b] pair
    π√               Compute its product and square root it (GM)
      @              Swap the other copy of the pair to the top
       æ             Compute its mean.
        k            Compile the stack back into a list.

5

C ++,108个 102 100字节

感谢@RetoKoradi和@AlexA为我节省了6个字节。

这是非竞争性的,因为C ++不是一种好的高尔夫语言。这样做是为了好玩:)

#include<cmath>
std::string f(float a,float b,int n){return n==0?a+" "+b:f((a+b)/2,sqrt(a*b),n-1);}

这是一个简单的递归函数,与JS答案非常相似。


3
您可以删除逗号后的空格。另外,使用float代替double更短。
Reto Koradi

1
您也可以删除行中的空格#include
Alex A.

哇,我很愚蠢,没注意到这一点。谢谢!
TheCoffeeCup

我会考虑f(float*s)哪一个指向3个浮点数的指针处于“合理格式”。不知道这是否真的使它更短。
nwp 2015年

4

K5,15个字节

非常文字:

{(+/x%2;%*/x)}/

实际上:

 {(+/x%2;%*/x)}/[0; 24 6]
24 6
 {(+/x%2;%*/x)}/[5; 24 6]
1.345817e1 1.345817e1

不幸的是,这无法正常运行,因为该解释器当前不支持副词的投射(咖喱)。在真正的k5中工作。

在OK中,当前需要将定义包装在lambda中:

  {x{(+/x%2;%*/x)}/y}[5; 24 6]
13.4582 13.4582

4

J,18 13字节

-:@+/,%:@*/^:

用法:

   agm =: -:@+/,%:@*/^:
   5 agm 24 6
13.4582 13.4582

哇,这可行。连词很奇怪。我希望这个表达式是副词(可以是副词),但是如果带有参数,它也是一个函数。
randomra 2015年

3

Japt,24字节25 33

保存了9个7字节,感谢@ETHproductions

Uo r@[VW]=[V+W /2(V*W q]

利用了ES6的重组。

在线尝试

取消&&说明

Uo r@[VW]=[V+W /2(V*W q]

       // Implicit: U: 1st input, V: 2nd input, W: 3rd input
Uo     // Range from 0 to 1st input
r@     // Loop over range
  [V,W]=    // Set 2nd and 3rd input to...
   [V+W /2,   // Add 2nd and 3rd inputs, divide by 2
   (V*W q]    // Multiple 2nd and 3rd inputs, find square root
            // Set's to the above respectively 
       // Implicit: return [V,W]

Uo生成从0到U的数字范围,因此Uo m@[V,W]=[V+W /2,(V*W q]应该可以工作。(未经测试)
ETHproductions'December

哦,您根本不需要逗号。:)
ETHproductions 2015年

@ETHproductions再次感谢!:)
Downgoat

哦,亲爱的,这对于U除1之外的任何其他对象都会失败,并输出每个循环。这是一个正常工作的:Uo £[VW]=[V+W /2(V*W q]};[VW]
ETHproductions 2015年

@ETHproductions谢谢,但使用r似乎也可以
Downgoat 2015年

3

Matlab,54个字节

function x=f(x,n)
for k=1:n
x=[mean(x) prod(x)^.5];end

例:

>> f([24 6], 2)
ans =
  13.500000000000000  13.416407864998739

3

珀斯,12岁

u,.OG@*FG2EQ

测试套件

说明

u,.OG@*FG2EQ    ##  implicit: Q = eval(input())
u         EQ    ##  reduce eval(input()) times, starting with Q
                ##  the reduce lambda has G as the previous value and H as the next
  .OG           ##  arithmetic mean of last pair
     @*FG2      ##  geometric mean of last pair, uses *F to get the product of the list
                ##  and @...2 to get the square root of that
 ,              ##  join the two means into a two element list

忘了@.O,但我甚至不知道的新的用途E
orlp

@orlp啊,没看到您的帖子,我不好,我只是在评论中建议了这些。是的,要跟踪所有不断变化的内容有点
麻烦

2

Minkolang v0.14,23个字节

在这里尝试!

$n[$d+2$:r*1Mi2%?!r]$N.
$n                      C get all input C
  [                ]    C pop N; repeat inner N times C
   $d                   C duplicate stack [1,2] => [1,2,1,2] C
     +                  C add top two elements C
      2$:               C divide by two C
         r              C reverse stack (get the other two) C
          *             C multiply them together C
           1M           C take square root C
             i2%?!r     C reverse the stack if an odd step number C
                    $N  C output stack
           1M           C take square root C
             i          C get step in for loop C


2

Python 3,65 55字节

感谢mathmandan使用lambda运算符指出较短的版本。

f=lambda a,b,n:f((a+b)/2,(a*b)**.5,n-1)if n else(a,b)

我的原始版本:

def f(a,b,n):
 if n:f((a+b)/2,(a*b)**.5,n-1)
 else:print(a,b)

使我烦恼的是,递归函数(JavaScript和C ++的答案)比简单的for循环短。


2
您可以使用lambda和三进制if/else运算符将其缩短一点:f=lambda a,b,n:f((a+b)/2,(a*b)**.5,n-1)if n else(a,b)
mathmandan

没问题!(另外,我认为这是53个字节。)
mathmandan

我保存的.py文件被列出为55个字节。有没有更好的方法来计算程序大小?
杰克·布劳恩斯坦

有时,该网站上的用户将其代码复制并粘贴到mothereff.in/byte-counter中。如果您想知道这个差异,我想Windows会在.py文件的末尾插入不必要的换行符(Windows会将换行计为2个字节而不是1个字节)。无论哪种方式,您都不必为了计分目的而将最后一个换行符算作代码的一部分。如果要发布多行条目,则每个换行符应为1,而不是2,并且在最后一行代码的末尾不应包含任何换行符。(据我了解,规则仍然如此!)
mathmandan

2

R,66个字节

f=function(a,b,n){while(n){x=(a+b)/2;b=(a*b)^.5;n=n-1;a=x};c(a,b)}

用法:

> f(24,6,0)
[1] 24  6
> f(24,6,1)
[1] 15 12
> f(24,6,2)
[1] 13.50000 13.41641
> f(24,6,3)
[1] 13.45820 13.45814
> f(24,6,4)
[1] 13.45817 13.45817
> f(100,50,10)
[1] 72.83955 72.83955
> f(1,1.41421356237,10)
[1] 1.19814 1.19814

您可以删除函数名称以节省2个字节。
Alex A.

2

Mathematica,31个 30字节

感谢MartinBüttner,节省了一个字节。

{+##/2,(1##)^.5}&@@#&~Nest~##&

用法:

In[1]:= {+##/2,(1##)^.5}&@@#&~Nest~##&[{24, 6}, 5]

Out[1]= {13.4582, 13.4582}

1

Lua,62个字节

n,a,b=...for i=1,n do a,b=(a+b)/2,math.sqrt(a*b)end print(a,b)

用途命令从行参数...分配给na并且b,一个漂亮的把戏我最近了解到的Lua。


1

Haskell,40个字节

(!!).iterate(\(a,b)->((a+b)/2,sqrt$a*b))

匿名函数。用法示例:

>> let f=(!!).iterate(\(a,b)->((a+b)/2,sqrt$a*b)) in f (1.0,1.41421356237) 10
(1.198140234734168,1.1981402347341683)

lambda函数(\(a,b)->((a+b)/2,sqrt$a*b))采用元组的算术和几何均值。从第一个输入(元组)开始进行迭代,然后(!!)为第二个输入建立索引以指定迭代次数。


1

Perl,60个字节

perl -ape'F=($F[0]/2+$F[1]/2,sqrt$F[0]*$F[1])for 1..shift@F;$_="@F"'

NB:根据这篇文章,我相信我的得分是正确的。实际的代码(单引号之间)是58个字符,然后我为ap标志添加了+2,因为这与最短的调用有所不同,perl -e'...'

含糊的投诉

我有种na的感觉,我没有明显的进步。我知道,“欢迎打高尔夫”,但我的意思是,比平时更多,我相信有一个简单的机会可以缩短这一时间。

早些时候,我曾迷惑使用$\第二个术语取得了一些成功,但是上述方法最终缩短了2个字节,即使ap需要额外的标志。类似地,避免显式$_分配会很好,但是循环会增加难度。

shift@F错误我也; 但是,如果我不那样做(或者@F=(0,...,...)改用,它不保存任何字节),那么@F分配就会出现错误。

echo 5 24 6 | perl -ape'F=($F[0]/2+$F[1]/2,sqrt$F[0]*$F[1])for 1..shift@F;$_="@F"'

产出

13.4581714817256 13.4581714817256

1

朱莉娅49字节

(a,b,n)->(for i=1:n;a,b=(a+b)/2,√(a*b)end;(a,b))

非常直接的迭代算法。使用符号和多次返回可以节省一些字节,但是for循环语法需要花费一些时间。


1

Haskell,47字节

f a b 0=(a,b)
f a b n=f((a+b)/2)(sqrt$a*b)(n-1)

您可以将f中的ab作为一对保存一些字节:fx 0 = x; f(a,b)n = f((a + b)/ 2,sqrt $ a * b)$ n-1
Damien

并定义函数中缀。
xnor 2015年

1

朱莉娅,42个字节

f(a,b,n)=n>0?f((a+b)/2,(a*b)^.5,n-1):(a,b)

这是一个递归函数f,它接受三个数字并返回一个元组。

取消高尔夫:

function f(a::Real, b::Real, n::Integer)
    if n > 0
        # Recurse on the arithmetic and geometric means, decrementing n
        return f((a + b) / 2, sqrt(a * b), n - 1)
    else
        # Return the pair
        return (a, b)
    end
end



1

CJam,16个字节

{{_:+2/\:*mq]}*}

这是一个匿名函数。输入是带有两个值(双精度)的列表,其后是迭代计数。在线尝试使用I / O代码进行测试。

我通常不会发布此消息,因为@PeterTaylor在看到问题之前发布了同样长的CJam答案。但是,由于这是系列的开始,所以我想保持选择开放,以防系列有趣。

虽然长度与彼得的答案相同,但代码却不同。我通过在列表中使用两个值来选择了一种不同的输入格式,其中Peter使用了单独的值。因此,尽管两种输入格式的内容都不多,但代码看起来却大不相同。

{     Start loop over number of iterations.
  _     Copy the current pair of values.
  :+    Reduce pair with + operator.
  2/    Divide by 2.
  \     Swap second copy of pair to top.
  :*    Reduce pair with * operator.
  mq    Calculate square root.
  ]     Wrap the two new values in a list for next iteration.
}*    End iteration loop.

0

Perl 6的 53个  47字节

{(($^a,$^b),->(\a,\b){((a+b)/2,sqrt(a*b))}...*)[$^n]} # 53 bytes

用法:

# give it a name
my &code = {(($^a,$^b),->(\a,\b){((a+b)/2,sqrt(a*b))}...*)[$^n]}

say code 100,50,10;          # (72.8395515523453 72.8395515523453)
say code 1,1.41421356237,10; # (1.19814023473417 1.19814023473417)

如果将输入从更改为a,b,n(a,b),n我可以节省一些字节。

{($^l,->(\a,\b){((a+b)/2,sqrt(a*b))}...*)[$^n]} # 47 bytes

用法:

my &code = {($^l,->(\a,\b){((a+b)/2,sqrt(a*b))}...*)[$^n]}

say code (100,50),10;          # (72.8395515523453 72.8395515523453)
say code (1,1.41421356237),10; # (1.19814023473417 1.19814023473417)

say code (24,6),$_ for 0,1,2,5;
# (24 6)
# (15 12)
# (13.5 13.4164078649987)
# (13.4581714817256 13.4581714817256)
{
  (
    $^l,          # first 2 element tuple
    ->            # pointy block (lambda)
      (\a,\b)     # take a single tuple, and give its 2 elements each a name
    {
      (           # create a 2 element tuple
        (a+b)/2,  # arithmetic mean
        sqrt(a*b) # geometric mean
      )
    } ... *       # create a lazy infinite sequence of tuples
  )[ $^n ]        # take the nth "tuple" from the outer sequence
}

我真的会掉出... *... -> (\a,\b) { a =~= b }的话,那就没有必要的$^n参数。
(请勿使用==代替=~=,否则它可能不会停止)

my &code = {($^l,->(\a,\b){((a+b)/2,sqrt(a*b))}...->(\a,\b){a=~=b})[*-1]}

say code (24,6);           # (13.4581714817256 13.4581714817256)
say code (100,50);         # (72.8395515523453 72.8395515523453)
say code (1,1.41421356237) # (1.19814023473417 1.19814023473417)

0

Prolog,80个字节

码:

p(A,B,0):-write([A,B]).
p(A,B,N):-X is(A+B)/2,Y is sqrt(A*B),M is N-1,p(X,Y,M).

例:

p(100,50,10).
[72.83955155234534, 72.83955155234534]

在这里在线尝试


0

Java,103 96 84字节

String f(int n,double a,double b){return n>0?f(n-1,(a+b)/2,Math.sqrt(a*b)):a+","+b;}

验证所有测试用例。

旧版本(96字节):

String f(int n,double a,double b){for(;n>0;a=(a+b)/2,b=Math.sqrt((b-2*a)*b))n--;return a+","+b;}

旧版本(103字节):

String f(int n,double a,double b){double t;for(;n>0;t=(a+b)/2,b=Math.sqrt(a*b),a=t)n--;return a+","+b;}
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.