Hitung Pengaturan Pagar Maksimal

9

Latar Belakang

Saya ingin membangun pagar. Untuk itu, saya telah mengumpulkan banyak tiang, dan menancapkannya ke tanah. Saya juga telah mengumpulkan banyak papan yang akan saya paku ke tiang untuk membuat pagar yang sebenarnya. Saya cenderung terbawa ketika membangun barang-barang, dan kemungkinan besar saya akan terus menempelkan papan ke tiang sampai tidak ada lagi tempat untuk meletakkannya. Saya ingin Anda menyebutkan kemungkinan pagar yang bisa saya akhiri.

Memasukkan

Input Anda adalah daftar koordinat bilangan dua dimensi yang mewakili posisi kutub, dalam format apa pun yang nyaman. Anda dapat berasumsi bahwa itu tidak mengandung duplikat, tetapi Anda tidak dapat mengasumsikan apa pun tentang pesanannya.

Papan diwakili oleh garis lurus antara kutub, dan untuk kesederhanaan, kami hanya mempertimbangkan papan horizontal dan vertikal. Dua kutub dapat disatukan dengan papan jika tidak ada kutub atau papan lain di antara mereka, yang berarti bahwa papan tidak dapat saling bersilangan. Susunan tiang dan papan maksimal jika tidak ada papan baru dapat ditambahkan ke dalamnya (setara, ada baik tiang atau papan antara dua kutub horizontal atau vertikal).

Keluaran

Output Anda adalah jumlah pengaturan maksimal yang dapat dibangun menggunakan kutub.

Contoh

Pertimbangkan daftar input

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

Dilihat dari atas, susunan kutub yang sesuai terlihat seperti ini:

  o
 o o
o    o
 o o
  o

Tepat ada tiga pengaturan maksimal yang dapat dibangun menggunakan kutub ini:

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

Dengan demikian output yang benar adalah 3.

Aturan

Anda dapat menulis fungsi atau program lengkap. Hitungan byte terendah menang, dan celah standar tidak diizinkan.

Uji Kasus

[] -> 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
Zgarb
sumber
1
Contohnya tampaknya memiliki (-2,0) dua kali. Haruskah salah satunya (2,0)?
isaacg
@isaacg Sebenarnya, seharusnya (0,-2), tangkapan yang bagus. Berubah sekarang.
Zgarb

Jawaban:

5

Mathematica, 301 byte

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

Ini adalah fungsi tanpa nama yang mengambil koordinat sebagai bersarang Listdan mengembalikan integer. Artinya, Anda bisa memberikannya nama dan memanggilnya, atau hanya menambahkan

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

Dengan lekukan:

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

Saya bahkan tidak bisa mulai menyatakan betapa naifnya implementasi ini ... pasti tidak bisa lebih kasar ...

  • Dapatkan semua pasang (tidak berurutan) tiang.
  • Urutkan setiap pasangan dan semua pasangan ke dalam urutan kanonik.
  • Buang pasangan yang tidak berbagi satu koordinat (yaitu yang tidak dapat dihubungkan oleh garis ortogonal).
  • Buang pasangan dapat dibentuk dari dua pasangan yang lebih pendek (sehingga o--o--omenghasilkan hanya dua pagar, bukan tiga).
  • Dapatkan semua himpunan bagian dari pasangan itu - yaitu semua kemungkinan kombinasi pagar.
  • Saring kombinasi yang memiliki pagar saling silang.
  • Hitung jumlah set pagar yang dihasilkan yang tidak ada superset ketat dapat ditemukan dalam daftar.

Anehnya itu menyelesaikan semua kasus uji hampir secara langsung.

Trik yang sangat rapi yang saya temukan untuk ini adalah penggunaan Orderlessuntuk mengurangi jumlah pola yang harus saya cocokkan. Intinya, ketika saya ingin membuang pagar dengan pagar penyeberangan, saya perlu menemukan sepasang pagar vertikal dan horizontal dan memeriksa kondisinya. Tapi saya tidak tahu urutan apa yang akan muncul. Karena pola daftar biasanya tergantung pesanan, ini akan menghasilkan dua pola yang sangat panjang. Jadi alih-alih saya ganti dengan daftar sekitarnya dengan fungsi tdengan t @@@- yang tidak didefinisikan sehingga disimpan seperti apa adanya. Tapi fungsi itu Orderless, jadi saya hanya bisa memeriksa satu urutan dalam pola, dan Mathematica akan memeriksanya terhadap semua permutasi. Setelah itu, saya mengembalikan daftar itu ke tempatnya List @@@.

Saya berharap ada built-in yang a) Orderless, b) tidak Listable dan c) tidak didefinisikan untuk 0 argumen atau daftar argumen. Maka saya bisa menggantinya t. Tapi sepertinya tidak ada operator seperti itu.

Martin Ender
sumber
Ketika Anda berpikir jika Mathematica melakukannya dengan benar atau cukup cepat, jawabannya adalah "ya".
seequ
Ya, itu sama naifnya dengan implementasi referensi saya. : P
Zgarb
1

Haskell, 318 byte

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]

Penggunaan: p [(1,0),(0,1),(-1,0),(0,-1)]. Keluaran:2

Bagaimana itu bekerja:

  • buat semua sublists dari daftar input dan simpan mereka dengan dua elemen dan dengan koordinat x atau sama dengan y. Ini adalah daftar semua pasangan kutub tempat pagar dapat dibangun di antaranya.
  • buat semua sublists dari itu
  • tambahkan papan untuk setiap daftar
  • hapus daftar tempat koordinat xy muncul dua kali (papan dan kutub)
  • menghapus daftar duplikat (hanya papan) untuk menangani beberapa daftar kosong, karena kutub yang berbatasan langsung (misalnya (1,0) dan (1,1))
  • simpan yang bukan merupakan sublist ketat dari daftar lain
  • hitung daftar yang tersisa
nimi
sumber