最大フェンスの配置を数える


9

バックグラウンド

フェンスを作りたいです。そのために、私はたくさんの棒を集めて、それらを地面に貼りました。実際のフェンスを作るためにポールに釘付けにするボードもたくさん集めました。私はものを構築するときに夢中になる傾向があり、おそらくそれを置く場所がなくなるまでボードをポールに釘付けし続けるでしょう。最終的に可能なフェンスを列挙してほしい。

入力

入力は、便利な形式で極の位置を表す2次元整数座標のリストです。重複は含まれていないと想定できますが、その順序については何も想定できません。

ボードは、極の間の直線で表されます。簡単にするために、水平ボードと垂直ボードのみを考慮します。間に2つの極またはボードが存在しない場合、2つの極をボードで結合できます。つまり、ボードを相互に交差させることはできません。ポールとボードの配置は、新しいボードを追加できない場合に最大になります(同等に、水平または垂直に配置された2つのポールの間にポールまたはボードが存在します)。

出力

出力は、極を使用して構築できる最大配置の数です。

入力リストを検討する

[(3,0),(1,1),(0,2),(-1,1),(-2,0),(-1,-1),(0,-2),(1,-1)]

上から見ると、対応する極の配置は次のようになります。

  o
 o o
o    o
 o o
  o

これらの極を使用して構築できる3つの最大配置があります。

  o        o        o
 o-o      o|o      o-o
o----o   o||| o   o| | o
 o-o      o|o      o-o
  o        o        o

したがって、正しい出力は3です。

ルール

関数または完全なプログラムのいずれかを記述できます。最も低いバイト数が優先され、標準の抜け穴は許可されません。

テストケース

[] -> 1
[(0,0),(1,1),(2,2)] -> 1
[(0,0),(1,0),(2,0)] -> 1
[(0,0),(0,1),(1,0),(1,1)] -> 1
[(1,0),(0,1),(-1,0),(0,-1)] -> 2
[(3,0),(1,1),(0,2),(-1,1),(-2,0),(-1,-1),(0,-2),(1,-1)] -> 3
[(0,0),(4,0),(1,1),(1,-2),(3,1),(3,-2),(2,-1),(4,-1)] -> 3
[(0,0),(4,0),(1,1),(1,-2),(3,1),(3,-2),(2,-1),(4,-1),(0,-1)] -> 4
[(0,0),(4,0),(1,1),(1,-2),(3,1),(3,-2),(2,-1),(0,-1),(2,2)] -> 5
[(0,0),(4,0),(1,1),(1,-2),(3,1),(3,-2),(2,-1),(4,-1),(0,-1),(2,2)] -> 8

1
この例では、(-2,0)が2回あるようです。それらのうちの1つを(2,0)にする必要がありますか?
isaacg 2015年

@isaacg実際には、それは(0,-2)良いキャッチです。今変わります。
Zgarb 2015年

回答:


5

Mathematica、301バイト

