Haskell , 228 227 225 224 bayt
import Data.List
z=zipWith
a!b=div(max(a*a)(a*b))a
l x=z(!)(z(!)x(0:x))$tail x++[0]
s=(\x->length.($x).filter<$>[(>0),(<0)]).nub.(>>=id).(until=<<((==)=<<))((.)>>=id$transpose.map l).z(\i->z(\j x->2^i*j*(2*x-1))[1,3..])[1..]
Çevrimiçi deneyin!
Açıklama:
Bu çözüm için fikir aşağıdaki gibidir: Her hücrede benzersiz değerlere sahip matrisi, pozitif 1
ve negatif için başlat 0
. Daha sonra her bir hücreyi tekrar komşularıyla karşılaştırın ve eğer komşu aynı işarete ancak daha büyük bir mutlak değere sahip bir sayıya sahipse, hücrenin numarasını komşunun numarasıyla değiştirin. Bu, sabit bir noktaya ulaştığında, bölge sayısı için belirgin pozitif sayıları ve sayı 1
için belirgin negatif sayıları sayın .0
.
Kodunda:
s=(\x->length.($x).filter<$>[(>0),(<0)]).nub.(>>=id).(until=<<((==)=<<))((.)>>=id$transpose.map l).z(\i->z(\j x->2^i*j*(2*x-1))[1,3..])[1..]
ön işleme (hücrelere sayı atama), yineleme ve son işleme (hücreleri sayma) ayrılabilir
Ön İşleme
Ön işleme bölümü fonksiyondur
z(\i->z(\j x->2^i*j*(2*x-1))[1,3..])[1..]
Birkaç byte'ı tıraş etmek z
için kısaltma olarak kullanılır zipWith
. Burada yaptığımız şey, iki boyutlu diziyi satırlarda tamsayı indeksleri ve sütunlarda tek tamsayı dizinleri ile sıkıştırmak. Bunu (i,j)
, formülü kullanarak bir çift tam sayıdan benzersiz bir tam sayı oluşturabileceğimiz için yapıyoruz (2^i)*(2j+1)
. Eğer için sadece tuhaf tamsayılar üretersek , üç bayt tasarrufu j
yaparak hesaplamayı geçebiliriz 2*j+1
.
Eşsiz sayı ile, şimdi sadece matristeki değere dayalı bir işaretle çarpmak zorundayız. 2*x-1
tekrarlama
Yineleme tarafından yapılır
(until=<<((==)=<<))((.)>>=id$transpose.map l)
Girdi bir liste listesi biçiminde olduğundan, her satıra komşu karşılaştırması yaparız, matrisi çeviririz, her satırda karşılaştırmayı tekrar yaparız (translasyon nedeniyle daha önce sütunların ne olduğudır) ve tekrar dönüştürür. Bu adımlardan birini gerçekleştiren kod şudur:
((.)>>=id$transpose.map l)
l
Karşılaştırma fonksiyonu nerede (aşağıda detaylandırılmıştır) ve transpose.map l
karşılaştırma ve aktarma adımlarının yarısını gerçekleştirir. (.)>>=id
Argümanını iki kez gerçekleştirir, \f -> f.f
bu durumda operatör öncelik kuralları nedeniyle , amaçsız ve bir bayt daha kısadır.
l
yukarıdaki satırda tanımlanmıştır l x=z(!)(z(!)x(0:x))$tail x++[0]
. Bu kod (!)
, listeyi x
sağa kaydırılan liste 0:x
ve sola kaydırılan liste tail x++[0]
sırayla sıkıştırmak suretiyle, önce sol komşusu olan ve ardından sağ komşusu olan her hücrede bir karşılaştırma operatörü (aşağıya bakınız) gerçekleştirir . Önceden işlenmiş matriste asla bulunamadıkları için kaydırılmış listeleri doldurmak için sıfırları kullanırız.
a!b
Bunun üstündeki satırda tanımlanmıştır a!b=div(max(a*a)(a*b))a
. Burada yapmak istediğimiz, aşağıdaki durum ayrımıdır:
- Eğer
sgn(a) = -sgn(b)
matristeki iki zıt alanımız varsa ve onları birleştirmek istemiyorsak, o zaman a
değişmeden kalır.
- Öyleyse
sgn(b) = 0
, b
yastığın olduğu ve bu nedenle a
değişmeden kalan köşe kılıfına sahibiz.
- Eğer
sgn(a) = sgn(b)
bu iki alanı birleştirmek ve mutlak değeri en büyük olanı almak istiyoruz (kolaylık uğruna).
Not sgn(a)
olamaz 0
. Bunu, verilen formülle başardık. Belirtileri varsa a
ve b
farklılık a*b
ise, az ya da sıfır eşit a*a
sıfırdan her zaman büyüktür biz maksimum ve böl olarak almak, böylece a
geri almak için a
. Aksi takdirde, max(a*a)(a*b)
bir abs(a)*max(abs(a),(abs(b))
ve bu bölerek a
, bundan elde sgn(a)*max(abs(a),abs(b))
büyük bir mutlak değere sahip numarası olan.
Fonksiyonu ((.)>>=id$transpose.map l)
sabit bir noktaya gelinceye kadar yinelemek için (until=<<((==)=<<))
, bu stackoverflow yanıtından alınan kullanın .
Rötuş
Postprocessing için bu kısmı kullanıyoruz
(\x->length.($x).filter<$>[(>0),(<0)]).nub.(>>=id)
Bu sadece bir adımlar topluluğudur.
(>>=id)
listeler listesini tek bir listeye yerleştirir,
nub
çiftlerden kurtulur
(\x->length.($x).filter<$>[(>0),(<0)])
, listeyi bir çift listeye ayırır, biri pozitif, diğeri negatif sayılar için hesaplar ve uzunluklarını hesaplar.
[[1,0];[0,1]]
Çapraz bağlantının dahil olmadığından emin olmak gibi bir