Furo 1 da série AGM: Calcular a média aritmética-geométrica


26

Esta pergunta foi inspirada por este HNQ .

Sobre a série

Esta pergunta agora faz parte de uma série sobre o método AGM. Este primeiro post da série será sobre como realmente calcular o AGM. Você pode tratar isso como qualquer outro desafio de código de golfe e respondê-lo sem se preocupar com a série. No entanto, existe uma tabela de classificação em todos os desafios.

Qual é a média aritmética-geométrica

A média aritmética-geométrica de dois números é definida como o número para o qual converte repetidamente as médias aritmética e geométrica. Sua tarefa é encontrar esse número após algumas niterações.

Esclarecimentos

  • Você pega três números, a, b, nem qualquer formato razoável.
  • Por niterações, tirar a média aritmética e geométrico de ae be definida para aqueles ae b.
  • Para dois números ae b, a média aritmética é definida como (a + b) / 2.
  • A média geométrica é definida como √(a * b).
  • ae bdevem estar se aproximando.
  • Em seguida, imprima ambos ae b.
  • Você não precisa se preocupar com a imprecisão da bóia e tal.
  • Este é o pelo que o código mais curto em bytes vence!

Casos de teste

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

Entre os melhores

Roubado da série de Martin.

O trecho a seguir gerará uma tabela de classificação em todos os desafios da série.

Para garantir que suas respostas sejam exibidas, inicie todas as respostas com um título, usando o seguinte modelo de remarcação:

# Language Name, N bytes

onde N é o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:

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


1
Os números iniciais são inteiros positivos?
Xnor

2
" ambos aoub " - bem, qual? Ambos, ou qualquer um?
Maçaneta

@Doorknob -_- São ambos.
Maltysen

1
@xnor no. Veja o último caso de teste.
Maltysen

5
Fazer parte de uma série causa uma espécie de situação infeliz. Isso é tão simples que todas as soluções serão parecidas. E publicar soluções semelhantes em idiomas que já foram usados ​​geralmente é desaprovado. Escrevi minha solução em cerca de 2 minutos, mas está em um idioma que já foi usado e tem a mesma duração. Se eu seguir a etiqueta típica de postagem, não poderei participar da série.
Reto Koradi

Respostas:



9

Dyalog APL , 22 21 15 bytes

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

Aceita ( a , b ) como argumento correto e solicita n :

(

  +.× produto ponto de 0,5 e o argumento certo

, Seguido por

  ×.*⍨"ponto de poder" do argumento correto e 0,5 *

)⍣⎕ tempos de solicitação numérica aplicados.

* "ponto de poder" é como produto de ponto, mas usando multiplicação e poder em vez de mais e multiplicação, da seguinte maneira:

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

-3 bytes graças a ngn.


Versão antiga:

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

Toma ncomo argumento à esquerda e a bcomo argumento à direita.

⊢⍵No RightArg
(... )⍣⍺recalcule a
(+/÷≢)soma dos tempos do LeftArg dividida pelo registro
,seguido pela
.5*⍨×/raiz quadrada do produto.

Todos os casos de teste:

      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⍣⍺⊢⍵ou um idioma similar que você usa profissionalmente?
lirtosiast

@ThomasKwa Sim, consulte, por exemplo, Of⍣core⊢TREEem miserver.dyalog.com (clique no grande "D" e vá para a linha [266]).
Adám

7

TI-BASIC, 22 bytes

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

Faz exatamente o que o algoritmo diz. Retorna N do prompt e A e B passam Anspor uma lista de dois elementos.

Se N for 0, o For(loop será ignorado completamente.



6

MATLAB / oitava, 69 65 bytes

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

1
Você pode fazer b=(a*b).^5diretamente, pois não está reutilizando bnovamente nessa iteração e salvar 4 bytes.
Brain Guider

6

Gelatina, não concorrente

9 bytes Esta resposta não é concorrente, pois usa recursos que pós-datam o desafio.

SH;P½¥ðṛ¡

Experimente online!

Como funciona

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

Sério, 11 bytes

,p`;π√@æk`n

Hex Dump:

2c70603be3fb40916b606e

Experimente online

Explicação:

,                    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 bytes

Obrigado a @RetoKoradi e @AlexA por me salvarem 6 bytes.

Isso não é competitivo, porque o C ++ não é uma boa linguagem de golfe. Fiz isso por diversão :)

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

