October 2008 Archives

$c->forward() возвращает истину

$c->forward() возвращает только истину. Истину в последней инстанции :)

А серьезно, он может вернуть лишь одно значение. И оно должно быть истинно. Если оно ложно - результатом будет ноль. И неважно, что вы хотели вернуть пустую строку или undef. Вернется ноль.

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

Вот собственно и всё :) Теперь чуток примерчиков для наглядности:

sub t_zero   { 0           };
sub t_empty  { ""          };
sub t_undef  { undef       };
sub t_arr    { qw/a b c/   };
sub t_scalar { "ok"        };
sub t_arref  { [qw/a b c/] };
sub t_hashref{ {}          };

sub test {
    my ( $self, $c ) = @_;
    $c->forward('t_zero');    # 0
    $c->forward('t_empty');   # 0
    $c->forward('t_undef');   # 0
    $c->forward('t_arr');     # 'c'
    $c->forward('t_scalar');  # 'ok'
    $c->forward('t_arref');   # ['a', 'b', 'c']
    $c->forward('t_hashref'); # {}
};

rrdtool и freebsd

| 2 Comments

Всю жизнь свою юзал rrdtool из портов, и не заморачивался, и всё было хорошо. Но недавно её апнули до версии 1.3.x, и теперь она вместо libart_lgpl юзает cairo... а cairo тянет половину иксов.

Откатился до rrdtool10, а она страшненькая какая-то... непривычно. Вообщем на одном из серверов лежала 1.2.23, которую я с удовольствием и поставил :)

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

rrdtool_1_2_23.tar.gz

Дано:

Массив длиной L, каждый элемент массива имеет вес weight (для простоты - целочисленный)

Задача:

Выбрать рандомно N элементов из массива (N < L), при этом не должно быть одинаковых элементов, и вероятность выборки каждого элемента должна быть прямо пропорциональна весу элемента.

Решение:

Разместим элементы массива на оси весов, при этом длина отрезка каждого элемента равна весу этого элемента.
Посчитаем суммарный вес элементов - это максимально возможная координата.

Теперь итерируем массив от начала (столько итераций, сколько нужно выбрать элементов). На каждой итерации:

  • Выбираем рандомно точку от 1 до макс. координаты $weight
  • Ищем элемент, соответствующий отрезку, содержащему эту точку
  • Меняем местами выбранный элемент с элементом, соответствующем текущей итерации - т.о. "запоминаем" его.
  • Сдвигаем начало координат (и соотв. макс. координату) на величину, равную длине отрезка выбранного элемента

Всё. Теперь N начальных элементов - и есть интересующая нас выборка. Осталось только отбросить лишнюю часть массива от N+1 до L

# @res - исходный массив
# $need_count - сколько нужно выбрать элементов
# $weight - суммарный вес всех элементов исходного массива

for (my $i=0; $i<$need_count; $i++) {
    my $w = int(rand $weight)+1; # выбираем точку на оси весов
    for (my $j=$i; $j<=$#res; $j++) { # ищем элемент, соотв. точке
        if ($res[$j]->{weight} >= $w) {
            $weight -= $res[$j]->{weight};
            ($res[$i], $res[$j]) = ($res[$j], $res[$i]) if $i != $j;
            last;
        } else {
            $w -= $res[$j]->{weight};
        }
    }
}
@res = splice(@res,0,$need_count); # обрезаем массив

About this Archive

This page is an archive of entries from October 2008 listed from newest to oldest.

September 2008 is the previous archive.

November 2008 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Pages

Powered by Movable Type 4.2-en