Menor Disco Inteiro


23

Esse desafio é encontrar o menor disco que contenha alguns pontos. Isso é um pouco mais complicado, no entanto, pelo fato de que neste desafio, as coordenadas e o raio do disco devem ser inteiros.

Sua entrada será uma lista de pontos com coordenadas inteiras xe y. Você pode considerar isso como uma lista de tuplas, uma lista de listas ou qualquer outra maneira de representar uma coleção de pares. xe yserão ambos (possivelmente negativos) números inteiros. Cada ponto é garantido como único e haverá pelo menos um ponto.

Sua saída será um disco na forma de três números, X, Y, e R. X, YE Rsão todos inteiros, Xe Yrepresentam o centro do disco e Rrepresenta o seu raio. A distância entre cada ponto especificado e o centro deve ser menor ou igual a Re não deve existir um disco com um menor Rque também satisfaça essa condição.

É possível que existam várias soluções possíveis para uma determinada entrada; seu código deve gerar pelo menos uma delas nesse caso.

Você pode usar qualquer tipo de geometria embutida em seu idioma, se houver, e a entrada / saída pode ser através de objetos de ponto / disco embutidos, em vez de apenas números.

Casos de teste

Input   (Possible) Output(s)
(x,y)   (X,Y,R)
-------------------------
(0,0)   (0,0,0)
-------------------------
(0,1)   (0,0,1)
(1,0)   (1,1,1)
-------------------------
(1,4)   (4,4,3)
(3,2)
(4,1)
(4,5)
(5,2)
(7,4)
-------------------------
(-1,0)  (0,0,2)
(2,0)   (1,0,2)
-------------------------
(-1,0)  (1,0,2)
(2,1)   (0,1,2)
-------------------------
(0,0)   (1,0,1)
(1,1)   (0,1,1)

Menos bytes ganha.



Encontrado um par de erros de digitação, se você não se importa me apontando-as: "Isto é feito tanto enganar i er ..."; "... representa o centro do disco e R representa i t s raio ..."; "... e não deve existir tal disco ..."
J. Sallé

2
Normalmente, tornar as coisas inteiras apenas facilita o código-golfe.
user202729

@KevinCruijssen Isso é por coincidência. As entradas podem estar em qualquer ordem.
Pavel

1
@Pavel A entrada pode estar em qualquer ordem ou podemos receber a entrada em qualquer ordem? Como em, a entrada pode estar em qualquer ordem e devemos classificar manualmente primeiro em nossa solução, ou já podemos levar a entrada pré-classificada?
Kevin Cruijssen

Respostas:


6

Geléia , 25 24 22 21 20 18 bytes

«/r»/Œpµ³_²§½ṀĊ,)Ṃ

Obrigado a @EriktheOutgolfer por me informar ), economizando 1 byte.

Obrigado a @Dennis por salvar 2 bytes.

Experimente online!

Explicação

«/r»/Œpµ³_²§½ṀĊ,)Ṃ      Main link. Arg: points
                        e.g. [[1,4],[3,2],[3,1]]
«/                      Find minimums by coordinate
                        e.g. [1,1]
   »/                   Find maximums by coordinate
                        e.g. [3,4]
  r                     Inclusive ranges by coordinate
                        e.g. [[1,2,3],[1,2,3,4]]
     Œp                 Cartesian product of the x and y ranges
                        e.g. [[1,1],[1,2],[1,3],[1,4],...,[3,4]]
       µ                    Chain, arg: center
                            e.g. [1,3]
        ³                   Get the original points
                            e.g. [[1,4],[3,2],[3,1]]
         _                  Subtract the center from each
                            e.g. [[0,1],[2,-1],[2,-2]]
          ²                 Square each number
                            e.g. [[0,1],[4,1],[4,4]]
           §                Sum each sublist
                            e.g. [1,5,8]
            ½               Square root of each number
                            e.g. [1,2.24,2.83]
             Ṁ              Find the maximum
                            e.g. 2.83
              Ċ             Round up
                            e.g. 3
               ,            Pair with the center point
                            e.g. [3,[1,3]]
                )       Do the above for all points
                        e.g. [[3,[1,1]],[3,[1,2]],[3,[1,3]],...,[3,[3,4]]]
                 Ṃ      Find the lexicographically smallest pair
                        e.g. [3,[1,1]]