Esta é uma função de recursão simples, muito semelhante à resposta JS.


3
Você pode se livrar dos espaços após as vírgulas. Além disso, usar em floatvez de doubleé mais curto.
Reto Koradi

1
Você também pode remover o espaço na #includelinha.
Alex A.

Uau, eu sou estúpido por não perceber isso. Obrigado!
TheCoffeeCup

Eu consideraria f(float*s)que leva um ponteiro para 3 carros alegóricos para estar em um "formato razoável". Não tenho certeza se isso realmente diminui.
nwp

4

K5, 15 bytes

Muito literal:

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

Em ação:

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

Infelizmente, isso não funciona bem porque esse intérprete atualmente não suporta projeção (currying) de advérbios. Funciona no verdadeiro k5.

No oK, atualmente seria necessário agrupar a definição em um lambda:

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

4

J, 18 13 bytes

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

Uso:

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

Uau, isso funciona. As conjunções são estranhas. Eu esperaria que essa expressão fosse um advérbio (o que pode ser), mas se apresentada com argumentos também é uma função.
Random #

3

Japt , 24 bytes 25 33

Guardado 9 7 bytes graças a @ETHproductions

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

Aproveita a desestruturação do ES6.

Experimente online

Ungolfed && Explicação

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]

Uogera um intervalo de números de 0 a U, portanto, Uo m@[V,W]=[V+W /2,(V*W q]deve funcionar. (Não testado)
ETHproductions

Ah, e você não deveria precisar de vírgulas. :)
ETHproductions

@ETHproductions obrigado mais uma vez! :)
Downgoat

Oh, meu Deus, isso falha para qualquer Uoutro que não seja 1, produzindo cada loop à medida que avança. Aqui está uma que funciona corretamente:Uo £[VW]=[V+W /2(V*W q]};[VW]
ETHproductions

@ETHproductions graças, mas usando rparecia trabalho também
Downgoat

3

Matlab, 54 bytes

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

Exemplo:

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

3

Pyth, 12

u,.OG@*FG2EQ

Suíte de teste

Explicação

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

Esqueci @e .O, mas eu nem conhecia o novo objetivo E.
orlp

@ orlp ah, não vi o seu post, meu mal, eu teria sugerido isso nos comentários. E sim, acompanhar tudo o que está mudando é um pouco
difícil

2

Minkolang v0.14, 23 bytes

Experimente aqui !

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

Agradecemos a mathmandan por apontar uma versão mais curta usando o lambdaoperador.

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

Minha versão original:

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

Para meu desgosto, uma função recursiva (à la as respostas JavaScript e C ++) era mais curta do que um simples loop for.


2
Você pode encurtar um pouco isso lambdae com o if/elseoperador ternário :f=lambda a,b,n:f((a+b)/2,(a*b)**.5,n-1)if n else(a,b)
mathmandan

Sem problemas! (Além disso, eu acho que isso é de 53 bytes.)
mathmandan

O arquivo .py que eu salvei está listado como sendo 55 bytes. Existe uma maneira melhor de calcular o tamanho do programa?
21815 Jack Brounstein

Às vezes, as pessoas neste site copiam e colam seu código em mothereff.in/byte-counter . Se você está se perguntando sobre a discrepância, acho que o Windows está inserindo um caractere de nova linha desnecessário no final do seu arquivo .py (e o Windows conta uma nova linha como 2 bytes em vez de 1). De qualquer forma, você não precisa contar a última nova linha como parte do seu código para fins de pontuação. Se você postar uma entrada de várias linhas, conte 1 para cada caractere de nova linha, não 2 e não inclua nenhuma nova linha no final da sua última linha de código. (Tanto quanto eu entendo as regras de qualquer maneira!)
mathmandan

