Kare bulucu - Düzenli tetragonların konumlandırılması


27

Düzlemde çizilen ve her birinin tamsayı koordinatlarındaki köşeleri ve eksene paralel kenarları olan bir dikdörtgeni hayal edin:

görüntü tanımını buraya girin

Dikdörtgenler, düzlemi, aşağıda kırmızı ve mavi renkli olan birkaç ayrık bölgeye ayırır:

görüntü tanımını buraya girin

Amacınız mükemmel kareler gibi bölgelerin sayısını bulmaktır. Yukarıdaki örnekte üç tane var:

görüntü tanımını buraya girin

Ortadaki büyük karenin tek bir bölge olmadığı için sayılmadığını, bunun yerine daha küçük ayrık bölgelerden oluştuğunu unutmayın.

Giriş

Bu görev için bir işlev veya tam bir program yazabilirsiniz.

Girdi , düzlemdeki dikdörtgenleri 4ntanımlayan negatif olmayan tam sayılar olacaktır n. Her dikdörtgen iki karşıt tepe noktasıyla temsil edilir, örneğin karşıt tepe noktaları 4 9 7 8olan dikdörtgeni temsil eder (4, 9)ve (7, 8). Bu dikdörtgenin de 7 8 4 9veya olarak gösterilebileceğini unutmayın 4 8 7 9.

Kesin giriş formatı esnektir (örn. Boşlukla ayrılmış dize, virgülle ayrılmış dize, tekli tamsayılar dizisi, koordinat ipuçlarının listesi vb.), Ancak lütfen makul olun ve kodunuzu gönderiminizde nasıl çalıştıracağınıza dair bir örnek verin. Girişi yeniden sıralayamayabilirsiniz.

Basit olması için, iki kenarın üst üste gelmeyeceğini varsayabilirsiniz - buna bir tepe noktasında örtüşme dahildir. Özellikle, bu hiçbir iki dikdörtgenin kenardan kenara veya köşeden köşeye temas etmeyeceği ve dikdörtgenlerin sıfır alan içermeyeceği anlamına gelir.

Çıktı

Programınız, kare bölge sayısı olan tek bir tam sayı yazdırmalı veya döndürmelidir.

puanlama

Bu kod golf, yani en az bayttaki kod kazanıyor.


Test durumları

Giriş:

0 0 5 5
6 8 10 4
14 16 11 13
19 1 18 2

Çıktı:

4

Bu sadece dört ayrık karedir:

görüntü tanımını buraya girin


Giriş:

2 1 3 11
1 10 5 19
6 10 11 3
8 8 15 15
13 13 9 5
15 1 19 7
17 19 19 17

Çıktı:

3

Bu, gönderinin başlangıcındaki örnek test durumudur.


Giriş:

0 9 15 12
6 3 18 15
9 6 12 20
13 4 17 8

Çıktı:

7

görüntü tanımını buraya girin


Giriş:

5 9 11 10
5 12 11 13
6 8 7 14
9 8 10 14
13 8 14 9
13 10 14 14

Çıktı:

14

görüntü tanımını buraya girin


Giriş:

0 99999 100000 0

Çıktı:

0

Bu sadece bir büyük dikdörtgen.


Giriş:

0 99999 100000 0
2 1 142857 285714

Çıktı:

1

Örtüşen iki büyük dikdörtgen.

Yanıtlar:


9

SQL (POSTGIS), 286 269 261 240 226 218 216

Bu PostgreSQL için PostGIS uzantısı için bir sorgu. Toplamda giriş değerlerini saymadım.

SELECT SUM(1)FROM(SELECT(ST_Dump(ST_Polygonize(g))).geom d FROM(SELECT ST_Union(ST_Boundary(ST_MakeEnvelope(a,b,c,d)))g FROM(VALUES
-- Coordinate input
(2, 1, 3, 11)
,(1, 10, 5, 19)
,(6, 10, 11, 3)
,(8, 8, 15, 15)
,(13, 13, 9, 5)
,(15, 1, 19, 7)
,(17, 19, 19, 17)
)i(a,b,c,d))i)a WHERE(ST_XMax(d)-ST_XMin(d))^2+(ST_YMax(d)-ST_YMin(d))^2=ST_Area(d)*2

