Disque entier le plus petit

23

Ce défi consiste à trouver le plus petit disque contenant des points donnés. Ceci est rendu quelque peu plus délicat, cependant, par le fait que dans ce défi, les coordonnées et le rayon du disque doivent tous deux être des entiers.

Votre entrée sera une liste de points avec des coordonnées entières xet y. Vous pouvez prendre cela comme une liste de tuples, une liste de listes ou toute autre manière de représenter une collection de paires. xet yseront tous deux (éventuellement négatifs) des entiers. Chaque point est garanti unique et il y aura au moins un point.

Votre sortie sera un disque sous la forme de trois numéros, X, Y, et R. X,, Yet Rsont tous des entiers, Xet Yreprésentent le centre du disque et Rson rayon. La distance entre chaque point donné et le centre doit être inférieure ou égale à R, et il ne doit pas exister un tel disque avec un plus petit Rqui remplisse également cette condition.

Il est possible qu'il y ait plusieurs solutions possibles pour une entrée donnée, votre code doit en sortir au moins une dans ce cas.

Vous pouvez utiliser n'importe quel type de géométrie intégré dans votre langage s'il en existe, et l'entrée / sortie peut se faire via des objets point / disque intégrés au lieu de simples nombres.

Cas de test

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)

Le moins d'octets gagne.

Pavel
la source
Sandbox
Pavel
J'ai trouvé quelques fautes de frappe, si cela ne vous dérange pas de les signaler: "C'est un peu compliqué i er ..."; « ... représente le centre du disque et R représente i t rayon de ... »; "... et il ne doit pas exister un tel disque ..."
J. Sallé
2
Habituellement, rendre les choses entières facilite le code-golf.
user202729
@KevinCruijssen C'est par hasard. Les entrées peuvent être dans n'importe quel ordre.
Pavel
1
@Pavel L'entrée peut être dans n'importe quel ordre, ou nous pouvons prendre l'entrée dans n'importe quel ordre? Comme dans, l'entrée peut être dans n'importe quel ordre et nous devons d'abord trier manuellement dans notre solution, ou pouvons-nous déjà prendre l'entrée pré-triée?
Kevin Cruijssen

Réponses:

6

Gelée , 25 24 22 21 20 18 octets

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

Merci à @EriktheOutgolfer de m'avoir informé de la )sauvegarde de 1 octet.

Merci à @Dennis d'avoir économisé 2 octets.

Essayez-le en ligne!

Explication

«/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
la source
@Dennis Merci! Depuis quand la vectorisation de Jelly a-t-elle répété la liste la plus courte, ou ai-je mal interprété la suppression de ?
PurkkaKoodari
Les profondeurs sont adaptées en premier. Si vous une paire et un tableau de paires, la paire est appariée avec toutes les paires.
Dennis
8

Brachylog v2, 19 octets

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

Essayez-le en ligne!

Ce programme était facile à écrire - Brachylog est presque parfait pour ce genre de problème - mais difficile à jouer au golf. Cela ne me surprendrait pas si un octet était enregistré quelque part ici, car peu de choses que j'ai faites semblaient avoir un effet (et il contient des instructions de carte imbriquées, normalement un signe que vous devriez utiliser member / findall, mais je ne peux pas voir un moyen de le faire).

Ceci est une soumission de fonction. L'entrée est de l'argument gauche à la fonction dans le format [[x,y],[x,y],…], sortie de l'argument droit dans le formulaire [r,[[x,y]]]. (Si vous voulez essayer des nombres négatifs dans l'entrée, notez que Brachylog utilise _pour le signe moins, non -. C'est déroutant car la fonction → le wrapper de programme complet fourni avec Brachylog, demandé à l'aide de l'argument de ligne de commande Z, présentera des nombres négatifs dans la sortie avec un signe moins régulier.)

Explication

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

