D
D
Denis2016-11-10 14:04:39
Algorithms
Denis, 2016-11-10 14:04:39

How to create an array with equidistant elements?

Colleagues help me come up with an algorithm.
Everything seems to be simple, but the head does not cook;
Given:

array(
A=3,
B=6,
C=9
)

It is required to form an array of 18 elements whose values ​​are equal to the keys of the input array, their number is
equal to the value specified in the source array
The same values ​​are as far apart as possible,
for example, the answer may be: 3 yellow sectors = 6 green sectors = 9 sectors It is necessary to place these colored sectors as evenly as possible in the circle. UPDATE2 the total sum of the values ​​of the original array is always 18. The minimum value of the input element = 1 i.e. the edge case of the input data A=1


B=1
C=16
Thanks in advance to all who responded

Answer the question

In order to leave comments, you need to log in

2 answer(s)
V
volginn, 2016-11-10
@cjbars

I have such an idea,
for example, we need to place:
9-A
6-B
3-C
firstly we create an array that will be the answer
secondly we create an array in which empty indices in the output array will be stored
and now the filling itself: we
go from those elements of which are more to those of which there are less
1) insert 9-A
calculate the coefficient = the number of free places in the output array / the number of elements to be inserted
K=18/9=2
at the moment we have such a thing
output array
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
array of empty indices in output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
further in 2,4,6,8,10,12, 14,16,18 elements are inserted K=2
output array
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
A A A A A A A A A
array of empty indices in output
1 2 3 4 5 6 7 8 9
1 3 5 7 9 11 13 15 17
SECOND STEP
counting for B
K=9/6=1.5
we get indices for uniform distribution, it is worth rounding down
1.5=1
3=3
4.5=4
6=6
7.5=7
9=9
it turns out that these indices in the array empty places are the indices of those places where it is necessary to insert B, we
get an output array of this type
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 times for the triple, we get the same output array 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
B A C A B A B A C A B A B A C A B A

M
Mercury13, 2016-11-10
@Mercury13

Good results were obtained with one of the first versions with the simplest patch for repetitions.

#include <iostream>

struct Sector
{
    char name;
    int total, counter, remainder;
    bool allowNearby;
};

enum { N = 3 };
Sector secs[] { { 'A', 3 }, { 'B', 6 }, { 'C', 30 } };

int main()
{
    int nTotal = 0;
    for (int i = 0; i < N; ++i) {
        Sector& sec = secs[i];
        nTotal += sec.total;
    }
    for (int i = 0; i < N; ++i) {
        Sector& sec = secs[i];
        sec.counter = sec.total;
        sec.remainder = sec.total;
        sec.allowNearby = (sec.total * 2 > nTotal);
    }

    Sector* repeatS = nullptr;
    for (int iSec = 0; iSec < nTotal; ++iSec) {
        Sector* bestS = nullptr;
        for (int i = 0; i < N; ++i) {
            Sector& sec = secs[i];
            if (sec.remainder != 0 && &sec != repeatS) {
                if (!bestS) {   // первый подходящий?
                    bestS = &sec;
                } else {    // лучше bestS?
                    if (sec.counter < bestS->counter
                            || (sec.counter == bestS->counter && sec.total > bestS->total))
                        bestS = &sec;
                }
            }
        }
        if (!bestS)     // так и не нашли, что брать — берём repeatS
            bestS = repeatS;

        // пересчитаем счётчик и остаток
        bestS->counter += nTotal * 2;
        --bestS->remainder;

        for (int i = 0; i < N; ++i) {
            Sector& sec = secs[i];
            sec.counter -= sec.total * 2;
        }
        repeatS = bestS->allowNearby ? nullptr : bestS;
        std::cout << bestS->name;
    }
    std::cout << std::endl;
}

I write in "si with crosses". Since you are working in PHP, instead of pointers, you will have to keep "best index" and "last index".
The principle of the program is simple. Counters count down at different speeds; the more common the sector, the faster. The priority of taking is: not exhausted → no repetitions → who has a counter less → which is more common. However, if some sector has more than 50%, repetitions are quite allowed for it.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question