Your code looks like a quite good start.
You can however also filter by template instead of limiting to a specific parent page:
foreach ($solutions->index()->filterBy('template', 'solution') as $solution) {
...
This will get all pages (even sub-sub-sub-pages of $solutions), but only those that use the template solution.php.
In the loop you then need to iterate through the items from the structure field and build an index of the categories. Here’s some untested example code:
Controller code
$categories = array();
foreach ($solutions->index()->filterBy('template', 'solution') as $solution) {
$solutionCategories = $solution->categories()->toStructure();
foreach($solutionCategories as $category) {
list($mainCategory, $subCategory) = explode('/', $category->subcategory());
// Add sub category to array
if(!isset($categories[$mainCategory][$subCategory])) {
$categories[$mainCategory][$subCategory] = false;
}
// Set page if set to be destination
// Check whether a destination has already been set (makes sure the first match is being used)
if($category->destination() === 'true' && $categories[$mainCategory][$subCategory] === false) {
$categories[$mainCategory][$subCategory] = $solution;
}
}
}
// Sort columns alphabetically
ksort($categories);
Template code
// Print columns and rows
foreach($categories as $mainCategory => $subCategories) {
// Pseudo markup
echo '<column>' . $mainCategory;
// Sort rows alphabetically
ksort($subCategories);
foreach($subCategories as $subCategory => $destination) {
echo '<row><a href="' . $destination->url() . '">' . $subCategory . '</a></row>';
}
echo '</column>';
}
Edit: Oh, you were faster. I hope my example helps you anyway. 