最小整数ディスク


23

この課題は、特定のポイントを含む最小のディスクを見つけることです。ただし、この課題では、ディスクの座標と半径は両方とも整数でなければならないという事実により、これはやや複雑になります。

入力は、整数座標xとを持つ点のリストになりyます。これは、タプルのリスト、リストのリスト、またはペアのコレクションを表す他の方法として使用できます。xそして、y両方とも(おそらく負の)整数になります。すべてのポイントは一意であることが保証されており、少なくとも1つのポイントがあります。

あなたの出力は、3つの数字の形でディスクになりXYRXYおよびRすべての整数であり、XおよびYディスクの中心を表し、Rその半径を表します。与えられたすべての点と中心の間の距離はに等しいかそれ以下Rでなければならず、Rこの条件を満たしているより小さいディスクが存在してはなりません。

特定の入力に対して複数の可能な解決策がある可能性がありますが、この場合、コードは少なくとも1つを出力する必要があります。

言語がサポートしている場合は、言語でサポートされているあらゆる種類のジオメトリビルトインを使用できます。入力/出力は、単なる数字ではなく、組み込みのポイント/ディスクオブジェクトを介して行われます。

テストケース

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)

少ないバイトが勝ちます。



あなたがそれらを指摘私を気にしない場合は、カップルの誤植が見つかりました:「これはややトリック行われるIえー...」。「...ディスクの中心を表し、RはIを表し、T sの半径...」。「...そしてそこにはならない存在 ...、このようなディスクを」
J.サール

2
通常、物事を整数にするだけで、コードゴルフが簡単になります。
user202729

@KevinCruijssenそれは偶然です。入力は任意の順序にすることができます。
パベル

1
@Pavel入力任意の順序にすることができますか、または任意の順序で入力を取得できますか?同様に、入力は任意の順序にすることができ、ソリューションでは最初に手動でソートする必要がありますか、または事前にソートされた入力を取得できますか?
ケビンクルーイッセン

回答:


6

ゼリー25 24 22 21 20 18バイト

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

を知らせてくれた@EriktheOutgolferに感謝します。1 )バイト節約します。

2バイトを節約してくれた@Dennisに感謝します。

オンラインでお試しください!

説明

«/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]]

@デニスありがとう!Jellyのベクトル化はいつより短いリストを繰り返したのですか、それとも削除を誤解していますか?
PurkkaKoodari

深さが最初に一致します。ペアとペアの配列の場合、ペアはすべてのペアと一致します。
デニス

8

Brachylog v2、19バイト

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

オンラインでお試しください!

このプログラムは書くのが簡単でした– Brachylogはこの種の問題にはほぼ完璧です–しかし、ゴルフは難しいです。ここにバイトの保存があったとしても、私は何も効果がないように思えたので、それは驚くことではありません(そして、ネストされたマップ命令、通常はmember / findallを使用する必要があるというサインが含まれていますが、私はできませんそれを行う方法を参照してください)。

これは関数の提出です。入力は、左引数から形式の形式の関数へ[[x,y],[x,y],…]、出力は形式の右引数から[r,[[x,y]]]です。(入力で負の数を試したい場合は、Brachylog _がマイナス記号ではなく、マイナス記号に使用することに注意してください-。これは、コマンドライン引数を使用して要求される関数→Brachylogに付属する完全なプログラムラッパーがZ負の数を提示するため、混乱を招くことになります中出力定期的なマイナス記号付き)。

説明

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

これは、特定のプロパティの値(この場合、Aすべての入力ポイントに適合するポイントを中心とするディスクの半径)を見つけるようにBrachylogに要求しているという点で興味深いですが、要件はほとんどありません(必要なのは半径が数値であること)。ただし、Brachylogは、具体的な数値を使用しようとするのではなく、問題の半径を内部的にシンボリックに計算するため、最終に到達すると、一度に2つのことを実行します。最初に、整数のみがA半径と座標に使用される(平方半径を強制的に平方数にし≤ᵛ、「最大以上」を見つけるための使用法を説明します); 次に、可能な最小の実行可能な半径を見つけます(出力で半径が最初になるため)。

