Как создать массив с равноудаленными элементами?

Коллеги помогите придумать алгоритм.
Вроде все просто, но голова не варит;

Дано:
array(
A=3,
B=6,
C=9
)


Требуется сформировать массив из 18 элементов значения которых равны ключам входного массива,
их количество равно значению указанному в исходном массиве
Одинаковые значения находятся максимально далеко друг от друга

например ответ может быть таким:
CACBCBCBACBCBCACBC

UPDATE
Немного перефразирую задачу
Есть круг с 18 секторами
есть входные данные
красных = 3 сектора
желтых = 6 секторов
зеленых = 9 секторов
Нужно максимально равномерно разместить эти цветные сектора в круге.

UPDATE2
общая сумма значений исходного массива всегда равна 18. Минимальное значение входного элемента = 1
То-есть граничный случай входных данных
A=1
B=1
C=16

Заранее спасибо всем откликнувшимся
  • Вопрос задан
  • 373 просмотра
Решения вопроса 1
@volginn
вот такая идея у меня
например нам надо разместить:
9-А
6-В
3-С
во первых мы создаем массив который будет ответом
во вторых мы создаем массив в котором будут храниться пустые индексы в выходном массиве

и теперь собственно само заполнение:
идем от тех элементов которых больше к тем которых меньше
1)вставляем 9-А
вычисляем коэффицент = количество свободных мест в выходном массиве/ количество вставляемых элементов
К=18/9=2

на данный момент у нас такая штука

выходной массив
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
далее в 2,4,6,8,10,12,14,16,18 элементы вставляем А т.к. К=2

выходной массив
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
1 3 5 7 9 11 13 15 17

ВТОРОЙ ШАГ
считаем для В
К=9/6=1,5
получаются индексы для равномерности распределения стоит округлять в меньшую сторону
1,5=1
3=3
4,5=4
6=6
7,5=7
9=9
получается что по этим индексам в массиве пустых мест лежат индексы тех мест куда надо вставить В
получаем выходной массив такого вида
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
В А С А В А В А С А В А В А С А В А
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Mercury13
Программист на «си с крестами» и не только
Неплохие результаты получились с одной из первых версий с простейшим патчем на повторы.
#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;
}

Пишу на «си с крестами». Раз уж вы работаете на PHP, вместо указателей придётся держать «лучший индекс» и «последний индекс».

Принцип программы прост. Счётчики считают вниз с разной скоростью; чем чаще встречается сектор, тем быстрее. Приоритет взятия такой: не исчерпан → без повторов → у кого счётчик меньше → какой встречается чаще. Однако если какого-то сектора больше 50%, для него повторы вполне себе разрешены.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы