Ok, let’s look at the picture. To me, it seems there are a few rows that have something in common:
Observations:
- The blue lines have the middle point filled, the orange ones have the middle empty.
- The blue ones have odd numbers, the orange ones have even numbers.
- The space on the left is
- in the odd case:
(rowLength - points)/2
, e.g. (9-1)/2 = 4 - in the even case:
(rowLength -points -1)/2
, e.g. (9-2-1)/2 = 3
- in the odd case:
Let’s put that into code. I use C# here, but Java should be very similar:
int rowLength = 9;
for (int points = 0; points <= rowLength; points++) {
bool isOdd = points%2 == 1;
if (isOdd)
{
int spaceOnSide = (rowLength-points)/2;
for (int i=0; i<points;i++)
{
Console.Write(""+(i+spaceOnSide)+" ");
}
}
else // even
{
int spaceOnSide = (rowLength-1-points)/2;
for (int i=0; i<points/2;i++)
{
Console.Write(""+(i+spaceOnSide)+" ");
}
for (int i=points/2; i<points;i++)
{
Console.Write(""+(i+spaceOnSide+1)+" ");
}
}
Console.WriteLine();
}
This is very straight forwards, just as the observations tell us.
Given that code, we can use some tricks:
-
Due to integer division, the line
int spaceOnSide = (rowLength-1-points)/2;
gives the same result as
int spaceOnSide = (rowLength-points)/2;
(without -1).
-
We can split the for loop in the odd case into two pieces:
for (int i=0; i<points/2;i++) { Console.Write(""+(i+spaceOnSide)+" "); } for (int i=points/2; i<points;i++) { Console.Write(""+(i+spaceOnSide)+" "); }
This sounds counter-productive at first, but look at step 3.
-
With that change done, the odd part and the even part look very similar. It’s really duplicate code. The only difference is in the
+1
part. We can add the if-statement there as a ternary operator:for (int i=0; i
-
If you dislike the ternary operator, you can get rid of it:
(isOdd?0:1)
is equal to
(points+1)%2
In the end you have code as simple as
int rowLength = 9;
for (int points = 0; points <= rowLength; points++) {
int spaceOnSide = (rowLength-points)/2;
for (int i=0; i<points/2;i++)
{
Console.Write(""+(i+spaceOnSide)+" ");
}
for (int i=points/2; i<points;i++)
{
Console.Write(""+(i+spaceOnSide+(points+1)%2)+" ");
}
Console.WriteLine();
}
solved Distribute points in a row using as little space as possible