Começos escalonados

13

Nas corridas em que os corredores percorrem pelo menos uma curva de uma pista curva, as posições iniciais de cada corredor são escalonadas, de modo que cada corredor percorre a mesma distância ao redor da pista (caso contrário, o corredor na pista mais interna teria uma grande vantagem )

Dados os comprimentos dos eixos maior e menor (ou semi-maior e semi-menor, se você preferir) de uma pista elíptica e o número de faixas na pista, produza as distâncias do ponto inicial da pista mais interna em que cada pista deve ser escalonado.

Especificações

  • Cada pista é uma elipse com eixos semi-principais 5 unidades a mais que a próxima pista mais curta. Para simplificar, suponha que as faixas tenham largura 0.
  • A faixa mais interna sempre começa em 0 e todos os outros pontos de partida são um número inteiro positivo maior ou igual ao ponto de partida anterior.
  • A entrada e a saída podem estar em qualquer formato conveniente e razoável.
  • As entradas sempre serão inteiras.
  • Você deve calcular a circunferência da pista dentro de 0,01 unidades do valor real.
  • As saídas devem ser arredondadas para o número inteiro mais próximo (no chão).
  • A linha de chegada é o ponto de partida para o corredor mais interno. Há apenas uma volta na corrida.
  • Os comprimentos dos eixos são medidos usando a faixa mais interna da pista.
  • A saída de 0 para o deslocamento da pista mais interna é opcional.

Casos de teste

Formato: a, b, n -> <list of offsets, excluding innermost lane>

20, 10, 5 -> 30, 61, 92, 124
5, 5, 2 -> 31
15, 40, 7 -> 29, 60, 91, 121, 152, 183
35, 40, 4 -> 31, 62, 94

Esses casos de teste foram gerados com o seguinte script Python 3, que usa uma aproximação da circunferência de uma elipse criada por Ramanujan:

#!/usr/bin/env python3

import math

a = 35 # semi-major axis
b = 40 # semi-minor axis
n = 4  # number of lanes
w = 5  # spacing between lanes (constant)

h = lambda a,b:(a-b)**2/(a+b)**2
lane_lengths = [math.pi*(a+b+w*i*2)*(1+3*h(a+w*i,b+w*i)/(10+math.sqrt(4-3*h(a+w*i,b+w*i)))) for i in range(n)]

print("{}, {}, {} -> {}".format(a, b, n, ', '.join([str(int(x-lane_lengths[0])) for x in lane_lengths[1:]])))

A aproximação usada é:

aproximação da circunferência da elipse

Finalmente, aqui está um diagrama útil para entender os cálculos das compensações:

rastrear

Mego
fonte
Eu uso a aproximação de Ramanujan como você. É isso que devemos fazer, ou você quer que avaliemos a convergência da série infinita?
Adám 22/08/16
1
@ Adám Você pode fazer o que for preciso para obter a precisão necessária. A aproximação de Ramanujan é boa para muitos valores porque seu erro é da ordem de h**5, o que é muito baixo 0.01para uma ampla faixa de valores.
Mego 22/08
De que adianta uma precisão mínima quando não há limite no tamanho da entrada?
feersum

Respostas:

2

05AB1E , 43 bytes

UVFXY-nXY+WZn/3*©T4®-t+/>Z*žq*5DX+UY+V})¬-ï

Explicação

UV                                           # X = a, Y = b
  F                                   }      # n times do
   XY-n                                      # (a-b)^2
       XY+W                                  # Z = (a + b)
             /                               # divide (a-b)^2
           Zn                                # by (a+b)^2
              3*                             # multiply by 3
                ©                            # C = 3h
                       /                     # 3h divided by 
                 T                           # 10
                      +                      # +
                  4®-t                       # sqrt(4-3h)
                        >                    # increment
                         Z*žq*               # times (a + b)*pi
                              5DX+UY+V       # increase a and b by 5
                                       )     # wrap in list of circumferences
                                        ¬-   # divide by inner circumference
                                          ï  # floor
                                             # implicitly display

