Distância entre dois pontos viajando em um gráfico de gráfico polar

23

Breve Problema Explicação

Escreva um programa para encontrar a distância mínima entre dois pontos que viajam apenas em raios que emanam da origem e círculos centrados na origem.

Explicação da premissa

Agora vamos imaginar que estamos em um avião, e neste plano só podemos viajar de maneiras especiais. Estamos autorizados a viajar em qualquer raio que emana da origem.

Raios em que podemos viajar

Também podemos viajar em qualquer círculo centrado em um círculo

Círculos em que podemos viajar

Agora, nosso objetivo é viajar de um ponto nesse avião para outro. No entanto, não podemos simplesmente viajar por um caminho euclidiano simples; só podemos fazer isso se os pontos caírem em um raio que emana do centro.

insira a descrição da imagem aqui

Podemos viajar nessa porque cai em um dos nossos raios.

insira a descrição da imagem aqui

Também podemos viajar em círculos centrados na origem.

insira a descrição da imagem aqui

Exemplos

Agora, aqui está o desafio:

Temos que ir de um ponto a outro no caminho mais curto; geralmente é uma combinação de viagens em círculos e raios.

insira a descrição da imagem aqui

Isso, no entanto, também pode estar viajando em dois raios.

insira a descrição da imagem aqui

Às vezes, existem dois caminhos que percorrem a distância mínima.

insira a descrição da imagem aqui

Problema

Seu desafio é escrever um programa que, quando dados dois pontos, nos dará a distância mínima entre eles, se seguirmos essas regras. As entradas podem ser dadas em formas retangulares ou polares e a saída deve ser um número, a distância entre elas.

Casos de teste

(com entrada retangular)

(1,1) (1,-1) -> ~ 2.22144
(0,0) (1, 1) -> ~ 1.41421
(1,0) (-0.4161 , 0.90929) -> ~ 2
(1,1) (1, 0) -> ~ 1.19961
(1,2) (3, 4) -> ~ 3.16609
Ando Bando
fonte
Os exemplos de casos de teste estão em formas retangulares ou polares? Também:
bewteen
Eles estão na forma retangular, devo esclarecer que
Ando Bando
O último exemplo está correto? Estou recebendo ~ 3.166
Angs
6
@ Peter Taylor Porque eles não são realmente o mesmo caminho. De maneira semelhante, um caminho de 0,0 a 1,1 no plano xy através de pequenos passos alternados nas direções x e y parece idêntico a um caminho diagonal direto, pois o comprimento do passo tende a zero. Mas o caminho diagonal tem comprimento sqrt (2), enquanto o caminho passo terá sempre comprimento 2.
Penguino
1
Acho que o desafio ficaria melhor se as imagens não fossem tão grandes. Atualmente eles dificultam o acompanhamento do texto
Luis Mendo 21/11

Respostas:

5

Haskell, 49 48 bytes

(a!q)c r=min(q+r)$abs(q-r)+acos(cos$a-c)*min q r

Uso:

> let rect2polar (x,y)=(atan2 y x, sqrt(x^2+y^2))
> let test c1 c2=let [(a1,r1),(a2,r2)]=rect2polar<$>[c1,c2] in (a1!r1)a2 r2
> test (1,0) (-0.4161, 0.90929)
1.9999342590038496

Obrigado a @Zgarb por salvar um byte

Angs
fonte
Você pode salvar um byte, definindo em (a!q)c rvez de d a q c r.
Zgarb
4

JavaScript (ES6), 65 bytes

with(Math)(r,t,s,u,v=acos(cos(t-u)))=>v<2?abs(r-s)+v*min(r,s):r+s

Toma coordenadas polares. Usa o truque do @Angs para reduzir um ângulo entre 0 e π. Para coordenadas retangulares, algo como isto funciona:

with(Math)g=(r,t,s,u,v=acos(cos(t-u)))=>v<2?abs(r-s)+v*min(r,s):r+s
with(Math)f=(x,y,v,w)=>g(hypot(y,x),atan2(y,x),hypot(w,v),atan2(y,v))
Neil
fonte
3

MATL , 22 bytes

|ttsGZ}/X/bX<*|bd|+hX<

Entrada é uma matriz de dois números complexos.

Experimente online! Ou verifique todos os casos de teste .

Explicação

|       % Implicitly input array and take absolute value of its entries
tt      % Duplicate twice
s       % Sum. This is the length of the path that follows the two radii
GZ}     % Push input again and split into the two numbers
/X/     % Divide and compute angle. This gives the difference of the angles
        % of the two points, between -pi and pi
bX<     % Bubble up a copy of the array of radii and compute minimum
*|      % Multiply and take absolute value. This is the arc part of the
        % path that follows one arc and the difference of radii
bd|     % Bubble up a copy of the array of radii and compute absolute
        % difference. This is the other part of the second path
+       % Add. This gives the length of second path
hX<     % Concatenate and take minimum to produce the smallest length.
        % Implicitly display
Luis Mendo
fonte
2

Ruby, 64 bytes

Primeiro, minha submissão. Função Lambda com argumentos distance 1, angle 1, distance 2, angle2.

