Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Подсчет равных хеш-таблиц, Элегантное решение 
V
    Опции темы
Danissimo
Дата 6.2.2007, 01:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Постановка задачи:

Дано множество хеш-таблиц L = { h(i) }, где h(i) -- i-тый элемент или, другими словами, i-тая хеш-таблица.
Для h(i) задано множество ее ключей K(i) = { k(i, 0), k(i, 1), ... }. Множества ключей могут пересекаться, а могут и нет, то есть

K(i) * K(j) = ?, i != j.

Значениями ключей таблицы h(i) является множество V(i) = { v(i, 0), v(i, 1), ... }, такое, что k(i, 0) => v(i, k(i, 0)), k(i, 1) => v(i, k(i, 1)), ...

(Я знаю, что вы все это знаете. Мне нужно подойти к заданию.)

Табицы h(i) и h(j) считаются равными, если для пересечения множества ключей R = K(i) * K(j) = { r(0), r(1), ... }, значения ключей из полученного множества равны:

v(i, r(0)) == v(j, r(0)) и
v(i, r(1)) == v(j, r(1)), и
v(i, r(2)) == v(j, r(2)), и т. д.

Напрмер, если

K(i) = { k(i, a), k(i, b), k(i, x), k(i, y) },
K(j) = { k(j, c), k(j, b), k(j, x), k(j, z) },
R = K(i) * K(j) = { r(b), r(x) },

то h(i) == h(j), если v(i, r(b)) == v(j, r(b)) и v(i, r(x)) == v(j, r(x)).

Множество L считать упорядоченым (то есть списком; не путать с отсортированным). Для определенности обход начинать с начала списка.

Необходимо удалить из L все h(j), для которых h(i) == h(j), i < j, добавляя к h(i) ключ c(i), значение которого равно количеству хеш-таблиц h(j), равных h(i). Если h(i) == h(j) и h(k) == h(j), где i < j < k, то счетчик совпадений увеличивать для h(i), но для h(k).

Задача не детерминирована, так как в зависимости от того, как пересекаются множества ключей таблиц, а также в зависимости от их упорядоченности в начале обхода, можно получить разные результаты.

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


Теперь про решение ;)

Я смог решить детерминированную (!) задачу (в которой у всех таблиц множества ключей одинаковые) лишь вложенными циклами:
Код

my @L = (
    { a => 'a',   b => 'b', c => undef },
    { a => 'a',   b => 'b', c => 'c' },
    { a => undef, b => 'b', c => 'c' },
    { a => 'a',   b => 'b', c => 'c' },
    { a => 'a',   b => 'b', c => 'c' },
    { a => 'a',   b => 'b', c => undef }
);
my @R = qw(a b c);

foreach my $i (0..$#L) {
    next if !$L[$i];
    my %hi = %{$L[$i]};
    my $cnt = 1;
    foreach my $j ($i + 1..$#L) {
        next if !$L[$j];
        my %hj = %{$L[$j]};
        my $notEqual = 0;
        foreach (@R) {
            unless ((!defined $hi{$_} and !defined $hj{$_})
                or (defined $hi{$_} and defined $hj{$_} and $hi{$_} eq $hj{$_})) {
                $notEqual = 1;
                last;
            }
        }
        unless ($notEqual) {
            $cnt += 1;
            delete $L[$j];
        }
    }
    $L[$i]->{cnt} = $cnt;
}

foreach (@L) {
    next if !$_;
    my %x = %$_;
    print join(', ', map { "$_ => " . ($x{$_} || 'false') } keys %x) . "\n";
}

И это работает ну очень медленно. Я уже не говорю про общую задачу.

Можете ли предложить более элегантное решение?
PM MAIL   Вверх
JAPH
Дата 6.2.2007, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 3
Всего: 23



Приведу моё решение. Насчёт скорости - не знаю, максимальный уровень вложенности циклов 3.
Код

use strict; use warnings;    
my @L = ({ a => 'a',   b => 'b', c => undef },    
         { a => 'a',   b => 'b', c => 'c' },    
         { a => undef, b => 'b', c => 'c' },    
         { a => 'a',   b => 'b', c => 'c' },    
         { a => 'a',   b => 'b', c => 'c' },    
         { a => 'a',   b => 'b', c => undef });    
my @Q = ();    
while (my $l = @L) {    
    my $L = shift @L;    
    @L = grep { notequal($_, $L) } @L;    
    push @Q, { %$L, 'count' => $l - @L }    
}    
foreach my $Q(@Q) {    
    print join(', ', map { $_ . ' => ' . (defined $$Q{$_} ? $$Q{$_} : 'undef') } keys %$Q ) . "\n"    
}    
sub notequal {    
    no warnings;    
    $_[0]{$_} ne $_[1]{$_} ? return 1 : 1 foreach grep { exists $_[1]{$_} } keys %{$_[0]};    
    return 0    
}


Это сообщение отредактировал(а) JAPH - 6.2.2007, 12:29


--------------------
Что непонятно - спрашиваем smile
PM MAIL ICQ   Вверх
Danissimo
Дата 6.2.2007, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Класс!!! Мало того, что понятнее, красивее, так еще на 50% быстрее. Отличный результат. Спасибо =)

Добавлено @ 21:27 
Смотри-ка какие классные программеры во Всеволожске обитают =)
PM MAIL   Вверх
tishaishii
Дата 13.2.2007, 00:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Создатель
***


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

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



Быстрее:
Код
sub notequal {
    no warnings;
    +grep {exists $_[1]{$_} && $_[0]{$_} ne $_[1]{$_}} keys %{$_[0]}
}
my @L = ({ a => 'a',   b => 'b', c => undef },
         { a => 'a',   b => 'b', c => 'c' },
         { a => undef, b => 'b', c => 'c' },
         { a => 'a',   b => 'b', c => 'c' },
         { a => 'a',   b => 'b', c => 'c' },
         { a => 'a',   b => 'b', c => undef });
my(@Q, $L, $l);
while ($l=@L) {
    $L=shift @L;
    @L=grep{notequal($_, $L) }@L;
    push @Q, {%$L, 'count' =>$l-@L}
}
print join(', ', map { $_ . ' => ' . (defined $$_{$_} ? $$_{$_} : 'undef') } keys %$_ ) . "\n" foreach @Q;

PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


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

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


 




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


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

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