Jogando bilhar

17

Nesse código de golfe, você terá que determinar a direção do tiro mais curto que atingir exatamente n almofadas antes de cair no bolso.

A mesa de bilhar é uma mesa de bilhar de 6 bolsos com as seguintes características:

  • As dimensões são variáveis ​​( a x b )
  • Sem atrito: a bola rolará para sempre até cair no bolso
  • Bolsos e tamanhos de bolas são quase nulos. Isso significa que a bola cairá no bolso apenas se tiver a mesma posição.
  • A bola é colocada no buraco inferior esquerdo no início (mas não cai nela)

3cushion

Crie um programa ou função completo que tome as dimensões ( a , b ) da tabela e o número de almofadas para atingir n como entrada e retorne o ângulo em graus do caminho mais curto, atingindo exatamente n almofadas antes de cair no bolso.

  • a > 0
  • b > 0
  • 0 <= n <10000000
  • 0 < alfa <90 (em graus) de precisão: pelo menos 10 ^ -6

exemplos :

com a = 2, b = 1, n = 1, existem três caminhos possíveis: (1) (2) (3) na figura a seguir. o número (1) é o menor, portanto a saída deve ser atan (2) = 63,43494882292201 graus

1 almofada

A solução para a = 2, b = 1, n = 4 é atan (4/3) = 53,13010235415598 graus

4 almofadas

amostras de teste:

a = 2,    b = 1,    n = 1,       -> alpha = 63.43494882292201
a = 2,    b = 1,    n = 2,       -> alpha = 71.56505117707799
a = 2,    b = 1,    n = 3,       -> alpha = 75.96375653207353
a = 2,    b = 1,    n = 4,       -> alpha = 53.13010235415598
a = 2,    b = 1,    n = 5,       -> alpha = 59.03624346792648
a = 2,    b = 1,    n = 6,       -> alpha = 81.86989764584403
a = 4.76, b = 3.64, n = 27,      -> alpha = 48.503531644784466
a = 2,    b = 1,    n = 6,       -> alpha = 81.86989764584403
a = 8,    b = 3,    n = 33,      -> alpha = 73.24425107080101
a = 43,   b = 21,   n = 10005,   -> alpha = 63.97789961246943

Este é o código / golfe de bilhar: o menor código vence!

Damien
fonte
A bola precisa acertar exatamente n almofadas, ou pelo menos n almofadas?
Peter Taylor
@PeterTaylor exatamente n almofadas
Damien
o caminho mais curto nem sempre é alternado entre o lado esquerdo superior e inferior e depois em um dos orifícios do meio?
Eumel
não, veja o exemplo 2 1 4. Este caminho é sqrt (25) = 5 longa enquanto que a sua solução é sqrt (26)
Damien

Respostas:

11

Python 2.7, 352 344 281 bytes

from math import*
def l(a,b,n):
 a*=1.;b*=1.
 r=set()
 for i in range(1,n+3):
  t=[]
  for k in range(1,i):
   for h in[0,.5]:
    x=(i-k-h)
    if 1-(x/k in r):r.add(x/k);t+=(x*a,k*b),
 d=(a*n+1)**2+(b*n+1)**2
 for x,y in t:
  if x*x+y*y<d:d=x*x+y*y;o=degrees(atan(y/x))
 return o
  • -16 bytes graças a @Dschoni

Explicação: ao invés de calcular as ocorrências de almofadas, estou adicionando n tabelas e aceitando os novos furos como válidos: bilhar Borda preta / furos é o original, borda verde / furos é válida para n = 1, borda vermelha / furos é válida para n = 2 e assim por diante. Depois, removo os orifícios inválidos (por exemplo, a seta azul para n = 1). Vou ter uma lista de furos válidos e suas coordenadas, depois calculo a distância do ponto inicial e, em seguida, o ângulo da distância menor.
Notas:
a = 4,76, b = 3,64, n = 27 - forneça 52,66286, tentando descobrir por que foi corrigido e salvou 8 bytes no processo = D
a = 43, b = 21, n = 10005 - leva ~ 80 segundos ( mas dá o ângulo certo)

versão legível:

from math import *
def bill(a,b,n):
    a=float(a)
    b=float(b)
    ratios = set()
    for i in range(0,n+2): # Create the new boards
        outter = []
        j=i+1
        for k in range(1,j): # Calculate the new holes for each board
            #y=k
            for hole_offset in [0,0.5]:
                x=(j-k-hole_offset)
                if (x/k) not in ratios:
                    ratios.add(x/k)
                    outter.append((x*a,k*b))
    min_dist = (a*n+1)**2+(b*n+1)**2
    for x,y in outter:
        if x*x+y*y<min_dist:
            min_dist = x*x+y*y
            min_alpha=degrees(atan(y/x))
    return min_alpha
Cajado
fonte
Você pode salvar um byte removendo o espaço em : degrees
Morgan Thrapp
Não tenho ideia de como sua resposta funciona (matemática), mas acho que você pode ganhar 1 byte removendo o espaço após os dois pontos. :) (O que @MorganThrapp disse)
basile-henry
2
Este caminho é válido, mas não é o mais curto em todos os casos, por exemplo, com 2 1 4 ..
Damien
Isso também assume isso b < a. Isso poderia ser facilmente corrigido, obtendo o mínimo / máximo de ae bembora.
user81655
fixo (sorta)
Rod
3

Haskell, 133 117 bytes

Esta é a minha implementação:

Com uma tabela 2x1, um caminho atingirá exatamente n almofadas antes de entrar no bolso se: (x-1) / 2 + (y-1) == ne x, y são primos entre si. onde x, y são a distância da bola sobre os eixos horizontal / vertical.

Os caminhos são os mesmos com o tamanho da tabela arbitrária; portanto, apenas precisamos atualizar comprimentos e ângulos com (a, b) e manter o menor. O comprimento do caminho é sqrt ((x * a / 2) ^ 2 + (y * b) ^ 2) e o ângulo é atan ((y * b) / (x * a / 2))

z=toEnum
f a b n=minimum[[z x^2+r^2,180/pi*atan(r/z x)]|x<-[1..2*n+2],y<-[n+1-div(x-1)2],r<-[2*b/a*z y],gcd x y<2]!!1
Damien
fonte