Neste desafio, você receberá uma lista de pontos. Esses pontos estão no perímetro de um quadrado imaginário . Seu objetivo é:
- Se possível, imprima a rotação do quadrado, que será um valor de [0, 90), em que 0 representa um quadrado com linhas verticais e horizontais. A rotação deve ser dada em graus contados no sentido anti-horário.
- Se a rotação do quadrado for ambígua (como receber apenas 2 pontos), imprima "Desconhecido"
- Se a criação de um quadrado dado os pontos for impossível, imprima "Impossível"
Os pontos que você recebe são garantidos como únicos e não estão em uma ordem específica. Você pode usar qualquer formato que desejar inserir na lista, mas, para meus exemplos, meus pontos estarão no formato x,y
e no espaço será separado. Os números são de ponto flutuante e você pode assumir que eles estão dentro de um intervalo que seu idioma possa suportar. Sua saída deve ser precisa com pelo menos três casas decimais e assumir que seu idioma lida com números de ponto flutuante com precisão perfeita.
Aqui estão alguns casos de teste (eu fiz a maioria deles usando números inteiros para facilitar a visualização, mas seu programa deve lidar com pontos flutuantes):
Desconhecido:
0,0
0,0 1,0
0,0 1,0 0,1
0,0 1,0 0,1 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2
Impossível:
0,0 1,0 2,0 3,1 4,2
0,0 1,0 2,0 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2 2,2
2,0 0,1 2,2 0,3
0,0 2,1 0,2 2,2 -1,1
Possível (se não designado, deve retornar 0):
0,0 1,0 2,0
0,0 0.3,0.3 0.6,0.6 (should return 45)
0,0 0.1,0.2 0.2,0.4 (should return appx 63.435 (the real value is arctan(2)))
0,0 0,1 2,1 2,2
0,1 0,2 1,0 1,4 2,0 2,4 4,1 4,3
Eu posso ter perdido alguns casos de teste interessantes. Se sim, comente para adicioná-los.
Isso é código-golfe, então o código mais curto vence!
Respostas:
Rev 1: Ruby, 354 bytes
mais golfe graças ao blutorange.
Ruby, 392 bytes
O algoritmo é o seguinte:
-Escolha um ponto arbitrário (o primeiro) e mova-o para a origem (subtraia as coordenadas desse ponto de todos os pontos da lista).
-Tente todas as rotações do quadrado sobre a origem em incrementos de 0,001 grau a 360 graus.
-Para uma determinada rotação, se todos os pontos estiverem acima do eixo y, desenhe o menor quadrado possível em torno de todos os pontos, incorporando o ponto mais baixo e o mais à esquerda.
-Verifique se todos os pontos estão no limite. Isso é feito com um cálculo simples que pega cada ponto, localiza as distâncias ao quadrado de todas as arestas e as multiplica. Isso dá um bom ajuste ao invés de uma resposta sim / não. É interpretado que uma solução é encontrada se este produto dividido pelo comprimento da linha lateral ^ 8 for menor que 1E-9. Na prática, isso é menos que um grau de tolerância.
-O melhor ajuste é obtido mod 90 graus e relatado como o ângulo correto.
Atualmente, o código retorna um valor ambíguo se forem encontradas mais de 100 soluções (com resolução de 0,001 grau. Isso é 0,1 grau de tolerância).
primeira função totalmente funcional, no programa de teste
Deixei a resolução em 1/10 da resolução necessária para tornar a velocidade razoável. Há um erro de 0,01 degress no último caso de teste.
A versão para golf, resolução compatível com as especificações, leva cerca de um minuto por chamada, no programa de teste.
Ainda existe um erro irritante de 0,001 graus no último caso de teste. Aumentar ainda mais a resolução provavelmente a eliminaria.
Observe que, para cerca de 30% a mais de código, esse algoritmo pode ser adaptado para funcionar rapidamente: é óbvio que em casos com um número finito de soluções, uma das arestas fica plana ao longo de um cubo, então tudo o que realmente precisamos tentar é esses ângulos que correspondem a cada par de vértices. Também seria necessário fazer algumas oscilações para verificar se não existem infinitas soluções.
fonte
0,0 1,0 2,0 1,2
ainda é possível para um quadrado de diagonal 0,0 ... 2,2. Eu tentei isso e também0,0 1,0 2,0 1,1
(o último é realmente impossível.) Outro ponto: você considera aceitável ou inaceitável que meu código retorne mais impossível do que desconhecido quando apenas um ponto é dado? Eu apreciaria uma resposta antes de começar a jogar golfe.1,1
. Não sei como1,2
chegou lá. Não é aceitável.if..end
s porque tenho um problema terrível com operadores ternários aninhados em Ruby. Vejo que você contornou isso usando&&
.Perl
Olá, aqui está minha humilde alma. Os casos de teste são colocados no fluxo de dados na parte inferior do arquivo. O algoritmo cresceu com uma abordagem de tentativa e erro.
Admito que é uma abordagem amplamente heurística, mas é realmente rápida: resolve todos os casos instantaneamente .
Estou ciente de que haverá alguns erros, mas até agora ele fornece respostas corretas para todos os casos de teste.
Também estou ciente de que o código mais curto vence, mas tenho certeza de que esse é um dos mais curtos no significado mais rápido do termo.
Aqui está o algoritmo
examine os pontos e, para cada segmento, entre dois pontos, incline o registro, comprimento, interceptação x, intercepto em y
encontre linhas retas (isto é, três pontos ou dois segmentos adjacentes) e inclinações possíveis distintas (digamos, rotações). Acompanhe o segmento mais longo disponível em cada linha.
encontre todas as distâncias entre um segmento e um terceiro ponto (isso deve ser usado no ponto 4). Acompanhe a distância mínima diferente de zero.
para quaisquer quatro pontos (um retângulo áspero) encontre pontos internos
Mostrar soluções:
A. Diga "Impossível" se houver um ou mais pontos internos.
B. Uma linha:
No caso da maioria dos pontos em uma única linha sem pontos internos, diga "Possível"
No caso de pontos muito próximos da linha, diga "Impossível"
C. Duas linhas:
Diga "Possível" quando houver apenas uma rotação possível
Diga "Impossível" quando houver mais de uma rotação
D. Sem linhas: encontre a rotação que se ajusta ao seu segmento de rotação de 90 °
Diga "Possível" se apenas um couber ou quantos pontos couberem.
Diga "Impossível" se mais de um couber e não tantos quantos pontos
Diga "Desconhecido" se houver o ajuste de rotação.
Aqui está o código (todos os erros conhecidos foram resolvidos)
E aqui está sua saída
Saudações.
Matteo.
fonte