Haskell , 228  227  225 224 ไบต์
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..]
ลองออนไลน์!
คำอธิบาย:
ความคิดสำหรับการแก้ปัญหานี้จะเป็นดังนี้: initialise เมทริกซ์ที่มีค่าที่ไม่ซ้ำกันในแต่ละเซลล์ในเชิงบวกสำหรับและเชิงลบสำหรับ1 0จากนั้นเปรียบเทียบแต่ละเซลล์กับเพื่อนบ้านเป็นประจำและหากเพื่อนบ้านมีสัญลักษณ์เดียวกัน แต่มีตัวเลขที่มีค่าสัมบูรณ์ที่ใหญ่กว่าให้แทนที่หมายเลขเซลล์ด้วยหมายเลขของเพื่อนบ้าน เมื่อถึงจุดคงที่ให้นับจำนวนของจำนวนบวกที่แตกต่างกันสำหรับจำนวนของ1ภูมิภาคและจำนวนลบที่แตกต่างกันสำหรับจำนวนของ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..]
สามารถแยกออกเป็นการประมวลผลล่วงหน้า (การกำหนดหมายเลขให้กับเซลล์) การวนซ้ำและการประมวลผลภายหลัง (การนับเซลล์)
กระบวนการเตรียมการผลิต
ส่วนการประมวลผลล่วงหน้าคือฟังก์ชั่น
z(\i->z(\j x->2^i*j*(2*x-1))[1,3..])[1..]
ซึ่งใช้zเป็นตัวย่อสำหรับzipWithการโกนไม่กี่ไบต์ สิ่งที่เราทำที่นี่คือซิปอาเรย์สองมิติพร้อมดัชนีจำนวนเต็มที่แถวและดัชนีเลขจำนวนเต็มคี่ที่คอลัมน์ เราทำเช่นนี้เนื่องจากเราสามารถสร้างจำนวนเต็มไม่ซ้ำกันจากคู่ของจำนวนเต็มโดยใช้สูตรที่(i,j) (2^i)*(2j+1)หากเราสร้างจำนวนเต็มคี่สำหรับjเราสามารถข้ามการคำนวณ2*j+1และบันทึกสามไบต์
ด้วยหมายเลขที่ไม่ซ้ำกันตอนนี้เราต้องคูณด้วยเครื่องหมายตามค่าในเมทริกซ์ซึ่งได้มาเป็น 2*x-1
การย้ำ
การวนซ้ำทำได้โดย
(until=<<((==)=<<))((.)>>=id$transpose.map l)
เนื่องจากอินพุตอยู่ในรูปแบบของรายการเราจึงทำการเปรียบเทียบเพื่อนบ้านในแต่ละแถวย้ายเมทริกซ์ทำการเปรียบเทียบในแต่ละแถวอีกครั้ง (ซึ่งเนื่องจากการแปลงเป็นคอลัมน์ก่อนหน้านี้) และเปลี่ยนอีกครั้ง รหัสที่สำเร็จหนึ่งในขั้นตอนเหล่านี้คือ
((.)>>=id$transpose.map l)
โดยที่lฟังก์ชั่นการเปรียบเทียบ (รายละเอียดด้านล่าง) และtranspose.map lดำเนินการครึ่งหนึ่งของขั้นตอนการเปรียบเทียบและการขนย้าย (.)>>=idดำเนินการโต้แย้งสองครั้งเป็นรูปแบบ pointfree \f -> f.fและสั้นลงหนึ่งไบต์ในกรณีนี้เนื่องจากกฎที่มีความสำคัญกว่าผู้ประกอบการ
ll x=z(!)(z(!)x(0:x))$tail x++[0]ถูกกำหนดไว้ในแถวด้านบนเป็น รหัสนี้ดำเนินการตัวดำเนินการเปรียบเทียบ(!)(ดูด้านล่าง) ในทุกเซลล์ที่มีเพื่อนบ้านด้านซ้ายก่อนแล้วจึงมีเพื่อนบ้านที่เหมาะสมโดยการซิปรายการที่xมีรายการที่เลื่อนด้านขวา0:xและรายการที่เลื่อนด้านซ้ายtail x++[0]ในทางกลับกัน เราใช้ศูนย์เพื่อรองรายการที่ถูกเลื่อนเนื่องจากมันไม่สามารถเกิดขึ้นได้ในเมทริกซ์ที่ประมวลผลล่วงหน้า
a!ba!b=div(max(a*a)(a*b))aถูกกำหนดไว้ในแถวข้างต้นนี้เป็น สิ่งที่เราต้องการทำที่นี่คือความแตกต่างกรณีดังต่อไปนี้:
- หากsgn(a) = -sgn(b)เรามีพื้นที่ตรงข้ามสองแห่งในเมทริกซ์และไม่ต้องการรวมมันเข้าด้วยกันดังนั้นaไม่เปลี่ยนแปลง
- หากsgn(b) = 0เรามีกรณีมุมซึ่งbเป็นช่องว่างภายในและดังนั้นจึงaยังคงไม่เปลี่ยนแปลง
- หากsgn(a) = sgn(b)เราต้องการรวมสองพื้นที่และนำสิ่งที่มีค่าสัมบูรณ์ที่ใหญ่กว่า (เพื่อประโยชน์ของความสะดวกสบาย)
โปรดทราบว่าไม่สามารถจะsgn(a) 0เราทำสิ่งนี้สำเร็จด้วยสูตรที่กำหนด หากมีอาการของaและbแตกต่างกันa*bน้อยหรือเท่ากับศูนย์ในขณะที่a*aอยู่เสมอมากกว่าศูนย์เพื่อให้เรารับมันเป็นสูงสุดและหารด้วยที่จะได้รับกลับมาa aมิฉะนั้นmax(a*a)(a*b)เป็นabs(a)*max(abs(a),(abs(b))และโดยการหารด้วยaเราได้sgn(a)*max(abs(a),abs(b))ซึ่งเป็นจำนวนที่มีค่าสัมบูรณ์ที่ใหญ่กว่า
ในการวนซ้ำฟังก์ชัน((.)>>=id$transpose.map l)จนกว่าจะถึงจุดคงที่เราใช้(until=<<((==)=<<))ซึ่งนำมาจากคำตอบสแต็คโอเวอร์โฟลว์นี้นี้
postprocessing
สำหรับการประมวลผลภายหลังเราใช้ชิ้นส่วน 
(\x->length.($x).filter<$>[(>0),(<0)]).nub.(>>=id)
ซึ่งเป็นเพียงชุดของขั้นตอน
(>>=id)สควอชรายการของรายการลงในรายการเดียว
 nubกำจัดคู่ผสม
 (\x->length.($x).filter<$>[(>0),(<0)])พาร์ทิชันรายการเป็นคู่ของรายการหนึ่งรายการสำหรับบวกและอีกหนึ่งสำหรับตัวเลขลบและคำนวณความยาวของพวกเขา
               
              
[[1,0];[0,1]]เพื่อให้แน่ใจว่าไม่มีการเชื่อมต่อในแนวทแยง