Ceci est intéressant dans la mesure où nous demandons à Brachylog de trouver une valeur de certaines propriétés (dans ce cas, le rayon d'un disque centré au point Aqui correspond à tous les points d'entrée), mais nous n'y plaçons pratiquement aucune exigence (tout ce dont nous avons besoin est que le rayon est un nombre). Cependant, Brachylog calculera en interne le rayon en question de manière symbolique plutôt que d'essayer d'utiliser des nombres concrets, donc lorsque la finale est atteinte, il accomplit deux choses à la fois: tout d'abord, il garantit que seuls des entiers sont utilisés pour les coordonnées de Aet pour le rayon (forçant le rayon carré à être un nombre carré, et expliquant l'utilisation de ≤ᵛpour trouver un "maximum ou plus"); deuxièmement, il trouve le plus petit rayon viable possible (car le rayon vient en premier dans la sortie).

Une chose qui n'est pas du tout spécifiée dans le programme est que tous les points sont mesurés par rapport au même centre d'un disque; comme écrit, il n'y a aucune contrainte que nous n'utilisons pas un centre différent pour chaque point. Cependant, l'ordre de départage (qui dans ce cas est défini par le troisième , et qui en tant que contrainte de structure sera évalué avant la contrainte de valeur impliquée par ) veutA être aussi court que possible (c'est-à-dire un seul élément, nous utilisons donc le même centre à chaque fois; il essaie d'abord une longueur nulle Amais cela ne fonctionne évidemment pas, il essaie donc une liste singleton ensuite). En conséquence, nous finissons par obtenir une contrainte utile (que nous n'avons qu'un seul disque) "gratuitement".

Cette solution arrive à généraliser à n'importe quel nombre de dimensions , sans aucune modification du code source; il n'y a pas d'hypothèse ici que les choses sont bidimensionnelles. Donc, si vous avez besoin de la plus petite sphère entière, vous pouvez aussi l'avoir.

ais523
la source
3

Perl 6 , 81 octets

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

Essayez-le en ligne!

Prend une liste de points sous forme de listes à 2 éléments ((X1, Y1), (X2, Y2), ...). Renvoie une liste (R, (X, Y)). Utilise la même approche que la réponse 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.

La minmaxméthode est utile ici car elle renvoie a Range. Le produit cartésien des plages donne directement tous les points avec des coordonnées entières.

nwellnhof
la source
2

05AB1E , 26 octets

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

Réponse de Jelly du port de @ Pietu1998 .

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

ø                    # 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
la source
2

Matlab, 73 octets

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

Trouvez simplement la plus petite solution (virgule flottante) et arrondissez au point le plus proche et plafonnez le rayon (pire cas pour le problème minimax). Je ne sais pas avec certitude si cela donne la solution correcte pour tous les cas possibles (dans la précision), mais pour les cas de test, cela devrait fonctionner (si je n'ai pas fait d'erreur de frappe).

Appelez-le avec

g([1 4;3 2;4 1;4 5;5 2;7 4])
Jonas
la source
(0,0),(1,1)fminimax(0.5,0.5)(1,1)2/21(0,0)
Vous avez raison, mais la sortie de fminimax est [0,500000211699422 0,499999788525202], donc elle arrondit correctement. J'ai donc de la chance ici. Je réfléchis actuellement à la façon de contourner ce problème (car cela ne fonctionne que par pure chance).
Jonas
2

Pyth , 34 33 octets

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

La sortie est sous la forme [R,x,y]

Essayez-le en ligne ici ou vérifiez tous les cas de test en même temps ici .

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

Edit: enregistrement d'un octet en réorganisant le format de sortie, version précédente:

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

Sok
la source
2

Wolfram Language (Mathematica) , 66 octets

Voici une approche par force brute. J'ai considéré la BoundingRegion[#,"MinDisk"]&fonction beaucoup plus courte mais il n'y a aucun moyen de forcer les coordonnées entières et le rayon.

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

Essayez-le en ligne!

Kelly Lowder
la source
Agréable. Mais qu'en est-il {Round@#[[1]], Ceiling@#[[2]]} &@BoundingRegion[#, "MinDisk"]&?
DavidC
@DavidC, l'arrondi du centre peut le déplacer jusqu'à Sqrt [2] /2=.707 mais prendre le plafond n'ajoutera pas nécessairement suffisamment de longueur au rayon pour contrer cela. Je pense qu'un exemple de cet échec serait juste les deux points {{0,0}, {11,11}}
Kelly Lowder
Je vois ce que tu veux dire!
DavidC
2

Java 10, 283 279 277 257 octets

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 octets grâce à @nwellnhof la pointe de » l' utilisation Math.hypot.

Le tableau de résultats est dans l'ordre [R,X,Y].

Essayez-le en ligne.

Explication:

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
la source
1
Vous pouvez enregistrer au moins 8 octets avec Math.hypot.
nwellnhof
@nwellnhof Ah, complètement oublié Math.hypot, ce qui est parfait pour ce défi! -20 octets juste là. Merci. :)
Kevin Cruijssen
1

Javascript, 245 octets

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

Version (un peu) plus lisible:

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

Recherche simplement la boîte englobante et teste chaque coordonnée dans cette boîte pour savoir si elle est la meilleure.

Je pourrais économiser 8 octets avec une réponse approximative, en remplaçant:

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

Spitemaster
la source
Il y a certainement plus de choses au golf, mais JS n'est pas ma suite forte. Pourtant, vous pouvez jouer 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]}}au golf 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);. Et je suis sûr que vous pouvez supprimer l'espace à return[.
Kevin Cruijssen
1
Vous pouvez probablement enregistrer quelques octets en utilisant Math.hypot.
nwellnhof
1

Rubis , 113 octets

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

Essayez-le en ligne!

GB
la source
1

Fusain , 65 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

≔Eθ§ι¹ζ

Obtenez les coordonnées y z.

≔Eθ§ι⁰η

Obtenez les coordonnées x dans h .

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

Boucle sur les plages inclusives des minimums aux maximums de hetz générer la liste de tous les centres de disques potentiels.

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

En boucle sur tous les centres du disque, puis en boucle sur tous les points d'origine, puis en boucle sur les deux coordonnées, soustrayez, placez, additionnez, prenez le maximum et enregistrez la liste résultante.

I§υ⌕η⌊η

Trouvez la position du diamètre maximal minimal et imprimez le centre du disque correspondant.

I⌈X⌊η·⁵

Imprimez le diamètre maximal minimal, mais arrondissez-le au nombre entier suivant.

Neil
la source