@Dennis Thanks! Desde quando a vetorização de Jelly repetiu a lista mais curta, ou estou interpretando mal a remoção de ?
PurkkaKoodari

As profundidades são correspondidas primeiro. Se você possui um par e uma matriz de pares, o par é correspondido com todos os pares.
Dennis #

8

Brachylog v2, 19 bytes

;Az{\-ᵐ~√ᵐ+}ᵐ≤ᵛ√;A≜

Experimente online!

Esse programa foi fácil de escrever - o Brachylog é quase perfeito para esse tipo de problema - mas difícil de jogar. Não me surpreenderia se houvesse um byte salvando em algum lugar aqui, pois poucas coisas que fiz pareciam ter algum efeito (e contém instruções de mapa aninhadas, normalmente um sinal de que você deveria estar usando member / findall, mas não posso veja uma maneira de fazê-lo).

Este é um envio de função. A entrada é do argumento esquerdo para a função no formato [[x,y],[x,y],…], a saída do argumento direito no formulário [r,[[x,y]]]. (Se você quiser tentar números negativos na entrada, observe que o Brachylog usa _para o sinal de menos, não -. Isso é confuso porque a função → wrapper de programa completo que o Brachylog envia, solicitada usando o argumento da linha de comando Z, apresentará números negativos na saída com um sinal de menos regular.)

Explicação

;Az{\-ᵐ~√ᵐ+}ᵐ≤ᵛ√;A≜
;A                   Append something
  z                    to every element of the input
   {       }ᵐ        such that for each resulting element:
     -                 Subtracting
    \ ᵐ                  corresponding elements {of the (input, appended) element}
       ~√              and un-squarerooting
         ᵐ               {the result of} each {subtraction}
          +            and summing {the resulting square numbers}
             ≤       {lets us find} a number at least as large as
              ᵛ        every element {of the list of sums}
               √     which can be square-rooted;
                ;A   append the same list as initially to it.
                  ≜  Find the first integer solution to the above, lexicographically.

Isso é interessante, pois estamos solicitando ao Brachylog que encontre um valor de determinadas propriedades (nesse caso, o raio de um disco centrado no ponto Aque se encaixa em todos os pontos de entrada), mas dificilmente forçando requisitos (tudo o que exigimos é que o raio é um número). No entanto, o Brachylog calculará internamente o raio em questão simbolicamente, em vez de tentar usar números concretos; portanto, quando a final é alcançada, ele realiza duas coisas ao mesmo tempo: primeiro, garante que apenas números inteiros sejam usados ​​para as coordenadas de Ae para o raio (forçando o raio quadrado a ser um número quadrado e explicando o uso de ≤ᵛpara encontrar um "máximo ou maior"); segundo, encontra o menor raio viável possível (como o raio aparece primeiro na saída).

Uma coisa que não está especificada no programa é que todos os pontos são medidos no mesmo centro de um disco; como está escrito, não há restrições de que não usamos um centro diferente para cada ponto. No entanto, a ordem de desempate (que neste caso é definida pelo terceiro e que como restrição de estrutura será avaliada antes da restrição de valor implícita por ) deseja Aser o mais curta possível (ou seja, um único elemento, portanto, usamos o mesmo centralize cada vez; ele tenta um comprimento zero Aprimeiro, mas isso obviamente não funciona, então tenta uma lista única). Como resultado, acabamos recebendo uma restrição útil (que só temos um disco) "de graça".

Essa solução generaliza para qualquer número de dimensões , sem alterações no código-fonte; aqui não há suposições de que as coisas sejam bidimensionais. Portanto, se você precisar da menor esfera inteira, poderá ter isso também.


3

Perl 6 , 81 bytes

{min [X]([Z]($^p)>>.minmax).map:{$p.map({(@_ Z-$_)>>².sum**.5}).max.ceiling,$_}}

Experimente online!

Toma uma lista de pontos como listas de 2 elementos ((X1, Y1), (X2, Y2), ...). Retorna uma lista (R, (X, Y)). Usa a mesma abordagem que a resposta de Pietu1998 Jelly:

[X]([Z]($^p)>>.minmax)  # All possible centers within the bounding box
.map:{ ... }            # mapped to
$p.map({(@_ Z-$_)>>².sum**.5}).max  # maximum distance from any point
.ceiling                # rounded up,
,$_                     # paired with center.
min                     # Find minimum by distance.