->r,a,s,b{([d=(b-a).abs,?i.to_c.arg*4-d,2].min-2)*[r,s].min+s+r}

Agora, aqui estão duas soluções diferentes de 66 bytes (excluindo a atribuição f=), seguidas pelo meu envio real novamente em 64 bytes.

Solution 1:Using include Math, 66 bytes excluding f=
include Math;f=->r,a,s,b{[acos(cos(b-a)),2].min*[r,s].min+(s-r).abs}

Solution 2:Using complex number to define PI instead, 66 bytes excluding f=
f=->r,a,s,b{[d=(b-a).abs,?i.to_c.arg*4-d,2].min*[r,s].min+(s-r).abs}

SUBMISSION AGAIN, 64 bytes excluding f=
f=->r,a,s,b{([d=(b-a).abs,?i.to_c.arg*4-d,2].min-2)*[r,s].min+s+r}

O envio é baseado na solução 2, mas usa a identidade (s-r).abs= s+r-[s,r].min*2para encurtar o código em 2 bytes, daí o -2interior dos colchetes.

O outro recurso notável é a expressão ?i.to_c.arg*4= 2 * PI sem usar include Math. Se menor precisão é aceitável, isso pode ser substituído por um literal.

Solução 2 comentada no programa de teste

f=->r,a,s,b{          #r,s are distances, a,b are angles for points 1 and 2 respectively.                       
    [d=(b-a).abs,       #From nearer point we can take arc of length d radians perhaps crossing zero angle to the ray of the further point
    ?i.to_c.arg*4-d,    #or go the other way round which may be shorter (?i.to_c.arg*4 == 2*PI, subtract d from this.)
    2].min*             #or go through the centre if the angle exceeds 2 radians.
  [r,s].min+          #Multiply the radians by the distance of the nearer point from the origin to get the distance travelled. 
  (s-r).abs           #Now add the distance to move along the ray out to the further point.
}

#test cases per question (given as complex numbers, converted to arrays of [distance,angle]+[distance,angle] (+ concatenates.)
#the "splat" operator * converts the array to 4 separate arguments for the function.
p f[*("1+i".to_c.polar + "1-i".to_c.polar)]
p f[*("0".to_c.polar + "1+i".to_c.polar)]
p f[*("1".to_c.polar + "-0.4161+0.90929i".to_c.polar)]
p f[*("1+i".to_c.polar + "1".to_c.polar)]
p f[*("1+2i".to_c.polar + "3+4i".to_c.polar)]

Saída

2.221441469079183
1.4142135623730951
1.9999342590038496
1.1996117257705434
3.1660966740274357
Level River St
fonte
2

Mathematica 66 Bytes

Isso requer coordenadas retangulares e pode gerar uma solução simbólica exata

Min[If[(m=Min[{p,q}=Norm/@#])>0,m*VectorAngle@@#,0]+Abs[p-q],p+q]&

Uso:

%/@{
{{1,1},{1,-1}},
{{0,0},{1,1}},
{{1,0},{-.4161,.90929}},
{{1,1},{1,0}},
{{1,2},{3,4}}
}

rendimentos: resultado simbólico

N @% de rendimento:

{2.221441469, 1.414213562, 1.999934259, 1.199611726, 3.166096674}

Kelly Lowder
fonte
1
Bacana! se você estiver seguindo a rota simbólica, poderá substituir o caso de teste {1,0} {-. 4161, .90929} por {1,0} {cos (2), sin (2)}
Ando Bando
1

Python 2, 164 126 125 132 bytes:

def A(a,b,c,d,p=3.1415926535):z=abs(a-c);M=lambda f:2*p*f*abs(b-d)/360.0;print min((a==c)*min(a+c,M(a))+(b==d)*z or'',M(a)+z,M(c)+z)

No momento, estou olhando mais para o golfe. Aceita coordenadas polares. Deve ser chamado no formato A(r1,θ1,r2,θ2). Emite um valor de ponto flutuante com precisão de até 12números significativos.

Experimente Online! (Ideona)

Uma implementação simples e direta que calcula e gera como STDOUT o valor mínimo de uma matriz de no máximo 3 valores contendo:

  1. o valor mínimo da soma dos dois comprimentos ( r1+r2) ou do comprimento do arco que liga os dois pontos se r1==r2 ;
  2. a diferença entre as duas distâncias ( abs(r1-r2)) iff θ1==θ2 (isto é, os dois pontos são colineares);
  3. se nenhum dos 2 itens anteriores for adicionado, uma string vazia ( '') como aparentemente em Python, uma string será maior que qualquer número inteiro;
  4. e 2 valores finais dados a partir das distâncias percorridas ao longo de um círculo e um raio e vice-versa entre os dois pontos.
R. Kap
fonte
Por que não math.pi?
usar o seguinte comando
0

Wolfram Language (Mathematica) , 47 bytes

MinMax@Abs@{##}.{Min[Abs[Arg@#-Arg@#2]-1,1],1}&

Experimente online!

(supera a atual resposta de 66 bytes)

Tome entrada como 2 números complexos.

Pode haver alguns problemas se a entrada for simbólica. (por exemplo, Cos@2 + I Sin@2)

user202729
fonte