Naprzemienne początki

13

W wyścigach, w których zawodnicy omijają co najmniej jeden zakręt zakrzywionego toru, pozycje startowe dla każdego z zawodników są rozłożone w taki sposób, że każdy zawodnik pokonuje tę samą odległość wokół toru (w przeciwnym razie zawodnik na najbardziej wewnętrznej linii miałby ogromną przewagę ).

Biorąc pod uwagę długości głównych i podrzędnych osi (lub pół-głównych i pół-mniejszych, jeśli wolisz) toru eliptycznego oraz liczbę torów na torze, wyprowadzaj odległości od punktu początkowego najbardziej wewnętrznego pasa, że ​​każdy tor powinien być rozłożony.

Dane techniczne

  • Każdy pas jest elipsą z pół-głównymi osiami o 5 jednostek dłuższymi niż następny najkrótszy pas. Dla uproszczenia załóżmy, że ścieżki mają szerokość 0.
  • Najbardziej wewnętrzny pas zawsze zaczyna się od 0, a każdy inny punkt początkowy jest dodatnią liczbą całkowitą większą lub równą poprzedniemu punktowi początkowemu.
  • Dane wejściowe i wyjściowe mogą być w dowolnym dogodnym i rozsądnym formacie.
  • Wejściami zawsze będą liczby całkowite.
  • Należy obliczyć obwód toru z dokładnością do 0,01 jednostki rzeczywistej wartości.
  • Wyjścia należy zaokrąglić w dół do najbliższej liczby całkowitej (zmiennoprzecinkowej).
  • Linia mety jest punktem startowym dla najbardziej wewnętrznego kierowcy. W wyścigu jest tylko jedno okrążenie.
  • Długości osi są mierzone przy użyciu najbardziej wewnętrznego pasa toru.
  • Podanie 0 dla przesunięcia najbardziej wewnętrznego pasa jest opcjonalne.

Przypadki testowe

Format: 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

Te przypadki testowe zostały wygenerowane za pomocą następującego skryptu Python 3, który wykorzystuje przybliżenie obwodu elipsy opracowanej przez Ramanujana:

#!/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:]])))

Zastosowane przybliżenie to:

przybliżenie obwodu elipsy

Na koniec znajduje się pomocny schemat do zrozumienia obliczeń przesunięć:

tor

Mego
źródło
Korzystam z przybliżenia Ramanujana, tak jak ty. Czy to właśnie powinniśmy zrobić, czy chcesz, abyśmy ocenili zbieżność nieskończonej serii?
Adám
1
@ Adám Możesz zrobić wszystko, aby uzyskać wymaganą precyzję. Przybliżenie Ramanujana jest dobre dla wielu wartości, ponieważ jego błąd jest rzędu h**5, co jest znacznie poniżej 0.01szeregu wartości.
Mego,
Co dobrego ma minimalna dokładność, gdy nie ma ograniczenia co do wielkości wejściowej?
feersum

Odpowiedzi:

2

05AB1E , 43 bajty

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

Wyjaśnienie

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

Wypróbuj online!

Emigna
źródło
2

Haskell, 103 98 bajtów

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
źródło
1

Python 3, 168 164 bajtów

Dzięki @ Adám i @Mego za -2 bajty każdy

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

Funkcja, fktóra pobiera dane wejściowe za pomocą argumentu i zwraca listę przesunięć linii, w tym 0dla najbardziej wewnętrznej linii.

Jak to działa

Wykorzystuje to przybliżenie Ramanujana. Po prostu definiujemy funkcje hi Cdo obliczania parametru i obwodu, a następnie odejmujemy długość najbardziej wewnętrznego pasa od długości bieżącego pasa i podłogi, dla wszystkich pasów.

Wypróbuj na Ideone

TheBikingViking
źródło
sqrt(4-3*h(a,b))jest krótszy (4-3*h(a,b))**.5i floormożna go zastąpić int. Wykonanie obu tych czynności oznacza, że ​​nie musisz importować math.
Mego
@Mego Thanks. Chyba że jestem głupi, czy te pierwsze dwa nie są tej samej długości? Jeśli jednak instrukcja importu zostanie usunięta, wówczas istnieje problem z definicją pi.
TheBikingViking
Poprzez włączenie do 3*in h, należy zapisać dwa bajty.
Adám
Tęskniłem za tym, że używasz piByć może będziesz w stanie zakodować go z wystarczającą precyzją. I tak, pierwsze dwa są tej samej długości - oczywiście miałem na myśli bez importu! : P
Mego
@ Adám Dzięki za zwrócenie na to uwagi.
TheBikingViking
1

Dyalog APL , 45 bajtów

Zachęty do n , a następnie za pomocą b . Wymaga ⎕IO←0ustawienia domyślnego w wielu systemach.

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

⍳⎕monit o n , a następnie podaj {0, 1, 2, ..., n −1)

pomnożyć przez pięć uzyskać {0, 5, 10, ..., 5 n -5}

⎕∘.+szybka na i B , a następnie dokonać tabelę Dodawać , +5 +10 ... +5 n -5 b , b + 5, b +10 ... b + 5 N −5
  
  

(... )⌿zastosuj funkcję w nawiasach do każdej pary pionowej, tj.
  f ( a , b ), f ( a +5, b +5), f ( a +10, b +10), ..., f ( a + 5 n -5, b + 5 n -5)
  gdzie f ( x , y ) jest *

razy pi

( x + y ) razy

1+ jeden plus

h ( x , y ) [funkcja h zostanie zdefiniowana później] podzielona przez

10+ dziesięć plus

.5*⍨ pierwiastek kwadratowy z

4- cztery minus

h← h ( x , y ), co oznacza

trzy razy

2*⍨ kwadrat z

( x - y ) podzielone przez

+ x + y

(⊢-⊃) na wyniku funkcji zastosowanej do każdej pary odejmij wartość pierwszego wyniku

1↓ usuń pierwszy (zero)

zaokrąglić w dół

Wypróbuj APL online!


* W języku proceduralnym:

-÷+znaleźć ułamek różnicy, a suma x i y

2*⍨ kwadrat ten ułamek

pomnóż ten kwadrat przez trzy

h←przypisz ten produkt do h

4- odejmij ten produkt od czterech

.5*⍨ oblicz pierwiastek kwadratowy z tej różnicy

10+ dodaj dziesięć do tego pierwiastka kwadratowego

podziel h przez tę sumę

1+ dodaj jeden do tej frakcji

pomnożyć suma przy czym suma x i y

pomnóż ten produkt przez pi

Adám
źródło