Let's say I have the following input:
string input = "123456789";
and expect the following output:
string output = "741852963";
The logic is a square which needs to be turned by 90 degrees to the right - but without linebreak.
// squares
//INPUT OUTPUT
// 123 ══╗ 741
// 456 V 852
// 789 963
The width should be dynamic and always
int width = (int)Math.Sqrt(input.Length);
Is there a easy approach to solve this?
personally I would prefer for
loop, but there is a Linq
solution also
try it with Fiddle
string input = "0123456789ABCDEF";
/*
0123
4567
89AB
CDEF
*/
int width = (int)Math.Sqrt(input.Length);
var seq = input.AsEnumerable()
.Select((c, i) => new {Chr = c, Row = i / width, Col = i % width})
.OrderBy(a => a.Col)
.ThenByDescending(a => a.Row)
.Select(a=>a.Chr);
var s = string.Join("", seq);
Console.WriteLine(s);
prints
C840D951EA62FB73
How about:
void Main()
{
var input = "123456789";
var size = (int)Math.Sqrt(input.Length);
var table = new char[size, size];
for (var i = 0; i < input.Length; ++i)
{
table[i / size, i % size] = input[i];
}
var result = new StringBuilder();
for (var i = 0; i < size; ++i)
{
for (var j = size - 1; j >= 0; --j)
{
result.Append(table[j, i]);
}
}
Console.WriteLine(result.ToString());
}
Well I had fun with this one:
const string input = "123456789";
string toFill = "";
int offset = 0;
int upTo = (int) Math.Sqrt(input.Length);
while (offset < upTo )
{
string temp = "";
for (int i = 0; i < input.Length; i = i + upTo)
{
temp += input[i + offset];
}
offset++;
toFill += new string(temp.Reverse().ToArray()); ;
}
It works but don't use linq :(
Sort solution provided by ASh is perfect, there is nothing to add there.
But there is an interesting comment by Enigmativity saying "This is more of a mapping than a sort", so let give it a try.
What we have here is
int length = input.Length;
int width = (int)Math.Sqrt(length);
int height = (length + width - 1) / width;
and for each index i1
in range [0, length-1]
we define a transformation to another index i2
in the same range as follows
int x1 = i1 % width;
int y1 = i1 / width;
int x2 = height - 1 - y1;
int y2 = x1;
int i2 = y2 * height + x2;
Now let make the inverse transformation of the above
int x2 = i2 % height;
int y2 = i2 / height;
int x1 = y2;
int y1 = height - 1 - x2;
int i1 = width * y1 + x1;
which after substitutions becomes
int i1 = width * (height - 1 - i2 % height) + i2 / height;
With all that in mind, here is the "map" Linq solution:
string input = "123456789";
int length = input.Length;
int width = (int)Math.Sqrt(length);
int height = (length + width - 1) / width;
var output = new string(
Enumerable.Range(0, length)
.Select(i => input[width * (height - 1 - i % height) + i / height])
.ToArray());
Of course LINQ is no sense here, we can avoid introducing closures and do the same with the same or less amount of "normal" code lines, and as a bonus having a sweet choice of using the inverse transformation as above
var result = new char[length];
for (int i = 0; i < result.Length; i++)
result[i] = input[width * (height - 1 - i % height) + i / height];
var output = new string(result);
or the direct transformation (after substitution and simplification)
for (int i = 0; i < result.Length; i++)
result[height * (i % width + 1) - (i / width + 1)] = input[i];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With