Experimente online!

Emigna
fonte
2

Haskell, 103 98 bytes

c!d|h<-3*d*d/c/c=pi*c*(1+h/(10+sqrt(4-h)))
f a b n|x<-a-b=[floor$(a+b+10*w)!x-(a+b)!x|w<-[1..n-1]]
Damien
fonte
1

Python 3, 168 164 bytes

Obrigado a @ Adám e @Mego por -2 bytes cada

from math import*
h=lambda a,b:3*(a-b)**2/(a+b)**2;C=lambda a,b:pi*(a+b)*(1+h(a,b)/(10+sqrt(4-h(a,b))))
f=lambda a,b,n:[int(C(a+i*5,b+i*5)-C(a,b))for i in range(n)]

Uma função fque recebe entrada por meio de argumento e retorna uma lista de deslocamentos de faixa, inclusive 0para a faixa mais interna.

Como funciona

Isso usa a aproximação de Ramanujan. Simplesmente definimos funções he, Cpara calcular o parâmetro e a circunferência, subtraímos o comprimento da faixa mais interna do comprimento da faixa e piso atuais, para todas as faixas.

Experimente no Ideone

TheBikingViking
fonte
sqrt(4-3*h(a,b))é mais curto que (4-3*h(a,b))**.5e floorpode ser substituído por int. Ao fazer os dois, você não precisa importar math.
Mego 22/08
Obrigado @Mego. A menos que eu esteja sendo estúpido, esses dois primeiros não têm o mesmo comprimento? No entanto, se a instrução de importação for removida, haverá o problema de definir pi.
TheBikingViking
Incluindo o do 3*em h, você deve guardar dois bytes.
Adám 22/08/16
Senti muita falta do seu uso. piVocê poderá codificá-lo com precisão suficiente. E sim, os dois primeiros têm o mesmo comprimento - eu quis dizer sem a importação, é claro! : P
Mego 22/08
@ Adám Obrigado por apontar isso.
TheBikingViking
1

Dyalog APL , 45 bytes

Instruções para n , em seguida, para um b . Requer ⎕IO←0qual é o padrão em muitos sistemas.

1↓(⊢-⊃)(○+×1+h÷10+.5*⍨4-h3×2*⍨-÷+)⌿⎕∘.+5×⍳⎕

⍳⎕solicite n e , em seguida, forneça {0, 1, 2, ..., n −1)

multiplicar por cinco a obter {0, 5, 10, ..., 5 n -5}

⎕∘.+pronto para um e b , em seguida, fazer uma tabela disso:
  um , um 5, um 10, ... uma 5 n -5
  b , b 5, b 10, ... b 5 n -5

(... )⌿aplica a função entre parênteses a cada par vertical, ou seja,
  f ( a , b ), f ( a +5, b +5), f ( a +10, b +10), ..., f ( a + 5 n -5, b 5 n -5)
  , onde f ( x , y ) é *

vezes pi

( x + y ) vezes

1+ um mais

h ( x , y ) [a função h será definida posteriormente] dividida por

10+ dez mais

.5*⍨ a raiz quadrada de

4- quatro menos

h← h ( x , y ), que é

três vezes

2*⍨ a praça de

( x - y ) dividido por

+ x + y

(⊢-⊃) no resultado da função aplicada a cada par, subtraia o valor do primeiro resultado

1↓ remova o primeiro (zero)

arredondar para baixo

TryAPL online!


* Na linguagem processual:

-÷+Encontre a fração da diferença entre e a soma de x e y

2*⍨ esquadrar essa fração

multiplique esse quadrado por três

h←atribuir esse produto a h

4- subtrair esse produto de quatro

.5*⍨ pegue a raiz quadrada dessa diferença

10+ adicione dez a essa raiz quadrada

dividir h por essa soma

1+ adicione um a essa fração

multiplicar que soma com a soma de x e y

multiplique esse produto por pi

Adão
fonte