Подтвердить что ты не робот

Есть ли название для этого алгоритма?

Извините за непонятный вопрос; если вы можете думать о лучшем, я все уши.

Я пишу некоторый Perl для реализации алгоритма и кода, который у меня есть запах. Поскольку у меня нет фона CS, у меня нет большого количества стандартных алгоритмов в моем заднем кармане, но это похоже на то, что может быть.

Позвольте мне описать, что я делаю в метафоре:

  • У вас есть конвейер с апельсинами. Апельсины проходят один за другим. У вас также есть неограниченная поставка плоских упакованных ящиков.
  • Для каждого апельсина проверьте его. Если он гниет, утилизируйте его
  • Если это хорошо, поместите его в коробку. Если у вас нет коробки, возьмите новую и создайте ее.
  • Если в коробке есть 10 апельсинов, закройте его и поместите на поддон. Не создавайте новую.
  • Повторяйте, пока у вас не будет больше апельсинов.
  • Если у вас есть построенная коробка с некоторыми апельсинами, закройте ее и положите на поддон

Итак, у нас есть алгоритм обработки элементов в списке, если они соответствуют некоторым критериям, их следует добавить в структуру, которая, когда она удовлетворяет некоторым другим критериям, должна быть "закрыта". Кроме того, как только список будет обработан, если есть "открытая" структура, он также должен быть "закрыт".

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

Итак, вот мои вопросы:

  • Это описание известного алгоритма? Если да, имеет ли это имя?
  • Есть ли эффективный способ объединить активность "закрытия ящика" в одно место, а не один раз внутри цикла и один раз за пределами цикла?

Я отметил это как "Perl", потому что подходы Perlish представляют интерес, но мне было бы интересно услышать любые другие языки, на которых есть четкие решения.

4b9b3361

Ответ 1

Хорошо сочетается с функциональным подходом - вы повторяете поток апельсинов, тестируете, группируете и действуете на них. В Scala это будет что-то вроде:

 val oranges:Stream[Oranges] = ... // generate a stream of Oranges

 oranges.filter(_.isNotRotten).grouped(10).foreach{ o => {(new Box).fillBox(o)}}

(grouped делает правильную вещь с частичным полем в конце)

Вероятно, существуют эквиваленты Perl.

Ответ 2

Существует ли эффективный способ объединения активности "закрытия ящика" в одно место, а не один раз внутри цикла и один раз за пределами цикла?

Да. Просто добавьте "... или больше нет апельсинов" к функции "должна ли быть закрыта структура". Самый простой способ сделать это - построить do/while (технически говоря, это не цикл в Perl, хотя он выглядит как один):

my $current_container;
my $more_objects;
do {
    my $object = get_next_object();  # Easiest implementation returns undef if no more 
    $more_objects = more_objects($object) # Easiest to implement as "defined $object"
    if (!$more_objects || can_not_pack_more($current_container) { 
        close_container($current_container);
        $current_container = open_container() if $more_objects;
    }
    pack($object, $current_container) if $more_objects;
} while ($more_objects);

ИМХО, это действительно ничего не выиграет, если close_container() инкапсулирован в метод - нет никаких существенных технических или качественных затрат на качество для вызова как внутри, так и вне цикла. На самом деле, я твердо придерживаюсь мнения, что сложное обходное решение, как я изложил выше, - это качество кода ВОСЕМЫ, чем просто:

my $current_container;
while (my $more_objects = more_objects(my $object = get_next_object())) {
    if (can_not_pack_more($current_container)) { # false on undef
        close_container($current_container);
    }
    $current_container = open_container_if_closed($current_container); # if defined
    pack($object, $current_container);
}
close_container($current_container);

Ответ 3

Похоже, что проблема, которую вы описываете, немного сложна, но она теоретически близка к Петри Нэтсу. проверьте Петри Сети по википедии

Реализация perl может быть найдена здесь

Надеюсь, это поможет вам,

Джером Вагнер

Ответ 4

Я не думаю, что есть имя для этого алгоритма. Для прямой реализации вам понадобятся два теста: один для обнаружения полного поля, в то время как в цикле обработки и один после цикла для обнаружения частично полного поля. Логика "закрытия ящика" может быть превращена в подпрограмму, чтобы избежать ее дублирования. Функциональный подход может обеспечить такой способ:

use List::MoreUtils qw(part natatime);

my ($good, $bad) = part { $_->is_rotten() } @oranges;

$_->dispose() foreach @$bad;

my $it = natatime 10, @$good;
while (my @batch = $it->()) {
    my $box = Box->new();
    $box->add(@batch);
    $box->close();
    $box->stack();
}

Ответ 5

При взгляде на алгоритмы, основной поток CS, как правило, обрабатывают очень сложные ситуации или используют очень сложные подходы (посмотрите NP-Complete для пример). Более того, алгоритмы имеют тенденцию фокусироваться на оптимизации. Как эта система может быть более эффективной? Как я могу использовать меньше шагов в этом производственном графике? Какое количество фосов, которые я могу поместить в мой бар? и др.

Примером сложного подхода, на мой взгляд, является быстрый вид, потому что рекурсия довольно гениальна. Я знаю, что это стандарт, но мне это очень нравится. Если вам нравятся алгоритмы, ознакомьтесь с Simplex Algorithm - это было очень влиятельным.

Примером сложной ситуации было бы, если бы у вас были апельсины, которые вошли, отсортированы по 5 апельсиновым сваям, затем отправились в 5 разных мест, чтобы очиститься, а затем все вернулись с другим путем апельсинов до 10 оранжевых свай, затем каждый апельсин индивидуально нарезался и помещался в коробки ровно в 2 фунта.

Вернемся к вашему примеру. Ваш пример - упрощенная версия проточной сети. Вместо того, чтобы иметь так много боковых путей и опций, есть только один путь с емкостью по одному апельсину за раз. Из алгоритмов проточной сети алгоритм Ford-Fulkerson, вероятно, самый влиятельный.

Таким образом, вы, вероятно, можете подгонять один из этих алгоритмов в представленный пример, но это будет через процесс упрощения. В принципе, здесь не требуется сложной оптимизации. И нет никакого риска работать при неэффективной временной сложности, поэтому нет необходимости запускать "идеальный подход".

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