Disco entero más pequeño

23

Este desafío consiste en encontrar el disco más pequeño que contenga algunos puntos dados. Sin embargo, esto se hace algo más complicado por el hecho de que en este desafío, las coordenadas y el radio del disco deben ser enteros.

Su entrada será una lista de puntos con coordenadas enteras xy y. Puede tomar esto como una lista de tuplas, una lista de listas o cualquier otra forma de representar una colección de pares. xy yambos serán enteros (posiblemente negativos). Se garantiza que cada punto sea único, y habrá al menos un punto.

Su salida será un disco en forma de tres números, X, Y, y R. X, YY Rson todos los enteros, Xy Yrepresentan el centro del disco y Rrepresenta su radio. La distancia entre cada punto dado y el centro debe ser menor o igual que R, y no debe existir un disco con un tamaño menor Rque también satisfaga esta condición.

Es posible que haya múltiples soluciones posibles para una entrada dada, su código debe generar al menos una de ellas en este caso.

Puede usar cualquier tipo de geometría incorporada que su lenguaje admita si las hay, y la entrada / salida puede ser a través de objetos de punto / disco integrados en lugar de solo números.

Casos de prueba

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)

Pocos bytes ganan.

Pavel
fuente
Sandbox
Pavel
Encontrado un par de errores tipográficos, si no le importa que señalándolos: "Esto es un poco engañar i er ..."; "... representa el centro del disco y R representa i t s radio ..."; "... y no debe existir tal disco ..."
J. Sallé
2
Por lo general, hacer las cosas enteras solo hace que el golf de código sea más fácil.
user202729
@KevinCruijssen Eso es una coincidencia. Las entradas pueden estar en cualquier orden.
Pavel
1
@Pavel ¿La entrada puede estar en cualquier orden, o podemos tomar la entrada en cualquier orden? Como en, la entrada puede estar en cualquier orden y deberíamos ordenar manualmente primero en nuestra solución, ¿o ya podemos tomar la entrada previamente ordenada?
Kevin Cruijssen

Respuestas:

6

Jalea , 25 24 22 21 20 18 bytes

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

Gracias a @EriktheOutgolfer por informarme sobre cómo )guardar 1 byte.

Gracias a @Dennis por guardar 2 bytes.

Pruébalo en línea!

Explicación

«/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]]
PurkkaKoodari
fuente
@ Dennis Gracias! ¿Desde cuándo la vectorización de Jelly repite la lista más corta, o estoy malinterpretando la eliminación de ?
PurkkaKoodari
Las profundidades se corresponden primero. Si tiene un par y una matriz de pares, el par se empareja con todos los pares.
Dennis
8

Brachylog v2, 19 bytes

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

Pruébalo en línea!

Este programa fue fácil de escribir, Brachylog es casi perfecto para este tipo de problema, pero difícil de jugar. No me sorprendería si hubiera un byte guardado en algún lugar aquí, ya que pocas cosas que hice parecían tener algún efecto (y contiene instrucciones de mapa anidadas, normalmente una señal de que debería estar usando member / findall, pero no puedo ver una forma de hacerlo).

Esta es una presentación de función. La entrada es del argumento izquierdo a la función en el formato [[x,y],[x,y],…], la salida del argumento derecho en el formulario [r,[[x,y]]]. (Si desea probar números negativos en la entrada, tenga en cuenta que Brachylog usa _para el signo menos, no -. Esto es confuso porque la función → envoltura completa del programa con la que se entrega Brachylog, solicitada usando el argumento de la línea de comandos Z, presentará números negativos en la salida con un signo menos regular).

Explicación

;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.

Esto es interesante porque le estamos pidiendo a Brachylog que encuentre un valor de ciertas propiedades (en este caso, el radio de un disco centrado en el punto Aque se ajusta a todos los puntos de entrada), pero casi no tenemos ningún requisito (todo lo que necesitamos es que el radio es un número). Sin embargo, Brachylog calculará internamente el radio en cuestión simbólicamente en lugar de tratar de usar números concretos, por lo que cuando se alcanza el final , logra dos cosas a la vez: primero, asegura que solo se usen números enteros para las coordenadas del Aradio y (obligando al radio al cuadrado a ser un número cuadrado, y explicando el uso de ≤ᵛpara encontrar un "máximo o mayor"); segundo, encuentra el radio viable más pequeño posible (ya que el radio viene primero en la salida).

Una cosa que no se especifica en el programa es que todos los puntos se miden contra el mismo centro de un disco; como está escrito, no hay restricciones de que no usemos un centro diferente para cada punto. Sin embargo, el orden de desempate (que en este caso se establece por el tercero , y que como una restricción de estructura se evaluará antes de que la restricción de valor implícita ) quiera Aser lo más corto posible (es decir, un solo elemento, entonces usamos el mismo centrar cada vez; Aprimero intenta una longitud cero, pero eso obviamente no funciona, por lo que intenta una lista singleton a continuación). Como resultado, terminamos obteniendo una restricción útil (que solo tenemos un disco) "gratis".