açıklama

Sorgu, her koordinat çifti için geometri oluşturur. Çizgileri doğru şekilde düğümlemek için dış halkaları birleştirir. Sonuçları çokgenlere dönüştürür ve genişliği genişliğe ve alanın her bir karesinin toplamına göre iki katına çıkardığını test eder.

PostGIS Uzantısına sahip herhangi bir PostgreSQL veritabanında bağımsız bir sorgu olarak çalışacaktır.

Düzenle Birkaç tane daha bulundu.


1
... ve Haskell
Doktor

@optimizer Sonuna kalacağından şüpheliyim :)
MickyT

@MickyT Bu sağlıklı bir rekabete dönüşmüştür. :)
Zgarb

@zgarb biraz :-) var ama gidecek başka bir şeyim olduğunu sanmıyorum.
MickyT

13

Python 2, 480 436 386 352 bayt

exec u"""s=sorted;H=[];V=[]
FRIinput():
 S=2*map(s,zip(*R))
 FiI0,1,2,3:
    c=S[i][i/2];a,b=S[~i]
    FeIs(H):
     C,(A,B)=e
     if a<C<b&A<c<B:e[:]=C,(A,c);H+=[C,(c,B)],;V+=[c,(a,C)],;a=C
    V+=[c,(a,b)],;H,V=V,H
print sum(a==A==(d,D)&c==C==(b,B)&B-b==D-d&1-any(d<X[0]<D&b<y<B Fy,XIH)Fb,aIH FB,AIH Fd,cIV FD,CIV)""".translate({70:u"for ",73:u" in ",38:u" and "})

STDIN aracılığıyla koordinat çiftlerinin bir listesini alır:

[  [(x, y), (x, y)],  [(x, y), (x, y)],  ...  ]

ve sonucu STDOUT'a yazdırır.


Dize değişiminden sonra gerçek program şudur:

s=sorted;H=[];V=[]
for R in input():
 S=2*map(s,zip(*R))
 for i in 0,1,2,3:
    c=S[i][i/2];a,b=S[~i]
    for e in s(H):
     C,(A,B)=e
     if a<C<b and A<c<B:e[:]=C,(A,c);H+=[C,(c,B)],;V+=[c,(a,C)],;a=C
    V+=[c,(a,b)],;H,V=V,H
print sum(a==A==(d,D) and c==C==(b,B) and B-b==D-d and 1-any(d<X[0]<D and b<y<B for y,X in H)for b,a in H for B,A in H for d,c in V for D,C in V)

açıklama

Karmaşık çokgenlerle uğraşmak yerine, bu program basit çizgi bölümleriyle ilgilenir. Her giriş dikdörtgeni için dört kenarından her birini ayrı ayrı bir toplu segment listesine ekliyoruz. Listeye bir bölüm eklemek aşağıdaki gibidir: mevcut bölümlerin her birini yeni bölümle kesişmek üzere test ediyoruz; Bir kavşak bulursak, her iki kesimi de kavşak noktasında böler ve devam ederiz. İşleri kolaylaştırmak için aslında iki ayrı bölüm listesi tutuyoruz: yatay ve dikey olanlar. Segmentler üst üste gelmediğinden, yatay segmentler yalnızca dikey segmentlerle kesişebilir veya tersi de geçerlidir. Daha da iyisi, tüm kavşakların (aynı dikdörtgenin kenarlarını göz önünde bulundurmadan) "uygun" olduğu anlamına gelir, yani T şeklinde kavşaklarımız yoktur, bu nedenle her bir parçanın "her iki tarafı" gerçekten bölünmüştür.

