In this tip, you will find a solution to the Spiral Print problem using multiple iterations over four Action delegates.
Introduction
This tip is an alternative to the article, A Stepwise C# Implementation of a Solution to the Spiral Print Problem. It’s not meant to be a critique of that article. It’s simply another approach.
Analysis of the Problem
It seems to me that spiral printing of a two dimensional array is just a question of iterating around the border of the array, then reducing the active size of the array by removing from consideration the 2 rows and 2 columns that have just been iterated over and repeating the exercise until all the characters have been printed.
So an array :
A B C D
E F G H
I J K L
M N O P
Q R S T
Is spiral printed as: ABCDHLPTSRQMIEFGKONJ
The Implementation of a Solution
There are four steps needed to print the border of the array. They are:
- Print the first row in ascending column order.
- Print the end column in ascending row order.
- Print the end row in descending column order.
- Print the first column in descending row order.
Each of the four steps can be implemented using an Action
delegate defined in the constructor of a SpiralPrinter
class in this way.
public SpiralPrinter(char[,] characters)
{
var nCols = characters.GetLength(1);
var nRows = characters.GetLength(0);
colEnd = nCols - 1;
rowEnd = nRows - 1;
PrintRowAsc = (() =>
{
for (int i = colStart; i <= colEnd; i++)
{
Console.Write(characters[rowStart, i]);
isActive = true;
}
rowStart++;
});
PrintRowDes = (() =>
{
for (int i = colEnd; i >= colStart; i--)
{
Console.Write(characters[rowEnd, i]);
isActive = true;
}
rowEnd--;
});
PrintColAsc = (() =>
{
for (int i = rowStart; i <= rowEnd; i++)
{
Console.Write(characters[i, colEnd]);
isActive = true;
}
colEnd--;
});
PrintColDes = (() =>
{
for (int i = rowEnd; i >= rowStart; i--)
{
Console.Write(characters[i, colStart]);
isActive = true;
}
colStart++;
});
}
Each delegate removes from consideration the row or column that it has just printed. It also sets the isActive
flag if it does any work. This enables the PrintSpiral
method to know when it has finished.
Printing Out the Spiral
This is done by simply iterating over the four methods until the isActive
flag is not set by any of them.
public void PrintSpiral()
{
do
{
isActive = false;
PrintRowAsc();
PrintColAsc();
PrintRowDes();
PrintColDes();
}
while (isActive);
Console.ReadLine();
}
Conclusion
Breaking a repetitive task into a series of self-contained actions and iterating over them until there is no more work to be done is a useful technique for simplifying seemingly complex problems.
History
- 6th May, 2020: Initial version