O minmaxmétodo é útil aqui, pois retorna a Range. O produto cartesiano de faixas produz diretamente todos os pontos com coordenadas inteiras.


2

05AB1E , 26 bytes

øεWsàŸ}`âεUIεX-nOt}àîX‚}{н

Porto da resposta de @ Pietu1998 Jelly .

Experimente online ou verifique todos os casos de teste .

Explicação:

ø                    # Zip the (implicit) input, swapping the rows and column
                     #  i.e. [[1,4],[3,2],[3,1]] → [[1,3,3],[4,2,1]]
 ε    }              # Map each to:
  W                  #  Push the smallest value (without popping the list)
                     #   i.e. [[1,3,3],[4,2,1]] → [1,1]
   s                 #  Swap so the list is at the top of the stack again
    à                #  Pop the list and push the largest value
                     #   i.e. [[1,3,3],[4,2,1]] → [3,4]
     Ÿ               #  Take the inclusive range of the min and max
                     #   i.e. [[1,2,3],[1,2,3,4]]
`                    # After the map, push both lists separated to the stack
 â                   # And take the cartesian product of the two lists
                     #  i.e. [[1,2,3],[1,2,3,4]]
                     #   → [[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[2,4],[3,1],[3,2],[3,3],[3,4]]
  ε             }    # Map each pair to:
   U                 #  Pop and store the current value in variable `X`
    I                #  Push the input
     ε     }         #  Map each pair in the input to:
      X              #   Push variable `X`
       -             #   Subtract it from the current pair
                     #    i.e. [3,2] - [1,3] → [2,-1]
        n            #   Take the square of each
                     #    i.e. [2,-1] → [4,1]
         O           #   Sum the lists
                     #    i.e. [4,1] → 5
          t          #   Take the square-root of each
                     #    i.e. 5 → 2.23606797749979
            à        #  Pop the converted list, and push its largest value
                     #   i.e. [[3.0,2.23606797749979,2.0],[2.0,2.0,2.23606797749979],...,[2.0,2.0,3.0]]
                     #    → [3.0,2.23606797749979,...,3.0]
             î       #  Round it up
                     #   i.e. [3.0,2.23606797749979,...,3.0] → [3.0,3.0,3.0,4.0,4.0,3.0,3.0,4.0,4.0,3.0,3.0,3.0]
              X     #  Pair it with variable `X`
                     #   i.e. [[3.0,[1,1]],[3.0,[1,2]],...,[3.0,[3,4]]]
                 {   # After the map, sort the list
                  н  # And take the first item (which is output implicitly)
                     #  i.e. [[3.0,[1,1]],[3.0,[1,2]],...,[3.0,[3,4]]] → [3.0,[1,1]]

2

Matlab, 73 bytes

function g(x);[r,~,d]=fminimax(@(a)pdist2(x,a),[0 0]);[round(r) ceil(d)]

Basta encontrar a menor solução (ponto flutuante) e arredondar para o ponto mais próximo e limitar o raio (pior caso para o problema minimax). Não sei ao certo se isso gera a solução correta para todos os casos possíveis (dentro da precisão), mas para os casos de teste deve funcionar (se eu não cometer um erro de digitação).

Ligue com

g([1 4;3 2;4 1;4 5;5 2;7 4])

(0,0),(1,1)fminimax(0.5,0.5)(1,1)2/21(0,0)

Você está correto, mas a saída do fminimax é [0.500000211699422 0.499999788525202], portanto, ela arredonda corretamente. Então, eu tenho sorte aqui. Atualmente, estou pensando em como contornar esse problema (como ele funciona apenas por pura sorte).
Jonas

2

Pitão , 34 33 bytes

hSm+.EeSm@s^R2-Vdk2Qd*Fm}FhM_BSdC

A saída está no formato [R,x,y]

Experimente online aqui ou verifique todos os casos de teste de uma vez aqui .

hSm+.EeSm@s^R2-Vdk2Qd*Fm}FhM_BSdCQ   Implicit: Q=eval(input())
                                     Trailing Q inferred
                                CQ   Transpose (group x and y coordinates separately)
                       m             Map each in the above, as d, using:
                              Sd       Sort d
                            _B         Pair with its own reverse
                          hM           Take the first element of each, yielding [min, max]
                        }F             Generate inclusive range
                     *F              Cartesian product of the above two lists, yielding all coordinates in range
  m                                  Map each coordinate in the above, as d, using:
        m          Q                   Map each coordinate in input, as k, using:
              -Vdk                       Take the difference between x and y coordinates in d and k
           ^R2                           Square each
          s                              Sum
         @        2                      Take the square root
      eS                               Take the largest of the result
    .E                                 Rounded up
   +                d                  Prepend to d
 S                                   Sort the result, first element as most significant
