Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Интересная задача, Нужен алоритм для решения задачи 
:(
    Опции темы
sQu1rr
Дата 26.1.2015, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: нет
Всего: 13



Здравствуйте уважаемы программисты

Сегодня столкнулся с задачей, для решения которой не могу придумать алгоритм.
Вот упрощенная версия

Есть некий массив
Код

[[1,2,3],[4,5],[5,6],[1,4,6]]


Нужно убрать дубликаты из внутренних массивов, но не оставлять их пустыми
Код

[[1,2,3],[4],[5],[6]]


Это был очень простой пример. Сложность начинается когда один элемент появляется в трех или более массивах. Сложно определить, какой элемент убрать из какого массива. Оптимальный результат - минимальное кол-во дубликатов (который нужно оставлять только в случае если без него получится пустой массив).

Почему то мне кажется что попахивает графами, но какими именно понять не могу.
Спасибо

Пример глупого алгоритма который я хочу избежать (шаг 1 - оставляем уникальные, шаг 2 - добавляем в пустые без какой либо логики, последовательно)
Код

[[1,2,3],[5,6],[1,4,6],[4,5]] # Оригинал
[[1,2,3],[],[],[]] # Шаг 1
[[1,2,3],[5,6],[4],[4 или 5]] # Шаг 2

PM MAIL Skype GTalk   Вверх
Akina
Дата 26.1.2015, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Задача недоопределена. Допускаю, что из всех возможных конечных вариантов можно выбрать любой, но что делать, если конечного варианта без дубликата не существует (напр., 3 массива с элементами 1 и 2)?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
sQu1rr
Дата 26.1.2015, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: нет
Всего: 13



Цитата(Akina @  26.1.2015,  13:13 Найти цитируемый пост)
Допускаю, что из всех возможных конечных вариантов можно выбрать любой

да


Цитата(Akina @  26.1.2015,  13:13 Найти цитируемый пост)
если конечного варианта без дубликата не существует (напр., 3 массива с элементами 1 и 2)? 

значит будет либо что-то вроде [1],[2],[1] или 1,2,2
Главное - минимальное кол-во дубликатов, и что бы все элементы присутсвовали хотя бы один раз
PM MAIL Skype GTalk   Вверх
baldina
Дата 26.1.2015, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 4
Всего: 101



если объединить массивы в граф, то достаточно построить остовное дерево. элементы, образующие циклы, удалятся.

PM MAIL   Вверх
sQu1rr
Дата 26.1.2015, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: нет
Всего: 13



Цитата(baldina @  26.1.2015,  14:42 Найти цитируемый пост)
если объединить массивы в граф

Можно поподробнее? Именно этот момент меня и путает. что здесь будет вершинами и что ребрами?
PM MAIL Skype GTalk   Вверх
baldina
Дата 26.1.2015, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 4
Всего: 101



user posted image
красным - удаляемые ребра. нужно следить, что бы в результате удаления средние узлы не превращались листья  (иначе получатся пустые массивы)
PM MAIL   Вверх
sQu1rr
Дата 26.1.2015, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: нет
Всего: 13



Понял, спасибо, попробую отпишусь  smile

Добавлено @ 18:28
Так проблема в том что тут же зависит от того в какой последовательности я парсю граф, вот у вас, явно было слева направо, так все получается правильно. А если пойти справа налево, то получится как у меня в примере.

Цитата(baldina @  26.1.2015,  15:16 Найти цитируемый пост)
нужно следить, что бы в результате удаления средние узлы не превращались листья  (иначе получатся пустые массивы) 

Как раз вот тут вот у меня и проблема. скажем строю я дерево, наткнулся на такой результат, мне что, откатывать изменения? и до куда? это в итоге в брутфорс превратится

Я чего то не понимаю да?

ЗЫ можно вас попросить в след. раз картинку на форум выкладывать (кроме как ссылкой) как прикрепленный файл, для меня если. На работе блокировка на неизвесные/непроверенные сайты

Это сообщение отредактировал(а) sQu1rr - 26.1.2015, 18:31
PM MAIL Skype GTalk   Вверх
Akina
Дата 27.1.2015, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Давайте определим несколько моментов.
1) Задача - реальная или учебная?
2) Каково максимально возможное количество групп?
3) Каково максимально возможное количество элементов?
Дело в том, что есть подозрение, что задача-то - полненькая... при небольшом количестве элементов и групп вполне можно обойтись и полным перебором.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
sQu1rr
Дата 27.1.2015, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: нет
Всего: 13



Цитата(Akina @  27.1.2015,  09:27 Найти цитируемый пост)
Задача - реальная или учебная?

Скажем так, задача учебная для друга, для меня - чистый интерес, хочется найти способ решить не перебором, для себя.

Цитата(Akina @  27.1.2015,  09:27 Найти цитируемый пост)
2) Каково максимально возможное количество групп?
3) Каково максимально возможное количество элементов?
Дело в том, что есть подозрение, что задача-то - полненькая... при небольшом количестве элементов и групп вполне можно обойтись и полным перебором.

Разумеется можно, и, скорее всего, задача это подрузамевает. Но вопрос для меня - можно ли решить не перебором. Пусть не за полин. время, но и не за экспоненту
PM MAIL Skype GTalk   Вверх
baldina
Дата 27.1.2015, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 4
Всего: 101