プログラムでまったく指定されていないことの1つは、すべてのポイントがディスクの同じ中心に対して測定されることです。書かれているように、各ポイントに異なる中心を使用しないという制約はありません。ただし、タイブレーク順序(この場合はthirdによって設定され、構造制約としてによって暗示される値制約の前に評価されます)はA、できるだけ短くしたい(つまり、単一の要素なので、同じものを使用します)毎回中央に配置します; A最初に長さゼロを試行しますが、それは明らかに機能しないので、次にシングルトンリストを試行します)。その結果、「無料」で有用な制約(ディスクが1つしかない)を取得することになります。

このソリューション、ソースコードに変更を加えることなく、任意の数の次元に一般化されます。ここでは、物事が2次元であるという仮定はありません。したがって、最小の整数球が必要な場合は、それも使用できます。


3

Perl 6、81バイト

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

オンラインでお試しください!

ポイントのリストを2要素リストとして受け取ります((X1, Y1), (X2, Y2), ...)。リストを返します(R, (X, Y))。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.

minmaxそれが返すような方法は、ここに便利ですRange。範囲のデカルト積は、整数座標を持つすべてのポイントを直接生成します。


2

05AB1E、26 バイト

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

@ Pietu1998のJelly回答のポート。

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

ø                    # 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バイト

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

単純に最小の解(浮動小数点)を見つけ、最も近い点に丸めて半径を制限します(ミニマックス問題の最悪の場合)。すべての可能性のあるケース(精度内)で正しい解が得られるかどうかはわかりませんが、テストケースでは機能します(入力エラーがなかった場合)。

で呼び出す

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

0011fminimax0.50.5112/2100

正しいですが、fminimaxの出力は[0.500000211699422 0.499999788525202]であるため、正しく丸められます。私はここでラッキーです。私は現在、この問題を回避する方法を考えています(それは純粋な運によってのみ機能するため)。
ジョナス

2

Pyth34 33バイト

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

出力は次の形式です [R,x,y]

ここでオンライン試すか、ここですべてのテストケースを一度に確認してください

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

編集:出力形式を変更してバイトを保存しました、以前のバージョン:

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


2

Wolfram言語(Mathematica)、66バイト

これがブルートフォースアプローチです。私はずっと短いBoundingRegion[#,"MinDisk"]&関数を考えましたが、整数座標と半径を強制する方法はありません。

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

オンラインでお試しください!


いいね しかし、どう{Round@#[[1]], Ceiling@#[[2]]} &@BoundingRegion[#, "MinDisk"]&ですか?
DavidC

@DavidC、中心の丸めにより最大でSqrt [2] /2=.707だけ移動する場合がありますが、天井をとることで半径に十分な長さが追加されるとは限りません。その失敗の例は、{{0,0}、{11,11}}の2点だけだと思います
ケリーロウ

意味がわかりました!
DavidC

2

Java 10、283 279 277 257バイト

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

使用の@nwellnhofのヒントのおかげで-20バイトMath.hypot

結果の配列の順序は[R,X,Y]です。

オンラインでお試しください。

説明:

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
で少なくとも8バイトを保存できますMath.hypot
-nwellnhof

@nwellnhofああ、Math.hypotこのチャレンジにぴったりのを完全に忘れてしまいました!そこに-20バイト。ありがとう。:)
ケビンクルーイッセン

1

Javascript、245バイト

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

(多少)より読みやすいバージョン:

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

境界ボックスを見つけて、そのボックス内の各座標が最適かどうかをテストします。

以下を置き換えることで、おおよその答えで8バイトを節約できます。

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


ゴルフにはもっと多くのものがありますが、JSは私の強力なスイートではありません。それでも、あなたはにゴルフ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]}}することができます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);。で、スペースを削除できると確信していますreturn[
ケビンクルーイッセン

1
おそらくを使用して数バイトを保存できますMath.hypot
nwellnhof


1

木炭、65バイト

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

オンラインでお試しください!リンクは、コードの詳細バージョンです。説明:

≔Eθ§ι¹ζ

y座標をに取得しzます。

≔Eθ§ι⁰η

X座標をに取得しhます。

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

最小値からの最大値を含めた範囲をループhし、zすべての潜在的なディスクセンターのリストを生成します。

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

すべてのディスク中心をループし、すべての元のポイントをループし、両方の座標をループし、減算、二乗、合計し、最大値を取り、結果のリストを保存します。

I§υ⌕η⌊η

最小の最大直径の位置を見つけ、対応するディスクの中心を印刷します。

I⌈X⌊η·⁵

最小の最大直径を印刷しますが、次の整数に切り上げます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.