Bölüm listelerini oluşturduktan sonra, kareleri saymaya başlarız. Dört parçanın her kombinasyonu için (özellikle iki yatay parça ve iki dikey parça), bir kare oluşturup oluşturmadıklarını test ediyoruz. Dahası, bu karenin içinde hiçbir tepe noktası olmadığını doğrularız (örneğin, daha büyük bir karenin içinde küçük bir karemiz varsa olabilir.) Bu bize istenen miktarı verir. Program her bir kombinasyonu farklı sıralamalarda dört kez test etse de, segment koordinatlarının belirli bir şekilde sıralanması, her kareyi yalnızca bir kez saymamızı garanti eder.


1
Bunu ne kadar çabuk çözdüğünüzden ve soruna yaklaştığınızdan çok etkilendim! For döngüler beni "kesinlikle bir şeyler yapılabilir ..."
Sp3000

@ Sp3000 Evet. itertoolsDöngüler için kullanmayı denedim ama daha uzun sürdü. Bir kaç baytı exec+ string değiştirmeyle traşlayabilirim ama çok heyecan verici bir şey yok.
Ell

4

Haskell, 276 266 250 237 225 222 217 bayt

Kısalmaya devam ediyor ... ve daha fazla şaşırıyor.

(x#i)l=mapM id[[min x i..max x i-1],l]
(y!j)l f=and[p l==p(f[y,j])|p<-map elem$f[y..j]]
s[h,v]=sum[1|[x,j]<-h,[y,i]<-v,x<i,i-x==j-y,(y!j)h$x#i,(x!i)v$y#j]
n=s.foldr(\(x,y,i,j)->zipWith(++)[x#i$[y,j],y#j$[x,i]])[[],[]]

n [(0,0,5,5),(6,8,10,4),(14,16,11,13),(19,1,18,2)]İlk test durumu için değerlendirin . Sanırım Haskell'deki bu algoritmayı golfün sınırlarına yaklaştırıyorum.

Bu fonksiyon, (en azından çok yavaş O (n 3 ) burada n, giriş tüm dikdörtgenler toplam çevre olduğu) son iki testin durumlarda değerlendirmek olamaz. En iyi duruma getirme açıkken derlediğimde [(0,249,250,0),(2,1,357,714)]ve son testin 400 kez küçültülmüş versiyonunda çalıştırdığımda , 12 saniyenin biraz üzerinde bir sürede bitti. Buna dayanarak, gerçek test durumu yaklaşık 25 yıl içinde bitecekti.

Açıklama (kısmi, zamanım varken bunu genişleteceğim)

Biz ilk iki listeleri oluşturmak hve vaşağıdaki gibi. Girişteki her dikdörtgen için, sınırını uzunluk 1'e ayırırız. Yatay bölümlerin batı uç noktaları , uzunlukların 2 listesi olarak hdikey bölümlerin güney uç noktaları , depolar. golf nedenleriyle formu . Sonra her iki listede üzerinde sadece döngü ve yatay kenarı aramak ve dikey kenar öyle ve (onlar kuzeybatısında ve bir kare güneydoğu köşeleri bu yüzden) ve karenin sınırları doğru listelerinde olup olmadığını kontrol edin ve iç iken, koordinatlar değil. Aramanın pozitif örneklerinin sayısı çıktıdır.v[x,y]v[y,x][x,j][i,y]x < ii-x == j-yhv


Aferin, sanırım şimdi
toplanmam

@MickyT Bir hafta oldu, bu yüzden Zgarb'ın şimdilik cevabını kabul ettim, ancak daha sonra yenmeyi başarırsanız onay işareti hareket edebilir! Dürüst olmak gerekirse, siz ikinizin ne kadar ileri gidebildiğinizden çok etkilendim
Sp3000

@ Zgarb iyi kazanmak :-) kazandı
MickyT

@ Sp3000 güzel bir meydan okuma için teşekkürler.
MickyT

@ Sp3000 Teşekkürler! Bunu golf oynarken çok eğlendim.
Zgarb
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.