O problema:
Dado um conjunto não vazio de pontos no plano cartesiano, encontre o menor círculo que os inclua todos ( link da Wikipedia ).
Esse problema é trivial se o número de pontos for três ou menos (se houver um ponto, o círculo terá um raio de zero; se houver dois pontos, o segmento de linha que une os pontos será o diâmetro do círculo; se houver três pontos (não colineares), é possível obter a equação de um círculo que toca todos eles se formarem um triângulo não obtuso, ou um círculo que toca apenas dois pontos e encerra o terceiro se o triângulo for obtuso). Portanto, para o desafio deste desafio, o número de pontos deve ser maior que três.
O desafio:
- Entrada: uma lista de 4 ou mais pontos não colineares. Os pontos devem ter coordenadas X e Y; coordenadas podem ser flutuantes. Para facilitar o desafio, dois pontos não devem compartilhar a mesma coordenada X.
Por exemplo:[(0,0), (2,1), (5,3), (-1,-1)]
- Saída: uma tupla de valores,
(h,k,r)
tais que é a equação do menor círculo que envolve todos os pontos.
Regras:
- Você pode escolher qualquer método de entrada adequado ao seu programa.
- A saída deve ser impressa
STDOUT
ou retornada por uma função. - Os idiomas "normais", de uso geral, são preferidos, mas qualquer esolang é aceitável.
- Você pode assumir que os pontos não são colineares.
- Isso é código-golfe, então o menor programa em bytes vence. O vencedor será selecionado uma semana após o lançamento do desafio.
- Inclua o idioma que você usou e o comprimento em bytes como cabeçalho na primeira linha da sua resposta:
# Language: n bytes
- Inclua o idioma que você usou e o comprimento em bytes como cabeçalho na primeira linha da sua resposta:
Casos de teste:
- 1:
- Entrada:
[(-8,0), (3,1), (-6.2,-8), (3,9.5)]
- Saída:
[-1.6, 0.75, 9.89]
- Entrada:
- 2:
- Entrada:
[(7.1,-6.9), (-7,-9), (5,10), (-9.5,-8)]
- Saída:
[-1.73, 0.58, 11.58]
- Entrada:
- 3:
- Entrada:
[(0,0), (1,2), (3,-4), (4,-5), (10,-10)]
- Saída:
[5.5, -4, 7.5]
- Entrada:
- 4:
- Entrada:
[(6,6), (-6,7), (-7,-6), (6,-8)]
- Saída:
[0, -0.5, 9.60]
- Entrada:
Feliz golfe !!!
Respostas:
Wolfram Language (Mathematica) ,
2827 bytesExperimente online!
Os built-ins são úteis aqui. Saída é um objeto de disco com o centro e o raio. Como outros, eu achei o segundo e o terceiro casos de teste diferentes da questão.
Agradecemos a @lirtosiast por salvar um byte!
Se uma lista for necessária como saída, isso poderá ser feito em 35 bytes (ao custo de 8 bytes adicionais) . Agradecemos a @Roman por apontar isso.
fonte
Append@@BoundingRegion[#,"MinDisk"]&
JavaScript (ES6),
298 ... 243242 bytesRetorna uma matriz
[x, y, r]
.Experimente online!
ou veja uma versão formatada
Quão?
Método
Para cada par de pontos( A , B ) , que gera o círculo ( X, Y, r ) , cujo diâmetro é A B .
Para cada triplo de pontos distintos( A , B , C) , que gera o círculo ( X, Y, r ) que circunscreve o triângulo A B C .
E, finalmente, retornamos o menor círculo válido.
Implementação
fonte
R , 59 bytes
Experimente online!
Recebe entrada como um vetor de coordenadas complexas.
Mod
é a distância (módulo) no plano complexo enlm
é uma função de otimização: encontra a posição do centro (saída comoestimate
) que minimiza a distância máxima aos pontos de entrada e fornece a distância correspondente (saída comominimum
), ou seja, o raio . Preciso para 3-6 dígitos; o rodapé do TIO arredonda a saída para 2 dígitos.nlm
recebe um vetor numérico como entrada: ay%*%c(1,1i)
empresa o converte em um complexo.fonte
Geléia ,
10098 bytesExperimente online!
Em contraste com a minha resposta na linguagem Wolfram , o Jelly precisa de muito código para conseguir isso (a menos que esteja perdendo alguma coisa!). Este programa completo pega a lista de pontos como argumento e retorna o centro e o raio do menor círculo fechado. Ele gera circuitos para todos os conjuntos de três pontos e diâmetros para todos os conjuntos de dois pontos, verificações que incluem todos os pontos e, em seguida, seleciona aquele com o menor raio.
O código do bit make_circumcircle foi inspirado no código deste site , por sua vez, inspirado na Wikipedia.
fonte
APL (NARS), 348 caracteres, 696 bytes
Esta é uma 'implementação' de fórmulas na solução Arnauld ... Resultados e comentários:
f: encontra a combinação de alfa ojets no conjunto ômega
((X, Y), r) a partir de agora representam uma circonferência do raio r e centro em (XY).
c: descobre se o ponto em ⍺ está dentro da circunferência ((XY) r) em ⍵ (resultado <= 0) ou é externo (resultado> 0) No caso da entrada da circunferência em ⍵ é ⍬ como entrada, é retornaria 1 (fora da circunferência) cada entrada possível em ⍺.
p: se ⍵ é uma matriz de ((XY) r); para cada um dos ((XY) r) em ⍵ escreve 1 se todos os pontos da matriz ⍺ são internos para ((XY) r) escreve de outra forma 0 NB Aqui está algo que não vale porque eu tive que arredondar para epsilon = 1e¯ 13) em outras palavras, em casos limitados de pontos no avião (e provavelmente criados de propósito), não é 100% a solução segurada
s2: de 2 pontos em ⍵, retorna a circunferência no formato ((XY) r) que possui diâmetro nesses 2 pontos
s3: a partir de 3 pontos, retorna a circunferência no formato ((XY) r) passando por esses três pontos. Se houver problemas (por exemplo, os pontos estão alinhados), ela falhará e retornará ⍬.
note que -. × encontra o determinante de uma matriz nxn e
s: de n pontos em ⍵, encontra as circunferências de tipo daquelas encontradas por s2 ou as do tipo s3 que contêm todos os n pontos.
s1: do conjunto encontrado dos s acima calcula aqueles que possuem raio mínimo e retorna o primeiro que possui raio mínimo. Os três números como matrizes (a primeira e a segunda coordenadas são as coordenadas do centro, enquanto o terceiro é o raio da circunferência encontrada).
fonte
Python 2 (PyPy) ,
244242 bytesExperimente online!
Isso usa o algoritmo de força bruta O (n ^ 4), percorrendo cada par e triângulo de pontos, calculando o centro e mantendo o centro que precisa do menor raio para incluir todos os pontos. Ele calcula o perímetro de 3 pontos, encontrando a interseção de dois bissetores perpendiculares (ou, se dois pontos são iguais, ele usa o ponto médio com o terceiro).
fonte
P={x+y*1j for x,y in input()}
economiza 2 bytes também.Python
212190 bytesEsta solução está incorreta e tenho que trabalhar agora para não ter tempo para corrigi-la.
Experimente online!
Eu descobri quais são os dois pontos mais distantes e, em seguida, gerei uma equação para um círculo baseado nesses pontos!
Eu sei que isso não é o mais curto em python, mas é o melhor que eu poderia fazer! Além disso, esta é a minha primeira tentativa de fazer uma delas, então, por favor, seja compreensivo!
fonte
if g>c:\n c=g\n d=[e,f]
paraif g>c:c=g;d=[e,f]
, economizando muito espaço em branco. Eu não acho que você precise inicializar d antecipadamente, também usando duas variáveis eE,F=e,f
na linha 10 você ficaráprint
muito mais curto. Acho que uma soluçãomax
e uma compreensão da lista seriam ainda mais curtas que dois loops, mas posso estar errado. Infelizmente, no entanto, sua solução não está correta. Para os pontos (-1,0), (0,1,41), (0,5, 0), (1,0), sua solução calcula um círculo em torno de 0 com raio 1. Mas o ponto (1, 1,41) não está nesse círculo.