h                                    Take first element

Editar: salvou um byte reorganizando o formato de saída, versão anterior:

heDm+d.EeSm@s^R2-Vdk2Q*Fm}FhM_BSdC


2

Wolfram Language (Mathematica) , 66 bytes

Aqui está uma abordagem de força bruta. Eu considerei a BoundingRegion[#,"MinDisk"]&função muito mais curta , mas não há como forçar coordenadas e raios inteiros.

Minimize[{r,RegionWithin[{x,y}~Disk~r,Point@#]},{x,y,r},Integers]&

Experimente online!


Agradável. Mas que tal {Round@#[[1]], Ceiling@#[[2]]} &@BoundingRegion[#, "MinDisk"]&?
7268

@ DavidDC, o arredondamento do centro pode movê-lo em até Sqrt [2] /2=.707, mas assumir o teto não necessariamente adiciona comprimento suficiente ao raio para neutralizar isso. Eu acho que um exemplo dessa falha seria apenas os dois pontos {{0,0}, {11,11}} #
Kelly Lowder

Eu vejo o que você quer dizer!
9788

2

Java 10, 283 279 277 257 bytes

C->{int M=1<<31,m=M,X=M,Y=M,x=M-1,y=x,t,a,b,r[]={x};for(var c:C){x=(t=c[0])<x?t:x;X=t>X?t:X;y=(t=c[1])<y?t:y;Y=t>Y?t:Y;}for(;y<=Y;y++)for(t=x;t<=X;r=m<r[0]?new int[]{m,t,y}:r,m=M,t++)for(var c:C){a=c[0]-t;b=c[1]-y;a*=a;m=(a=(int)Math.ceil(Math.sqrt(a+=b*=b)))>m?a:m;}return r;}

-20 bytes graças à dica de uso do @nwellnhofMath.hypot .

A matriz de resultados está na ordem [R,X,Y].

Experimente online.

Explicação:

C->{                  // Method with 2D int-array as parameter & int-array as return-type
  int M=1<<31,        //  Minimum `M`, starting at -2,147,483,648
      m=M,            //  Temp integer, starting at -2,147,483,648 as well
      X=M,            //  Largest X coordinate, starting at -2,147,483,648 as well
      Y=M,            //  Largest Y coordinate, starting at -2,147,483,648 as well
      x=M-1,          //  Smallest X coordinate, starting at 2,147,483,647
      y=x,            //  Smallest Y coordinate, starting at 2,147,483,647 as well
      t,a,            //  Temp integers, starting uninitialized
      r[]={x};        //  Result-array, starting at one 2,147,483,647
  for(var c:C){       //  Loop over the input-coordinates
    x=(t=c[0])<x?t:x; //   If the X coordinate is smaller than `x`, change it
    X=t>X?t:X;        //   If the X coordinate is larger than `X`, change it
    y=(t=c[1])<y?t:y; //   If the Y coordinate is smaller than `y`, change it
    Y=t>Y?t:Y;}       //   If the Y coordinate is larger than `Y`, change it
 for(;y<=Y;y++)       //  Loop `y` in the range [`y`,`Y`]:
   for(t=x;t<=X       //   Inner loop `t` in the range [`x`,`X`]:
          ;           //     After every iteration:
           r=m<r[0]?  //      If `m` is smaller than the first value:
              new int[]{m,t,y}
                      //       Replace the result with `m,t,y`
             :        //      Else:
              r,      //       Leave `r` unchanged
           m=M,       //      Reset `m` to -2,147,483,648 for the next iteration
           t++)       //      And increase `t` by 1
     for(var c:C)     //    Inner loop over the input-coordinates
       m=(a=(int)Math.ceil(Math.hypot(c[0]-t,c[1]-y)))
                      //     Subtract `t` from the X coordinate;
                      //     subtract `y` from the Y coordinate;
                      //     take the hypot (<- sqrt(x*x+y*y)) of those
                      //     ceil it
                      //     And set `a` to this value
          >m?         //     If `a` is larger than `m`:
           a          //      Set `m` to `a`
          :           //     Else:
           m;         //      Leave `m` unchanged
  return r;}          //  Return the result `r`

1
Você pode salvar pelo menos 8 bytes com Math.hypot.
Nwellnhof 7/11

@nwellnhof Ah, esqueci completamente Math.hypot, o que é perfeito para esse desafio! -20 bytes ali. Obrigado. :)
Kevin Cruijssen

1

Javascript, 245 bytes

a=>{[b,c,d,e]=a.reduce(([j,k,l,m],[h,i])=>[j>h?j:h,k<h?k:h,l>i?l:i,m<i?m:i],[,,,,]);for(f=c;f<b;f++){for(g=e;g<d;g++){s=a.reduce((o,[p,q])=>o>(r=(p-f)**2+(q-g)**2)?o:r);n=n?n[2]>s?[f,g,s]:n:[f,g,s]}}return [n[0],n[1],Math.ceil(Math.sqrt(n[2]))]}

Versão (mais ou menos) mais legível:

a=>{
    [b,c,d,e]=a.reduce(([j,k,l,m],[h,i])=>[j>h?j:h,k<h?k:h,l>i?l:i,m<i?m:i],[,,,,]);
    for(f=c;f<b;f++){
        for(g=e;g<d;g++){
            s=a.reduce((o,[p,q])=>o>(r=(p-f)**2+(q-g)**2)?o:r);
            n=n?n[2]>s?[f,g,s]:n:[f,g,s]
        }
    }
    return [n[0],n[1],Math.ceil(Math.sqrt(n[2]))]
}

Apenas encontra a caixa delimitadora e testa cada coordenada nessa caixa para saber se é a melhor.

Eu poderia salvar 8 bytes com uma resposta aproximada, substituindo:

Math.ceil(Math.sqrt(n[2])) com ~~(n[2]+1-1e-9)


Com certeza há mais coisas para jogar golfe, mas JS não é minha suíte forte. Ainda assim, você pode golfe for(f=c;f<b;f++){for(g=e;g<d;g++){s=a.reduce((o,[p,q])=>o>(r=(p-f)**2+(q-g)**2)?o:r);n=n?n[2]>s?[f,g,s]:n:[f,g,s]}}para for(f=c;f<b;f++)for(g=e;g<d;n=n?n[2]>s?[f,g,s]:n:[f,g,s],g++)s=a.reduce((o,[p,q])=>o>(r=(p-f)**2+(q-g)**2)?o:r);. E eu tenho certeza que você pode remover o espaço em return[.
Kevin Cruijssen 6/11

1
Você provavelmente pode salvar alguns bytes usando Math.hypot.
Nwellnhof 7/11

1

Ruby , 113 bytes

->l{a=l.flatten;(z=*a.min..a.max).product(z).map{|x,y|[l.map{|u,v|(((x-u)**2+(y-v)**2)**0.5).ceil}.max,x,y]}.min}

Experimente online!


1

Carvão , 65 bytes

≔Eθ§ι¹ζ≔Eθ§ι⁰ηF…·⌊η⌈ηF…·⌊ζ⌈ζ⊞υ⟦ικ⟧≔Eυ⌈EθΣEιX⁻§λξν²ηI§υ⌕η⌊ηI⌈X⌊η·⁵

Experimente online! Link é a versão detalhada do código. Explicação:

≔Eθ§ι¹ζ

Obtenha as coordenadas y em z.

≔Eθ§ι⁰η

Obtenha as coordenadas x em h.

F…·⌊η⌈ηF…·⌊ζ⌈ζ⊞υ⟦ικ⟧

Passe pelos intervalos inclusivos, dos mínimos aos máximos he zgerando a lista de todos os potenciais centros de disco.

≔Eυ⌈EθΣEιX⁻§λξν²η

Faça um loop sobre todos os centros do disco, depois faça um loop sobre todos os pontos originais e, em seguida, faça um loop sobre as duas coordenadas, subtraia, quadrado, soma, obtenha o máximo e salve a lista resultante.

I§υ⌕η⌊η

Encontre a posição do diâmetro máximo mínimo e imprima o centro do disco correspondente.

I⌈X⌊η·⁵

Imprima o diâmetro máximo mínimo, mas arredonde-o para o próximo número inteiro.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.