Цитата(Akina @  27.1.2015,  12:27 Найти цитируемый пост)
есть подозрение, что задача-то - полненькая

ага

вобщемто остовный граф тут скорее всего бесполезен, т.к. графов этих может быть много, а нужны только с определенными свойствами (числа всегда листья, листья только числа), которые через веса дуг никак не выразить. раз удалению подлежат определенные ребра, весь граф не требуется.
PM MAIL   Вверх
Akina
Дата 27.1.2015, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



В принципе задачу можно перевести в матричную.
Есть прямоугольная матрица. Столбцы - элементы, строки - группы. Если элемент в группе - на пересечении 1, иначе 0. Задача - удалить (заменить нулями) максимально возможное количество единиц так, чтобы в каждом столбце и каждой строке осталось не менее одной единицы.

Добавлено через 3 минуты и 24 секунды
Эмпирически можно пойти приблизительно по такому пути (типа жадный алгоритм) - ищем единицу такую, чтобы суммарное количество единиц в её строке и её столбце было максимально по матрице, но по отдельности не было единичным. Заменяем на ноль. Повторяем до тех пор, пока удаётся удалять. Способ не гарантирует оптимума, но даст близкое к нему решение, и достаточно быстр.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
sQu1rr
Дата 27.1.2015, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: нет
Всего: 13



Интересно, приду домой пораскину мозгами, спасибо
PM MAIL Skype GTalk   Вверх
sQu1rr
Дата 29.1.2015, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: нет
Всего: 13



Решил так кому интересно. Можно оптимизировать, но решение думаю понятно (работает со всеми моими тестами по крайней мере). Приду домой опишу логику
Код

def test_algo( tests, index = None):
    if not index:
        for index, test in enumerate( tests ):
            print '#', index, ' ======================'
            print 'Solving: ', test
            print 'Result:  ', algo( copy.deepcopy( test ) )
            print '==========================='
    else:
        print '#', index, ' ======================'
        print 'Solving: ', tests[ index ]
        print 'Result:  ', algo( copy.deepcopy( tests[ index ] ) )
        print '==========================='
    
def algo_group( flat_test, test ):
    group = dict( ( key, [] ) for key in flat_test )
    for index, test_group in enumerate( test ):
        for key in test_group:
            group[ key ].append( index )
    return group

def remove_duplicates( test ):
    seen     = set()
    seen_add = seen.add
    return [ x for x in test if not ( x in seen or seen_add( x ) ) ]
            
def remove_group_duplicates( test ):
    for test_group in test:
        remove_duplicates( test_group )
        
def has_empty( output ):
    for group in output:
        if not len( group ):
            return True
    return False

def has_unique( group ):
    for length in group.values():
        if len( length ) == 1:
            return True
    return False
    
def add_unique( output, group ):
    keys = group.keys()
    for key in keys:
        if len( group[ key ] ) == 1:
            group_index = group[ key ][0]
            output[ group_index ].append( key )
            del group[ key ]
            for groups in group.values():
                if len( groups ) > 1 and group_index in groups:
                    groups.remove( group_index )
            
def add_loop( output, test, group ):
    temp_test  = copy.deepcopy( test )
    temp_group = copy.deepcopy( group )

    path = find_loop( temp_test, temp_group, [], 0 )
    if path == 'False':
        raise 'Cannot find solution'
    else:
        for out_group, key in path:
            output[ out_group ].append( key )
            for groups in group.values():
                if len( groups ) > 1 and out_group in groups:
                    groups.remove( out_group )
    
def find_loop( test, group, path, index ):
    test_indices = test[ index ]
    for key in test_indices:
        test[ index ].remove( key )
        group[ key ].remove( index )
        indices = group[ key ]
        for group_index in indices:
            if not key in test[ group_index ]:
                continue
            test[ group_index ].remove( key )
            path.append( ( group_index, key ) )
            if group_index == 0:
                return path
            else:
                result = find_loop( test, group, path, group_index )
                if result != False:
                    return result
            path.remove( ( group_index, key ) )
            test[ group_index ].append( key )
        group[ key ].append( index )
        test[ index ].append( key )
    return False
        
def algo( test ):
    remove_group_duplicates( test )
    
    flat_test = sum( test, [] )
    group      = algo_group( flat_test, test )
    
    output    = [ [] for _ in xrange( len( test ) ) ]
    while has_empty( output ):
        while has_unique( group ):
            add_unique( output, group )
        if has_empty( output ):
            add_loop( output, test, group )
            
    final_output = [ [] for _ in xrange( len( test ) ) ]
    group = algo_group( flat_test, test )
    for index, test_group in enumerate( test ):
        for key in test_group:
            if key in output[ index ] and ( len( group[ key ] ) == 1 or len( final_output[ index ] ) == 0 ):
                final_output[ index ].append( key )
        
    return final_output


Код

test_algo([[[1, 2, 3], [4, 5], [5, 6], [1, 4, 6]], [[1, 2, 3], [5, 6], [1, 4, 6], [4, 5]], [[1, 2], [1, 2], [1, 2]], [[1, 1, 5, 8], [5], [3], [6, 3, 1]], [[17133159, 12777590, 9402381], [9402381, 17133159], [9402381], [8953819]]])


Это сообщение отредактировал(а) sQu1rr - 29.1.2015, 15:35
PM MAIL Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.0627 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.