[Solved] Distribute points in a row using as little space as possible


Ok, let’s look at the picture. To me, it seems there are a few rows that have something in common:

Coloured image

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

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:

  1. Due to integer division, the line

    int spaceOnSide = (rowLength-1-points)/2;
    

    gives the same result as

    int spaceOnSide = (rowLength-points)/2;
    

    (without -1).

  2. 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.

  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

  4. 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