"Exercise: Rectangles"

rectangles: lines
"Count the rectangles in an ASCII diagram.
    You may assume that the input is always a proper rectangle (i.e. the length of every line equals the length of the first line)."
"(self new rectangles: #('   +--+' '  ++  |' '+-++--+' '|  |  |' '+--+--+')) >>> 6"
| h w count plusColsByRow |
	lines isEmpty ifTrue: [ ^ 0 ].
	w := lines first size.
	w = 0 ifTrue: [ ^ 0 ].
	h := lines size.

	plusColsByRow := Array new: h.
	1 to: h do: [ :r |
			| row pluses |
			row := lines at: r.
			pluses := ((1 to: w) select: [ :c | (row at: c) = $+ ]) asArray.
			plusColsByRow at: r put: pluses ].

	count := 0.
	1 to: h - 1 do: [ :r1 |
			r1 + 1 to: h do: [ :r2 |
					| topCols bottomCols common |
					topCols := plusColsByRow at: r1.
					bottomCols := plusColsByRow at: r2.
					common := topCols select: [ :c | bottomCols includes: c ].
					common size > 1 ifTrue: [
							1 to: common size - 1 do: [ :i |
									i + 1 to: common size do: [ :j |
											| c1 c2 okTop okBot okLeft okRight |
											c1 := common at: i.
											c2 := common at: j.

											okTop := (c1 + 1 to: c2 - 1) allSatisfy: [ :c |
													         | ch |
													         ch := (lines at: r1) at: c.
													         '-+' includes: ch ].
											okBot := (c1 + 1 to: c2 - 1) allSatisfy: [ :c |
													         | ch |
													         ch := (lines at: r2) at: c.
													         '-+' includes: ch ].

											(okTop and: [ okBot ]) ifTrue: [
													okLeft := (r1 + 1 to: r2 - 1) allSatisfy: [ :rr |
															          | ch |
															          ch := (lines at: rr) at: c1.
															          '|+' includes: ch ].
													okRight := (r1 + 1 to: r2 - 1) allSatisfy: [ :rr |
															           | ch |
															           ch := (lines at: rr) at: c2.
															           '|+' includes: ch ].

													(okLeft and: [ okRight ]) ifTrue: [ count := count + 1 ] ] ] ] ] ] ].
	^ count


"Tests"
testRectangles
self assert: (task rectangles: #()) equals: 0.
  self assert: (task rectangles: #('')) equals: 0.
  self assert: (task rectangles: #(' ')) equals: 0.
  self assert: (task rectangles: #('+-+' '| |' '+-+')) equals: 1.
  self assert: (task rectangles: #('  +-+' '  | |' '+-+-+' '| |  ' '+-+  ')) equals: 2.
  self assert: (task rectangles: #('  +-+' '  | |' '+-+-+' '| | |' '+-+-+')) equals: 5.
  self assert: (task rectangles: #('+--+' '+--+')) equals: 1.
  self assert: (task rectangles: #('++' '||' '++')) equals: 1.
  self assert: (task rectangles: #('++' '++')) equals: 1.
  self assert: (task rectangles: #('  +-+' '    |' '+-+-+' '| | -' '+-+-+')) equals: 1.
  self assert: (task rectangles: #('+------+----+' '|      |    |' '+---+--+    |' '|   |       |' '+---+-------+')) equals: 3.
  self assert: (task rectangles: #('+------+----+' '|      |    |' '+------+    |' '|   |       |' '+---+-------+')) equals: 2.
  self assert: (task rectangles: #('+---+--+----+' '|   +--+----+' '+---+--+    |' '|   +--+----+' '+---+--+--+-+' '+---+--+--+-+' '+------+  | |' '          +-+')) equals: 60.
  self assert: (task rectangles: #('+-+ +-+' '| | | |' '+-+-+-+' '  | |  ' '+-+-+-+' '| | | |' '+-+ +-+')) equals: 5