Генерация шаров в коробках - PullRequest
2 голосов
/ 19 июня 2010

Учитывая два отсортированных вектора a и b, найдите все векторы, которые являются суммами a и некоторой перестановкой b и которые являются уникальными после сортировки.

Вы можете создать один из искомых векторов следующим образом:

  • Взять вектор a и перестановку вектора b.
  • Суммируйте их вместе, чтобы c[i]=a[i]+b[i].
  • Сортировка c.

Мне интересно найти набор b -перестановок, которые дают полный набор уникальных c векторов.

Пример 0 : a='ccdd' и b='xxyy'
Дает суммированные векторы: 'cycydxdx', 'cxcxdydy', 'cxcydxdy'.
Обратите внимание, что перестановки b: 'xyxy' и 'yxyx' равны, потому что в обоих случаях «коробка c» и «коробка d» оба получают ровно одну 'x' и одну 'y'.

Полагаю, это похоже на помещение M шаров в M коробки (по одному в каждой) с некоторыми группами шаров и коробок, которые идентичны.
Обновление: Учитывая строку a='aabbbcdddd' и b='xxyyzzttqq', ваша задача будет 10 шариков в 4 коробках. Имеются 4 разных коробки размером 2, 3, 1 и 4. Шарики попарно неразличимы.

Пример 1: Заданы следующие строки: a='xyy' и b='kkd'.
Возможное решение: 'kkd', 'dkk'.
Причина: Мы видим, что все уникальные перестановки b являются 'kkd', 'kdk' и 'dkk'. Однако, с нашими ограничениями, две первые перестановки считаются равными как индексы, по которым отличия отображаются на один и тот же символ 'y' в строке a.

Пример 2: Заданы следующие строки: a='xyy' и b='khd'.
Возможное решение: 'khd', 'dkh', 'hkd'.

Пример 3: Заданы следующие строки: a='xxxx' и b='khhd'.
Возможное решение: 'khhd'.

Я могу решить проблему генерации уникальных кандидатов b перестановок, используя алгоритм Нараяны Пандиты, описанный в Википедия / Перестановка .
Вторая часть швов сложнее. Мой лучший способ - соединить две строки попарно в список, отсортировать их и использовать в качестве ключа в наборе поиска. ('xx' + 'hd' объединение → 'xh','xd' сортировка → 'xd','xh').

Поскольку мой M часто очень велик, и поскольку сходства в строках являются общими, в настоящее время я генерирую гораздо больше b перестановок, чем на самом деле проходит через установленный фильтр. Я хотел бы иметь алгоритм, генерирующий правильные напрямую. Любые улучшения приветствуются.

Ответы [ 2 ]

2 голосов
/ 19 июня 2010

Для генерации k-комбинаций возможно повторяющихся элементов (мультимножества) может быть полезно следующее: Код Грея для комбинаций мультимножества (1995) .

Для рекурсивного решенияВы пытаетесь сделать следующее:

Подсчитайте, сколько раз появляется каждый символ.Скажем, они x1 x2 ... xm, что соответствует m различным символам.

Затем вам нужно найти все возможные упорядоченные пары (y1 y2 ... ym), такие что

0 <=yi <= xi </p>

и Sum yi = k.

Здесь yi - количество раз, которое символ я появляется.

Идея состоит в том, чтобы зафиксировать количество раз char 1появляется (y1).Затем рекурсивно сгенерируйте все комбинации k-y1 из оставшихся.

psuedocode:

List Generate (int [] x /* array index starting at 1*/, 
               int k /* size of set */) {

    list = List.Empty;

    if (Sum(x) < k) return list;

    for (int i = 0; i <= x[1], i++) {

        // Remove first element and generate subsets of size k-i.

        remaining = x.Remove(1);

        list_i = Generate(remaining, k-i);

        if (list_i.NotEmpty()) {

            list = list + list_i;    

        } else {

            return list;
        }

    }

    return list;
}

ДО РЕДАКТИРОВАНИЯ:

Если я правильно понял, вынужно посмотреть на строку а, увидеть символы, которые появляются ровно один раз.Скажем, есть k таких символов.Затем вам нужно сгенерировать все возможные перестановки b, которые содержат k элементов и отображаются на эти символы в соответствующих позициях.Остальное вы можете игнорировать / заполнять по своему усмотрению.

Я помню, как разместил здесь код C # для этого: Как найти перестановку k в заданной длине?

Я предполагаю, что xxyy выдаст только 1 уникальную строку, а те, которые появляются ровно один раз, являются «отличительными» точками.

Например, в случае a=xyy, b=add

отличительная точка равна x

Таким образом, вы выбираете перестановки «сложения» длины 1. Это дает вам a и d.

Таким образом, add и dad (or dda) - это те, которые вам нужны.

Для a=xyyz b=good

отличительными точками являются x и z

Таким образом, вы генерируете перестановки b длины 2, давая

go
og
oo
od
do
gd
dg

, давая вам 7 уникальных перестановок.

Это помогает?Правильно ли мое понимание?

0 голосов
/ 21 июня 2010

Хорошо, извините, я так и не смог четко объяснить проблему, но вот решение.

Нам нужны две функции combinations и runvector(v).combinations(s,k) генерирует уникальные комбинации мультимножества длины k.Для s='xxyy' это будет ['xx','xy','yy'].runvector(v) преобразует мультимножество, представленное в виде отсортированного вектора, в более простую структуру - вектор выполнения.runvector('cddeee')=[1,2,3].

Для решения проблемы мы будем использовать рекурсивные генераторы.Мы проходим через все комбинации, которые вписываются в box1 и обращаемся к остальным блокам, забаняя значения, которые мы уже выбрали.Чтобы выполнить запрет, combinations будет поддерживать битовый массив вызовов.

В python подход выглядит следующим образом:

def fillrest(banned,out,rv,b,i):
    if i == len(rv):
        yield None
        return
    for comb in combinations(b,rv[i],banned):
        out[i] = comb
        for rest in fillrest(banned,out,rv,b,i+1):
            yield None

def balls(a,b):
    rv = runvector(a)
    banned = [False for _ in b]
    out = [None for _ in rv]
    for _ in fill(out,rv,0,b,banned):
        yield out[:]

>>> print list(balls('abbccc','xyyzzz'))
[['x', 'yy', 'zzz'],
 ['x', 'yz', 'yzz'],
 ['x', 'zz', 'yyz'],
 ['y', 'xy', 'zzz'],
 ['y', 'xz', 'yzz'],
 ['y', 'yz', 'xzz'],
 ['y', 'zz', 'xyz'],
 ['z', 'xy', 'yzz'],
 ['z', 'xz', 'yyz'],
 ['z', 'yy', 'xzz'],
 ['z', 'yz', 'xyz'],
 ['z', 'zz', 'xyy']]

Вывод в формате 'box', но можетлегко объединить в простые строки: 'xyyzzzz', 'xyzyzz' ...

...