(t~SetAttributes~Orderless;u=Subsets;c=Complement;l=Select;f=FreeQ;Count[s=List@@@l[t@@@u[Sort@l[Sort/@#~u~{2},!f[#-#2&@@#,0]&]//.{a___,{x_,y_},{x_,z_},b___,{y_,z_},c___}:>{a,{x,y},b,{y,z},c}],f[#,t[{{a_,b_},{a_,c_}},{{d_,e_},{f_,e_}},___]/;d<a<f&&b<e<c]&],l_/;f[s,k_List/;k~c~l!={}&&l~c~k=={},{1}]])&

これは、座標をネストされたものとして取りList、整数を返す名前のない関数です。つまり、名前を付けて呼び出すか、追加するだけです。

@ {{3, 0}, {1, 1}, {0, 2}, {-1, 1}, {-2, 0}, {-1, -1}, {0, -2}, {1, -1}}

インデントあり:

(
  t~SetAttributes~Orderless;
  u = Subsets;
  c = Complement;
  l = Select;
  f = FreeQ;
  Count[
    s = List @@@ l[
      t @@@ u[
        Sort @ l[
          Sort /@ #~u~{2}, 
          !f[# - #2 & @@ #, 0] &
        ] //. {a___, {x_, y_}, {x_, z_}, b___, {y_, z_}, c___} :> 
              {a, {x, y}, b, {y, z}, c}
      ],
      f[
        #,
        t[{{a_, b_}, {a_, c_}}, {{d_, e_}, {f_, e_}}, ___] 
          /; d < a < f && b < e < c
      ] &
    ], 
    l_ /; f[
      s, 
      k_List /; k~c~l != {} && l~c~k == {}, 
      {1}
    ]
  ]
) &

この実装の素朴さを表現することすらできません。

  • 極のすべての(順序付けられていない)ペアを取得します。
  • 各ペアとすべてのペアを正規の順序に並べ替えます。
  • 1つの座標を共有しない(つまり、直交線で接続できない)ペアを破棄します。
  • 破棄ペアは、2つの短いペアから形成できます(これo--o--oにより、フェンスが3つではなく2つだけ生成されます)。
  • それらのペアのすべてのサブセット、つまりフェンスのすべての可能な組み合わせを取得します。
  • フェンスが互いに交差している組み合わせを除外します。
  • リストに厳密なスーパーセットが見つからない結果のフェンスセットの数をカウントします。

驚くべきことに、すべてのテストケースをほぼ即座に解決します。

これについて私が発見した本当にすてきなトリックは、を使用Orderlessして、照合する必要のあるパターンの数を減らすことです。基本的に、フェンスセットと交差するフェンスを取り除きたい場合は、垂直フェンスと水平フェンスのペアを見つけて、それらの状態を確認する必要があります。しかし、どのような順序で表示されるのかはわかりません。リストパターンは通常順序に依存しているため、2つの非常に長いパターンになります。だからではなく、私は機能と、周囲のリストに置き換えるtt @@@、そのまま維持されるように定義されていません- 。しかし、その機能があるOrderlessので、私はできるだけのパターンで、単一の順序を確認し、Mathematicaはすべての順列に対してそれをチェックします。その後、リストをで元に戻しましたList @@@

0)引数またはリスト引数に対してOrderless、a)、b)なし Listable、およびc)定義されていない組み込みがあったらいいのにと思います。その後、それで置き換えることができtます。しかし、そのようなオペレーターはいないようです。


Mathematicaがそれを正しく行うか十分に速く行うかを考えている場合、答えは「はい」です。
Seequ

まあ、それは私のリファレンス実装と同じくらい素朴です。:P
Zgarb 2015年

1

Haskell、318バイト

import Data.List
s=subsequences
k[(_,a,b),(_,c,d)]|a==c=f(\w->(1,a,w))b d|1<2=f(\w->(2,w,b))a c
f t u v=[t x|x<-[min u v+1..max u v-1]]
q l=nub[x|x<-map(k=<<)$s[a|a@[(_,n,m),(_,o,p)]<-s l,n==o||m==p],x++l==nubBy(\(_,a,b)(_,c,d)->a==c&&b==d)(x++l)]
m=q.map(\(a,b)->(0,a,b))
p l=sum[1|x<-m l,all(\y->y==x||x\\y/=[])$m l]

使用法:p [(1,0),(0,1),(-1,0),(0,-1)]。出力:2

使い方:

  • 入力リストのすべてのサブリストを作成し、2つの要素と、x座標またはy座標が等しいものを保持します。これは、間にフェンスを構築できるポールのすべてのペアのリストです。
  • そのすべてのサブリストを作成する
  • すべてのリストにボードを追加する
  • xy座標が2度出現するリストを削除(ボードとポール)
  • 極が直接隣接しているため(例:(1,0)と(1,1))、重複リスト(ボードのみ)を削除して複数の空のリストを処理します
  • 別のリストの厳密なサブリストではないものを保持する
  • 残りのリストを数える
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.