Disco intero più piccolo


23

Questa sfida riguarda la ricerca del disco più piccolo che contiene alcuni punti. Ciò è reso in qualche modo più complicato dal fatto che, in questa sfida, le coordinate e il raggio del disco devono essere entrambi numeri interi.

Il tuo input sarà un elenco di punti con coordinate intere xe y. Puoi prenderlo come un elenco di tuple, un elenco di elenchi o qualsiasi altro modo per rappresentare una raccolta di coppie. xe ysaranno entrambi numeri interi (possibilmente negativi). Ogni punto è garantito per essere unico e ci sarà almeno un punto.

L'output sarà un disco sotto forma di tre numeri, X, Y, e R. X, YE Rsono tutti numeri interi, Xe Yrappresentano il centro del disco e Rrappresentano il suo raggio. La distanza tra ogni dato punto e il centro deve essere inferiore o uguale a R, e non deve esistere un tale disco con un disco più piccolo Rche soddisfi anche questa condizione.

È possibile che ci siano più possibili soluzioni per un determinato input, in questo caso il tuo codice deve generare almeno uno di essi.

Puoi usare qualsiasi tipo di geometria incorporata dal tuo linguaggio se ce ne sono, e l'input / output può avvenire attraverso oggetti punto / disco incorporati anziché solo numeri.

Casi 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)

Vince il minor numero di byte.



Trovato un paio di errori di battitura, se non ti dispiace me li sottolineando: "Questo è reso un po 'ingannare i er ..."; "... rappresenta il centro del disco e R rappresenta i t raggio s ..."; "... e non deve esistere un tale disco ..."
J. Sallé il

2
Solitamente rendere le cose intere semplifica il code-golf.
user202729

@KevinCruijssen Questo è un caso. Gli input possono essere in qualsiasi ordine.
Pavel

1
@Pavel L'input può essere in qualsiasi ordine o possiamo prendere l'input in qualsiasi ordine? Come in, l'input può essere in qualsiasi ordine e dovremmo ordinare prima manualmente nella nostra soluzione, oppure possiamo già prendere l'input preordinato?
Kevin Cruijssen,

Risposte:


6

Gelatina , 25 24 22 21 20 18 byte

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

Grazie a @EriktheOutgolfer per avermi informato ), risparmiando 1 byte.

Grazie a @Dennis per aver salvato 2 byte.

Provalo online!

Spiegazione

«/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 Grazie! Da quando la vettorializzazione di Jelly ha ripetuto l'elenco più breve o sto interpretando male la rimozione di ?
PurkkaKoodari,

Le profondità vengono prima abbinate. Se hai una coppia e un array di coppie, la coppia viene abbinata a tutte le coppie.
Dennis,

8

Brachylog v2, 19 byte

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

Provalo online!

Questo programma è stato facile da scrivere - Brachylog è quasi perfetto per questo tipo di problema - ma difficile da golf. Non mi sorprenderebbe se ci fosse un byte che salva da qualche parte qui, poiché poche cose che ho fatto sembravano avere alcun effetto (e contiene istruzioni sulla mappa nidificate, normalmente un segno che dovresti usare member / findall, ma non posso vedere un modo per farlo).

Questa è una presentazione di funzione. L'input è dall'argomento sinistro alla funzione nel formato [[x,y],[x,y],…], l'output dall'argomento destro nel modulo [r,[[x,y]]]. (Se si desidera provare numeri negativi nell'input, si noti che Brachylog utilizza _per il segno meno, non -. Ciò è fonte di confusione perché la funzione → wrapper di programma completo con cui viene fornito Brachylog, richiesta utilizzando l'argomento della riga di comando Z, presenterà numeri negativi in uscita con un normale segno meno.)

Spiegazione

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

Questo è interessante in quanto stiamo chiedendo a Brachylog di trovare un valore di determinate proprietà (in questo caso, il raggio di un disco centrato nel punto Ache si adatta a tutti i punti di input), ma difficilmente poniamo alcun requisito su di esso (tutto ciò di cui abbiamo bisogno è che il raggio è un numero). Tuttavia, Brachylog calcolerà internamente il raggio in questione simbolicamente anziché cercare di usare numeri concreti, quindi quando viene raggiunto il finale , compie due cose contemporaneamente: in primo luogo, assicura che vengano utilizzati solo numeri interi per le coordinate di Ae per il raggio (forzando il raggio quadrato ad essere un numero quadrato e spiegando l'uso di ≤ᵛper trovare un "massimo o maggiore"); in secondo luogo, trova il raggio possibile più piccolo possibile (poiché il raggio viene prima nell'output).

