Pegue uma grade bidimensional e desenhe um número de segmentos de linha para representar espelhos. Agora escolha um ponto para colocar um laser teórico e um ângulo para definir a direção que está apontando. A questão é: se você segue o caminho do feixe de laser por uma distância especificada, em que ponto de coordenada você está?
Exemplo:
Nesta imagem, L
é a localização do laser, t
é o ângulo que o (medido a partir do eixo X positivo), M1
, M2
, e M3
são todos os espelhos segmento de linha, e E
é o ponto do percurso do feixe de laser, depois D = d1 + d2 + d3 + d4
de unidades, a partir de L
.
Objetivo
Escrever o programa mais curto (em bytes) que saídas E
dada L
, t
, D
, e uma lista de espelhos.
(Use http://mothereff.in/byte-counter para contar bytes.)
Formato de entrada
A entrada virá do stdin no formato:
Lx Ly t D M1x1 M1y1 M1x2 M1y2 M2x1 M2y1 M2x2 M2y2 ...
- Todos os valores serão pontos correspondentes esse regex flutuante:
[-+]?[0-9]*\.?[0-9]+
. - Sempre há exatamente um espaço entre cada número.
- É necessário solicitar cotações em torno da entrada.
t
está em graus, mas não necessariamente na[0, 360)
faixa. (Se preferir, use radianos, apenas diga na sua resposta.)D
pode ser negativo, girando efetivamente o laser 180 graus.D
também pode ser 0.- Pode haver arbitrariamente muitos espelhos (incluindo nenhum).
- A ordem dos espelhos não deve importar.
- Você pode assumir que a entrada será apresentada em múltiplos de 4 números. por exemplo,
Lx Ly t
ouLx Ly t D M1x1
são inválidos e não serão testados. Nenhuma entrada também é inválida.
O layout acima pode ser inserido como:
1 1 430 17 4.8 6.3 6.2 5.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3
(Observe que a imagem foi desenhada à mão livre e esses valores são apenas aproximações. Os valores de entrada de Martin Büttner de
1 1 430 17 4.8 5.3 6.2 4.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3
dará mais colisões, embora não correspondam ao esboço.)
Formato de saída
A saída deve ir para stdout no formato:
Ex Ey
Estes também são carros alegóricos e podem estar na forma exponencial.
Notas
- Os espelhos podem se cruzar.
- Ambos os lados dos espelhos são reflexivos.
- O raio pode atingir o mesmo espelho várias vezes.
- O raio continua para sempre.
Casos indefinidos
Você pode assumir que os casos em que
- o laser começa em um segmento de linha de espelho
- o raio laser atinge o ponto final de um espelho
- o raio laser atinge a interseção entre dois espelhos
são indefinidos e não serão testados. Seu programa pode fazer qualquer coisa, se isso ocorrer, incluindo gerar um erro.
Bônus
Apenas por diversão, atribuirei 200 pontos de recompensa à mais votada, que gera uma representação gráfica do problema (você pode até escrever um script interativo). Esses envios de bônus não precisam ser disputados e podem ser tolerantes com a forma como a entrada e a saída são tratadas. Eles são distintos dos envios reais de golfe, mas ambos devem ser enviados na mesma resposta .
Nota: apenas enviar uma resposta de bônus é bom, você não será a resposta aceita. Para ser aceito, você deve seguir exatamente as especificações de entrada / saída (por exemplo, apenas a saída envolve Ex Ey
, não imagens) e ser o menor.
Respostas:
Ruby, 327 bytes
(role para baixo)
Mathematica, resposta bônus
Estou indo apenas para a apresentação gráfica agora. Eu posso portar isso para Ruby mais tarde e jogar golfe, se eu quiser.
Você pode chamá-lo como
Isso fornecerá uma animação no Mathematica e também exportará um GIF (aquele na parte superior desta entrada). Estendi um pouco o exemplo dos OPs para isso, para torná-lo um pouco mais interessante.
Mais exemplos
Um tubo com paredes ligeiramente divergentes, mas com uma extremidade fechada:
Um triângulo equilátero e uma direção inicial quase paralela a um dos lados.
Mais um:
Ruby, resposta de golfe
Esta é basicamente uma tradução direta da solução Mathematica para Ruby, além de alguns jogos de golfe e garantir que ela atenda aos critérios de E / S.
fonte
Python 3 (
421C 390C, 366C)Use
builtin.complex
como vetor 2d. tãoPara vencer a solução 368C Ruby, encontrei um método bastante compacto para calcular a reflexão de pontos ao longo de um espelho. E também usou álgebra complexa para reduzir mais caracteres. Eles podem ser facilmente encontrados no código não-destruído.
Aqui está a versão do golfe.
Ungolfed
Bônus: HTML, Coffeescript, Ajuste e cálculo em tempo real
Ou seja, você arrasta quaisquer pontos finais (ou lazer, mirros) e a trilha é renderizada. Ele também suporta dois tipos de entrada, o descrito na pergunta e o usado por @Martin Büttner.
A escala também é ajustada automaticamente.
Por enquanto não tem animação. Talvez eu melhore depois. No entanto, arraste os pontos brancos e você poderá ver outro tipo de animação. Experimente online aqui você mesmo, é engraçado!
Todo o projeto pode ser encontrado aqui
Atualizar
Aqui eu forneço um caso interessante:
E o resultado é:
fonte
JavaScript HTML,
10.543,947889Corrigi um bug e verifiquei se a saída atende às especificações da pergunta. A página da web abaixo tem a versão para golfe e também a versão gráfica do bônus. Também corrigi um erro apontado pelo @Ray que salvava 58 caracteres. (Obrigado Ray.) Você também pode executar o código em um console JavaScript. (Agora estou usando um laser verde de 2 mW.)
Código Golf
Entrada
Saída
Você pode testá-lo aqui: http://goo.gl/wKgIKD
Explicação
O código na página da web é comentado. Basicamente, calculo a interseção do laser com cada espelho, assumindo que o laser e os espelhos são infinitamente longos. Então eu verifico se a interseção está dentro do comprimento finito do espelho e do laser. Então pego a interseção mais próxima, movo o laser para esse ponto e continuo até que o laser perca todos os espelhos.
Projeto muito divertido. Obrigado por fazer esta pergunta!
Código legível
fonte
0 0 0.4 100 1 1 1 -1 1 -1 -1 -1 -1 -1 -1 1 -1 1 1 1
.Python - 765
Bom desafio. Esta é a minha solução que obtém a entrada do stdin e produz o stdout. Usando o exemplo de @Martin Büttner:
Aqui está o código do golfe:
E aqui está o código não destruído com uma figura de bônus
fonte
sys.argv
não é stdin.Matlab (388)
Enredo
Conceitos
Pontos de reflexão
Para calcular os pontos de reflexão, basicamente precisamos interceptar duas linhas retas. Um com o ponto p0 e o vetor v, o outro entre os dois pontos p1, p2. Portanto, a equação a ser resolvida é (s, t são parâmetros): p0 + t v = s p1 + (1-s) * p2.
O parâmetro s é então uma coordenada barricêntrica do espelho, portanto, se 0
Espelhamento
O espelhamento de v é bem simples. Vamos supor que || v || = || n || = 1 onde n é o vetor normal do espelho atual. Então você pode simplesmente usar a fórmula v: = v-2 ** n onde <,> é o produto escalar.
Validade do passo
Ao computar o espelho 'válido' mais próximo, precisamos considerar alguns critérios que o tornam válido. Primeiro, o ponto de interceptação do espelho deve estar entre os dois pontos de extremidade, portanto deve ser 0
Programa
Pouco golfe (388)
fonte