2

R, 66 bytes

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

Uso:

> 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

Você pode remover o nome da função para salvar 2 bytes.
Alex A.

2

Mathematica, 31 30 bytes

Guardou um byte graças a Martin Büttner.

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

Uso:

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

Out[1]= {13.4582, 13.4582}

1

Lua, 62 bytes

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

Usa argumentos de linha de comando ...para atribuir a n, ae b, um truque bacana que aprendi sobre Lua recentemente.


1

Haskell, 40 bytes

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

Uma função anônima. Exemplo de uso:

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

A função lambda (\(a,b)->((a+b)/2,sqrt$a*b))assume a média aritmética e geométrica em uma tupla. Isso é iterado a partir da primeira entrada (uma tupla) e (!!)indexa a segunda entrada para especificar o número de iterações.


1

Perl, 60 bytes

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

NB: Por este meta post , acredito que tenho a pontuação correta. O código real (entre aspas simples) tem 58 caracteres e adicionei +2 para ae psinalizadores, pois essa é a diferença da menor chamada,perl -e'...'

Reclamações vagas

Tenho essa sensação incômoda de que estou perdendo uma melhoria óbvia. Eu sei, "bem-vindo ao código do golfe", mas quero dizer mais do que o habitual , acredito que haja uma oportunidade fácil de encurtar isso.

No começo, eu tinha mexido com o uso $\do segundo termo com algum sucesso, mas a abordagem acima acabou sendo 2 bytes mais curta, mesmo com os apsinalizadores extras necessários. Da mesma forma, evitar a $_atribuição explícita seria bom, mas o loop torna isso difícil.

Os shift@Finsetos também; se eu não fizer dessa maneira (ou usar @F=(0,...,...), o que não salva bytes), há um erro de um por um na @Fatribuição.

Exemplo

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

Saídas

13.4581714817256 13.4581714817256

1

Julia, 49 bytes

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

Algoritmo iterativo bastante direto. O uso do símbolo e o retorno múltiplo economiza alguns bytes, mas a sintaxe do loop for custa alguns.


1

Haskell, 47 bytes

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

você pode salvar alguns bytes tomando ab como um par em f: fx 0 = x; f (a, b) n = f ((a + b) / 2, sqrt $ a * b) $ n-1
Damien

E defina o infixo da função.
Xnor

1

Julia, 42 bytes

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

Esta é uma função recursiva fque aceita três números e retorna uma tupla.

Ungolfed:

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

LabVIEW, 21 primitivas do LabVIEW

Primitivas contadas de acordo com esta meta post .

bastante direto, não há muito o que explicar.



1

CJam, 16 bytes

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

Esta é uma função anônima. A entrada é uma lista com os dois valores (como dobras), seguidos pela contagem da iteração. Experimente online com código de E / S para teste.

Normalmente, eu não teria postado isso porque @PeterTaylor postou uma resposta CJam igualmente longa antes de fazer a pergunta. Mas como isso é anunciado como o início de uma série, eu queria manter minhas opções em aberto, caso a série seja interessante.

Enquanto o comprimento é o mesmo que a resposta de Peter, o código não é. Eu escolhi um formato de entrada diferente, colocando os dois valores em uma lista, onde Peter usou valores separados. Portanto, embora não haja muito com os dois formatos de entrada, o código parece bem diferente.

{     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 bytes

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

uso:

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

Se eu alterar a entrada de a,b,npara (a,b),n, posso salvar alguns bytes.

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

uso:

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
}

Realmente eu trocaria o ... *com ... -> (\a,\b) { a =~= b }, então não haveria necessidade do $^nparâmetro.
(não use em ==vez de =~=ou pode não parar)

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 bytes

Código:

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

Exemplo:

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

Experimente online aqui


0

Java, 103 96 84 bytes

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

Verifique todos os casos de teste.

Versão antiga (96 bytes):

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

Versão antiga (103 bytes):

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;}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.