Una cosa che non è affatto specificata nel programma è che tutti i punti sono misurati sullo stesso centro di un disco; come scritto, non ci sono vincoli che non usiamo un centro diverso per ogni punto. Tuttavia, l'ordine di tiebreak (che in questo caso è impostato dal terzo e che come vincolo di struttura verrà valutato prima del vincolo di valore implicito da ) vuole Aessere il più breve possibile (ovvero un singolo elemento, quindi utilizziamo lo stesso ogni volta al centro; prima prova una lunghezza zero Ama ovviamente non funziona, quindi prova una lista singleton). Di conseguenza, otteniamo un vincolo utile (che abbiamo un solo disco) "gratis".

Questa soluzione si generalizza a qualsiasi numero di dimensioni , senza modifiche al codice sorgente; non ci sono ipotesi qui che le cose siano bidimensionali. Quindi, se ti capita di aver bisogno della sfera intera più piccola, puoi avere anche quella.


3

Perl 6 , 81 byte

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

Provalo online!

Prende un elenco di punti come elenchi a 2 elementi ((X1, Y1), (X2, Y2), ...). Restituisce un elenco (R, (X, Y)). Utilizza lo stesso approccio della risposta Jelly di 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.

Il minmaxmetodo è utile qui in quanto restituisce a Range. Il prodotto cartesiano degli intervalli produce direttamente tutti i punti con coordinate intere.


2

05AB1E , 26 byte

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

La risposta di Jelly al Port of @ Pietu1998 .

Provalo online o verifica tutti i casi di test .

Spiegazione:

ø                    # 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 byte

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

Basta trovare la soluzione più piccola (virgola mobile) e arrotondare al punto più vicino e cementare il raggio (caso peggiore per il problema minimax). Non so con certezza se questo fornisce la soluzione corretta per tutti i possibili casi (con precisione), ma per i casi di test dovrebbe funzionare (se non ho fatto un errore di battitura).

Chiamalo con

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)

Hai ragione, ma l'output di fminimax è [0.500000211699422 0.499999788525202], quindi viene arrotondato correttamente. Quindi sono fortunato qui. Attualmente sto pensando a come eludere questo problema (poiché funziona solo per pura fortuna).
Jonas,

2

Pyth , 34 33 byte

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

L'output è nella forma [R,x,y]

Provalo online qui o verifica tutti i casi di test contemporaneamente qui .

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

Modifica: salvato un byte riorganizzando il formato di output, versione precedente:

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


2

Wolfram Language (Mathematica) , 66 byte

Ecco un approccio alla forza bruta. Ho considerato la BoundingRegion[#,"MinDisk"]&funzione molto più breve ma non c'è modo di forzare coordinate e raggio interi.

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

Provalo online!


Bello. Ma che ne dici {Round@#[[1]], Ceiling@#[[2]]} &@BoundingRegion[#, "MinDisk"]&?
DavidC,

@DavidC, l'arrotondamento del centro potrebbe spostarlo fino a Sqrt [2] /2=.707, ma prendere il soffitto non aggiungerà necessariamente abbastanza lunghezza al raggio per contrastarlo. Penso che un esempio di questo fallimento sarebbero solo i due punti {{0,0}, {11,11}}
Kelly Lowder,

Capisco cosa vuoi dire!
DavidC,

2

Java 10, 283 279 277 257 byte

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 byte grazie al consiglio di utilizzo di @nwellnhofMath.hypot .

La matrice dei risultati è nell'ordine [R,X,Y].

Provalo online.

Spiegazione:

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
È possibile salvare almeno 8 byte con Math.hypot.
nwellnhof

@nwellnhof Ah, completamente dimenticato Math.hypot, perfetto per questa sfida! -20 byte proprio lì. Grazie. :)
Kevin Cruijssen,

1

Javascript, 245 byte

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

(Un po ') versione più leggibile:

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

Trova solo il rettangolo di selezione e verifica ogni coordinata in quella casella per verificare se sia la migliore.

Potrei salvare 8 byte con una risposta approssimativa, sostituendo:

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


Ci sono sicuramente più cose da golf, ma JS non è la mia suite forte. Tuttavia, puoi giocare 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 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);. E sono abbastanza sicuro che puoi rimuovere lo spazio in return[.
Kevin Cruijssen,

1
Probabilmente puoi salvare qualche byte usando Math.hypot.
nwellnhof

1

Rubino , 113 byte

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

Provalo online!


1

Carbone , 65 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Spiegazione:

≔Eθ§ι¹ζ

Ottieni le coordinate y in z.

≔Eθ§ι⁰η

Ottieni le coordinate x in h.

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

Scorri gli intervalli inclusivi dal minimo al massimo he zgenera l'elenco di tutti i potenziali centri disco.

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

Passa su tutti i centri del disco, quindi passa su tutti i punti originali, quindi passa su entrambe le coordinate, sottrai, piazza, somma, prendi il massimo e salva l'elenco risultante.

I§υ⌕η⌊η

Trova la posizione del diametro massimo minimo e stampa il centro del disco corrispondente.

I⌈X⌊η·⁵

Stampa il diametro massimo minimo, ma arrotondalo al numero intero successivo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.