パッキングサークル


21

この画像を見てください。具体的には、端の穴の配置方法。

ここに画像の説明を入力してください

画像ソース

この画像のパイプが六角形のパターンでどのように詰められているかに注目してください。2Dでは、六方格子が円の最も密なパッキングであることが知られています。この課題では、円のパッキングの周囲の最小化に焦点を当てます。境界線を視覚化する便利な方法の1つは、輪のコレクションの周りに輪ゴムを置くことを想像することです。

タスク

n入力として正の整数を指定するnと、できるだけ密にパックされた円のコレクションが表示されます。

規則と説明

  • 円の直径は1ユニットであると仮定します。
  • 最小化される変数は、グループ内の円の中心の凸包であると定義されている周囲の長さです。この画像を見てください:

ここに画像の説明を入力してください

直線の3つの円の周囲は4(凸包は2x0の長方形で、2は2回カウントされます)、120度の角度で配置された円の周囲は約3.85、三角形の周囲はわずか3ユニットです。円の中心ではなく、円の端だけを見ているため、実際の境界線となる追加のpi単位を無視していることに注意してください。

  • 任意のに対して複数のソリューションが存在する可能性があります(ほぼ確実に存在します)n。これらのいずれかを自由裁量で出力できます。向きは関係ありません。
  • 円は六角格子上になければなりません。
  • 円の直径は少なくとも10ピクセルである必要があり、塗りつぶしてもしなくてもかまいません。
  • プログラムまたは関数のいずれかを作成できます。
  • 入力は、STDINを介して、関数の引数として、または最も近いものとして取得できます。
  • 出力は表示されるか、ファイルに出力されます。

以下に、1から10までのnの有効および無効な出力の例を示します(有効な例は、最初の5つのみです)。有効な例は左側にあります。右側のすべての例は、対応する有効な例よりも大きな境界線を持っています。

ここに画像の説明を入力してください

この課題の作成を支援してくれたsteveverrillに感謝します。ハッピーパッキング!


3
六角形を待って、私は賭けています。; D
アディソンクランプ

@VoteToClose:Hexagonyにグラフィカルな出力があるとは思わないが、MAN、それは素晴らしいだろう!
エレンディアスターマン

El'endiaStarmanまあ@、あなたは可能性が stdoutにSVGを書くが、私は私がするつもりだとは思わない...:P
マーティン・エンダー

1
うわー、これまで誰もサンドボックスでの私のコメントに大胆に感謝していない。私は赤面しています:-Dもちろん、私はチャレンジが好きだったのでコメントしましたが、それに答える時間があるかどうかはわかりません。
レベルリバーセント

user81655の回答に関するReto Koradiとの私の議論によると、鋭い角で見られる最大の六角形は横長7d(8円)であると思います。これは合計N = 169円です。問題をその数に制限することを検討することができます。これにより、正しい答えを得る可能性が高くなり(現在はありません)、確認できるようになります。一方、任意のNに問題オープンまで残すことより面白いかもしれ
レベル川セント

回答:


4

Mathematica 295950 バイト

注:このまだゴルフのバージョンは、私の以前の試みに関してスティーブメリルによって提起された問題に対処します。

これは最初のバージョンよりも改善されていますが、六角形ではなく円形の全体的な形状を求める最も密なハンドル構成は見つかりません。

完全な内部六角形(n> = 6の場合)を構築することで解決策を見つけ、残りの円で外部シェルを完成させるためにすべての構成を調べます。

興味深いことに、Steve Merrillがコメントで指摘したように、n+1円の解は、n個の円に別の円が追加された解で構成されるとは限りません。30個の円の指定されたソリューションを、31個の円の指定されたソリューションと比較します。(注:30個の円に対して独自のソリューションがあります。)

m[pts_]:={Show[ConvexHullMesh[pts],Graphics[{Point/@pts,Circle[#,1/2]&/@ pts}], 
ImageSize->Tiny,PlotLabel->qRow[{Length[pts],"  circles"}]],
RegionMeasure[RegionBoundary[ConvexHullMesh[pts]]]};
nPoints = ((#+1)^3-#^3)&;pointsAtLevelJ[0] = {{0,0}};
pointsAtLevelJ[j_]:=RotateLeft@DeleteDuplicates@Flatten[Subdivide[#1, #2, j] &@@@
Partition[Append[(w=Table[j{Cos[k Pi/3],Sin[k Pi/3]},{k,0,5}]), 
w[[1]]], 2, 1], 1];nPointsAtLevelJ[j_] := Length[pointsAtLevelJ[j]]
getNPoints[n_] := Module[{level = 0, pts = {}},While[nPoints[level]<=n, 
pts=Join[pointsAtLevelJ[level],pts];level++];Join[Take[pointsAtLevelJ[level],n-Length[pts]],
pts]];ns={1,7,19,37,61,91};getLevel[n_]:=Position[Union@Append[ns,n],n][[1, 1]]-1;
getBaseN[n_] := ns[[getLevel[n]]];pack[1]=Graphics[{Point[{0,0}], Circle[{0, 0}, 1/2]}, 
ImageSize->Tiny];pack[n_]:=Quiet@Module[{base = getNPoints[getBaseN[n]], 
outerRing = pointsAtLevelJ[getLevel[n]], ss},ss=Subsets[outerRing,{n-getBaseN[n]}];
SortBy[m[Join[base,#]]&/@ss,Last][[1]]]

一部のチェックでは、nの単一の値(対称性を含む)で10万件を超えるケースを比較しました。合計34のテストケースを実行するのに約5分かかりました。言うまでもなく、n'sこのブルートフォースアプローチが大きくなると、すぐに実用的ではなくなります。より効率的なアプローチが存在することは確かです。

各パッキングの右側の数字は、それぞれの青い凸包の周囲です。以下はの出力です3 < n < 35。赤い円は、通常の六角形の周りに追加されたものです。

ディスク



1
ユーザー81655の回答で述べたように、22(および17、25、28、31、34)に突き出ている単一の円は、それが置かれている円の列の中央に配置する方が適切です。
レベルリバーセント

私もそう思いましたが、それから、突出した円のある9が正しいと見なされたことに気付きました。時間があれば、(中心の)凸包の測定値を比較します。
DavidC

9では、突出する円は平らな列に沿って1/4または3/4であるため、違いはありません。17、22、25、28、31では、突出する円は1 / 6、3 / 6、または5/6に沿っているため、中央の位置のほうが優れています(ひもを横に引くことを考えてください:中央から引く方が簡単です34(および35)では、フラットサイドに沿って1 / 8、3 / 8、5 / 8、7 / 8があります。これらの場合、3/8および5/8を選択する必要があります。 1/8および7/8の前
Level River St

あなたは絶対に正しいですし、これは測定によって確認されます。
DavidC

これはすごい!30-> 31の遷移は、前の形状を取得して外側に円を追加することはできないことを示しています(16.464の境界線を与えていたはずです)。外側ですが、別の配置を選択しました:12-> 13
Level River St
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.