Esta solución pasa a generalizarse a cualquier cantidad de dimensiones , sin cambios en el código fuente; No hay suposiciones aquí de que las cosas son bidimensionales. Entonces, si necesita la esfera entera más pequeña, también puede tenerla.

ais523
fuente
3

Perl 6 , 81 bytes

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

Pruébalo en línea!

Toma una lista de puntos como listas de 2 elementos ((X1, Y1), (X2, Y2), ...). Devuelve una lista (R, (X, Y)). Utiliza el mismo enfoque que la respuesta Jelly de Pietu1998:

[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.

El minmaxmétodo es útil aquí ya que devuelve a Range. El producto cartesiano de rangos produce directamente todos los puntos con coordenadas enteras.

nwellnhof
fuente
2

05AB1E , 26 bytes

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

Puerto de la respuesta Jelly de @ Pietu1998 .

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

ø                    # 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]]
Kevin Cruijssen
fuente
2

Matlab, 73 bytes

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

Simplemente encuentre la solución más pequeña (punto flotante) y redondee al punto más cercano y limite el radio (el peor de los casos para el problema minimax). No estoy seguro si eso proporciona la solución correcta para todos los casos posibles (dentro de la precisión), pero para los casos de prueba debería funcionar (si no cometí un error de tipeo).

Llámalo con

g([1 4;3 2;4 1;4 5;5 2;7 4])
Jonas
fuente
(0,0),(1,1)fminimax(0.5,0.5)(1,1)2/21(0,0)
Tiene razón, pero la salida de fminimax es [0.500000211699422 0.499999788525202], por lo que se redondea correctamente. Entonces tengo suerte aquí. Actualmente estoy pensando cómo evitar este problema (ya que solo funciona por pura suerte).
Jonas
2

Pyth , 34 33 bytes

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

La salida está en forma [R,x,y]

Pruébelo en línea aquí , o verifique todos los casos de prueba a la vez aquí .

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: guardado un byte reorganizando el formato de salida, versión anterior:

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

Sok
fuente
2

Wolfram Language (Mathematica) , 66 bytes

Aquí hay un enfoque de fuerza bruta. Consideré la BoundingRegion[#,"MinDisk"]&función mucho más corta , pero no hay forma de forzar coordenadas y radios enteros.

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

Pruébalo en línea!

Kelly Lowder
fuente
Agradable. Pero, ¿qué tal {Round@#[[1]], Ceiling@#[[2]]} &@BoundingRegion[#, "MinDisk"]&?
DavidC
@DavidC, el redondeo del centro podría moverlo hasta Sqrt [2] /2=.707, pero tomar el techo no necesariamente agregará suficiente longitud al radio para contrarrestar eso. Creo que un ejemplo de ese fracaso sería solo los dos puntos {{0,0}, {11,11}}
Kelly Lowder
¡Veo a que te refieres!
DavidC
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 gracias a la sugerencia de uso de @nwellnhofMath.hypot .

La matriz de resultados está en el orden [R,X,Y].

Pruébalo en línea.

Explicación:

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`
Kevin Cruijssen
fuente
1
Puede guardar al menos 8 bytes con Math.hypot.
nwellnhof el
@nwellnhof Ah, se olvidó por completo Math.hypot, ¡lo cual es perfecto para este desafío! -20 bytes justo allí. Gracias. :)
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]))]}

(Algo) versión más legible:

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]))]
}

Simplemente encuentra el cuadro delimitador y prueba cada coordenada en ese cuadro para ver si es la mejor.

Podría ahorrar 8 bytes con una respuesta aproximada, reemplazando:

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

Spitemaster
fuente
Seguramente hay más cosas para jugar al golf, pero JS no es mi suite fuerte. Aún así, se puede jugar golf 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]}}a 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);. Y estoy bastante seguro de que puedes eliminar el espacio en return[.
Kevin Cruijssen
1
Probablemente pueda guardar algunos bytes usando Math.hypot.
nwellnhof el
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}

Pruébalo en línea!

GB
fuente
1

Carbón , 65 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

≔Eθ§ι¹ζ

Obtenga las coordenadas y en z.

≔Eθ§ι⁰η

Obtenga las coordenadas x en h.

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

Recorra los rangos inclusivos desde los mínimos hasta los máximos hy zgenere la lista de todos los centros de discos potenciales.

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

Pase por todos los centros de disco, luego pase por todos los puntos originales, luego pase por ambas coordenadas, reste, cuadre, sume, tome el máximo y guarde la lista resultante.

I§υ⌕η⌊η

Encuentre la posición del diámetro máximo mínimo e imprima el centro del disco correspondiente.

I⌈X⌊η·⁵

Imprima el diámetro máximo mínimo, pero redondee al siguiente número entero.

Neil
fuente