overall code cleanup, modularization and optimizations

1. cleanup:
a) since rows and columns will always be equal (input is always a square
matrix), replaced them with gridSize
b) encapsulated logic to generate candidates using exclusion set into
GetCandidatesBasedOnExclusionSet() method and made all candidate
generators call this method
c) moved subgridsize computation to class level

optimizations:
a) modifications across candidate generation methods to use IEnumerable
instead of HashSet. This gives advantage of programming to interface and
also allows lazy evaluation
b) there was duplicate computation happening within and between
SubgridCandidatesBasedOnGrid() and SubgridCandidatesBasedOnSolution().
Introduced GetSubgridIndices() helper method to resolve this. it is used
for both subgrid row and column computation. Memoized it to save cost on
duplicate calls