[devel] Утилиты для работы с setversions?
Alexey Tourbin
alexey.tourbin на gmail.com
Ср Окт 30 18:12:45 MSK 2019
On Wed, Oct 30, 2019 at 12:06 PM Andrey Savchenko <bircoph на altlinux.org>
wrote:
>
> On Wed, 30 Oct 2019 05:04:27 +0300 Alexey Tourbin wrote:
> > On Tue, Oct 29, 2019 at 9:23 PM Andrey Savchenko <bircoph на altlinux.org>
wrote:
> > > К сожалению, для решения реальной проблемы этого недостаточно:
> >
> > Давайте решим реальную проблему. Что вы хотите сделать? Left outer join?
>
> Задача следующая:
>
> 1) Есть библиотека foo-1.0
> 2) Она обновилась до foo-1.0.1
> 3) Возник unmet пакета bar на libfoo.so (>= set:abcdef)
>
> Мне нужно знать, каких именно символов из foo стало не хватать bar.
Ну и чево? Есть set-версия R и есть множества строк P0 и P1. P0
удовлетворяет R, а P1 - не удовлетворят (какие-то строки из P1 удалили).
Есть готовые примитивы как это распаковать в массивы, как показано на
рисунке.
P0 P1 R
+----+----+ +----+----+ +----+
| h0 | s0 | | h0 | s0 | | h0 |
+----+----+ +----+----+ +----+
| h1 | s1 | | h2 | s2 | | h1 |
+----+----+ +----+----+ +----+
| h2 | s2 | | h3 | s3 | | h3 |
+----+----+ +----+----+ +----+
| h3 | s3 | | h4 | s4 |
+----+----+ +----+----+
На рисунке видно, что в новой версии P1 удалился символ s1 с хешем h1 (а
добавился символ s4 с хешем h4). Как тогда систематически напечатать
недостающие символы? Внешний цикл будет по R: для каждого хеша в R мы
смотрим, есть ли такой же хеш в P1. Если есть, то он удовлетворен, и
проблемы нет. А иначе он неудовлетворен, тогда нам нужно найти символ с
таким же хешем в P0 и его напечатать. В общем, с непривычки написать такой
цикл может и сложновато, но если думать логически, то ничего невозможного в
этом нет. Главное не пытаться каждый раз искать в P1 и P0 с самого начала,
тогда получится квадратичная сложность. Чтобы осталась линейная сложность,
нужно "подтягивать" P0 и P1 с прошлых итераций (алгоритмы такого рода,
"подтягивания" нескльких отсортированных списков, называются merge
algorithms). Для этого введем переменные P1h - текущий хеш, P1i -
следующий индекс, по принципу P1h = P1[P1i++].v, аналогично для P0. Тогда
цикл получается таким:
size_t P0i = 0;
size_t P1i = 0;
uint32_t P0h = P0[P0i++].v;
uint32_t P1h = P1[P1i++].v;
for (size_t i = 0; i < Rn; i++) {
uint32_t Rh = R[i];
// advance P1
while (P1h < Rh && P1i < P1n)
P1h = P1[P1i++].v;
// does P1 satisfy Rh?
if (P1h == Rh)
continue;
// advance P0
while (P0h < Rh && P0i < P0n)
P0h = P0[P0i++].v;
// P0 then must satisfy Rh
assert(P0h == Rh);
// print the symbol associated with P0h
fputs(P0[P0i-1].s, stdout);
// more than one symbol may hash to Rh,
// print them on the same line
while (P0i < P0n && (P0h = P0[P0i++].v) == Rh)
putchar(' '), fputs(P0[P0i-1].s, stdout);
putchar('\n');
}
Прикрепил полный пример. В общем, главное логически мыслить. Спросите там у
Евгенича, он вам скажет.
# Usage: unset P0.txt P1.txt set:R
$ ./unset <(print -l a b c) <(print -l a b d) $(print -l a c
|/usr/lib/rpm/mkset 10)
c
----------- следующая часть -----------
Вложение в формате HTML было удалено...
URL: <http://lists.altlinux.org/pipermail/devel/attachments/20191030/50339d34/attachment-0001.html>
Подробная информация о списке рассылки Devel