Firstly, how to calculate the required number of rows for a string of length n
using cols
columns:
rows = (n + cols - 1) / cols
This uses integer division for the calculation to avoid having to use floating point.
In order to fill the array, it would be nice to treat it as a 1D array so we can just copy the text into it. Because 2D arrays are stored as row-major order, this would work just fine.
We can do this by creating a Span<char>
for the 2D array using a helper method such as this (lifted from here):
public static Span<T> AsSpan<T>(Array array)
{
return MemoryMarshal.CreateSpan(
ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array)),
array.Length);
}
Putting those together we get the following:
string text = "DELICIOUS FOOD";
int cols = 5;
int rows = (text.Length + cols - 1) / cols;
var array = new char[rows, cols];
var span = AsSpan<char>(array); // Create a span that encompasses all the elements of 'array' as a single span.
text.CopyTo(span); // Copy the text to the span; this will wrap at the correct places.
span.Slice(text.Length).Fill('X'); // Fill the remainder of the span with 'X'.
Note that span.Slice(text.Length)
returns a new span starting at an offset of text.Length
elements - which is where we need to start filling with 'X' characters for the remainder of the last row.
Also note that Span<T>.Fill(item)
just fills that span with the specified item.
Putting this together into a test console app (try it online):
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Console1;
public static class Program
{
public static void Main()
{
string text = "DELICIOUS FOOD";
int cols = 5;
int rows = (text.Length + cols - 1) / cols;
var array = new char[rows, cols];
var span = AsSpan<char>(array); // Create a span that encompasses all the elements of 'array' as a single span.
text.CopyTo(span); // Copy the text to the span; this will wrap at the correct places.
span.Slice(text.Length).Fill('X'); // Fill the remainder of the span with 'X'.
// Print the result.
for (int r = 0; r < rows; ++r)
{
for (int c = 0; c < cols; ++c)
{
Console.Write(array[r, c]);
}
Console.WriteLine();
}
}
public static Span<T> AsSpan<T>(Array array)
{
return MemoryMarshal.CreateSpan(
ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array)),
array.Length);
}
}
This outputs:
DELIC
IOUS
FOODX