-4

I have a row that can contain up to N points. I want to distribute x points inside that row from the center outwards, using as little space.

I have managed to distribute points evenly within the row, but it uses all of the available space. Using the formula floor((i+0.5)*N/x), I get the following result, considering N=9:

4 
2 6 
1 4 7 
1 3 5 7 
0 2 4 6 8 
0 2 3 5 6 8 
0 1 3 4 5 7 8 
0 1 2 3 5 6 7 8 
0 1 2 3 4 5 6 7 8

The following is an example graphical representation of the indeces shown in the output above:

Evenly distributed on all sides

I want to basically restrict points from going too far outwards from the center, so I get a result more like:

4 
3 5 
3 4 5 
2 3 5 6 
2 3 4 5 6 
1 2 3 5 6 7 
1 2 3 4 5 6 7 
0 1 2 3 5 6 7 8 
0 1 2 3 4 5 6 7 8

The following is an example graphical representation of the indeces shown in the output above:

Distributed evenly restricted from center

I'm using Java and this is my current code

int rowLength = 9;

for (int points = 0; points <= rowLength; points++) {
    for (float i = 0; i < points; i++) {
        double result = Math.floor((i + 0.5) * rowLength / points);

        System.out.print((int) result + " ");
    }

    System.out.println();
}

How can I best achieve the result shown in the second image so that the output from my code matches that of the second example output?

driima
  • 623
  • 1
  • 11
  • 28
  • a) I'm asking how to get what I want, because I haven't managed to go further than what I have despite my efforts. b) the pictures are a graphical representation of the output provided. – driima Dec 17 '19 at 16:40
  • 1
    I have updated the question to make it as clear as I possibly can. – driima Dec 17 '19 at 16:51
  • 2
    What about rowLength = 8? Where do you expect the indices to be? There is no middle. – Thomas Weller Dec 17 '19 at 16:53
  • That's a good point. If rowLength = 8, or any even number rowLength, my code doesn't work. Ideally though, I only want to care about odd numbers. – driima Dec 17 '19 at 17:06

1 Answers1

0

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();
}
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222