这个算法有名字吗?

时间:2010-12-10 16:59:14

标签: algorithm perl

对非描述性问题表示歉意;如果你能想到一个更好的人,我会全力以赴。

我正在编写一些Perl来实现一个算法,而我的代码却有些腥味。由于我没有CS背景,所以我的后袋里没有很多关于标准算法的知识,但这看起来可能就像它一样。

让我用隐喻来描述我正在做的事情:

  • 你有一个橘子传送带。橘子一个接一个地通过你。您还可以无限量供应扁平包装盒。
  • 对于每个橙子,检查它。如果它已腐烂,请将其丢弃
  • 如果好,请将其放入盒子中。如果您没有盒子,请抓一个新盒子并构建它。
  • 如果包装盒中有10个橙子,请将其关闭并放在托盘上。 不要构建一个新的。
  • 重复,直到你没有更多的橘子
  • 如果你有一个带有橙子的构造盒子,把它关上并放在托盘上

因此,我们有一个处理列表中项目的算法,如果它们符合某些标准,它们应该被添加到一个结构中,当它满足其他一些标准时,应该“关闭”。此外,一旦处理完列表,如果存在“开放”结构,它也应该“关闭”。

天真地,我假设算法包含一个循环遍历列表的循环,带有条件以查看列表元素是否属于结构,还有条件查看结构是否需要“关闭”。 在循环之外,还有一个条件可以关闭任何未完成的结构。

所以,这是我的问题:

  1. 这是一个众所周知的算法的描述吗?如果是这样,它有名字吗?
  2. 是否有一种有效的方法可以将“关闭盒子”活动合并到一个地方,而不是一次在循环内部和一次在循环之外?
  3. 我将此标记为“Perl”,因为Perlish方法很有意思,但我很想知道其他任何语言都有这方面的解决方案。

5 个答案:

答案 0 :(得分:9)

它非常适合功能性方法 - 您可以迭代Orange流,对其进行测试,分组和操作。在Scala中,它将类似于:

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

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

grouped在末尾的部分框中做正确的事情)

可能有Perl等价物。

答案 1 :(得分:5)

  

是否有一种有效的方法可以将“关闭盒子”活动合并到一个地方,   而不是一次进入循环并且一次进入循环之外?

是。只需在“结构需要关闭”功能中添加“......或没有更多的橙子”。最简单的方法是使用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()被封装到一个方法中,这并没有真正赢得任何东西 - 在循环内外调用它没有重大的技术或代码质量成本。实际上,我强烈认为上面提到的一个复杂的解决方法是WORSE代码质量明智而不是直截了当:

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);

答案 2 :(得分:3)

对于你所描述的问题,似乎有点过于复杂,但听起来理论上接近Petri网。检查Petri Nets on wikipedia

可以找到perl实现here

我希望这会对你有所帮助,

Jerome Wagner

答案 3 :(得分:1)

我认为此算法没有名称。对于直接实现,您需要进行两项测试:一种是在处理循环中检测完整的盒子,另一种是在循环后检测部分满的盒子。可以将“关闭框”逻辑设置为子例程以避免重复它。功能性方法可以提供一种解决方法:

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();
}

答案 4 :(得分:0)

在查看算法时,主流的CS倾向于处理非常复杂情况,或采用非常复杂方法(例如查找NP-Complete)。此外,算法倾向于关注优化。这个系统如何更有效率?如何在此生产计划中使用更少的步骤?我可以在酒吧里容纳最多的foos?等

在我看来,复杂方法的一个例子是快速排序,因为递归非常天才。我知道这是标准的,但我真的很喜欢它。如果您喜欢算法,那么请查看Simplex Algorithm - 它非常有影响力。

复杂情况的一个例子是,如果你有橙子进入,分成5个橙色的堆,然后去5个不同的地方去皮,然后所有回来的另一条橙色路径到10个橙色桩,然后将每个橙子单独切片,并装入完全 2磅的组。

回到你的例子。您的示例是flow network的简化版本。没有那么多的侧面路径和选项,只有一条路径,一次只能容纳一个橙色。在流网络算法中,Ford-Fulkerson algorithm可能是最有影响力的。

因此,您可以将这些算法中的一种放入所提出的示例中,但这将通过简化过程实现。基本上没有足够的复杂性需要任何优化。并且不存在以低效时间复杂度运行的风险,因此不需要运行“完美方法”。

您详细说明的方法在这里会很好,上面接受的答案可以很好地为定义的问题提供实际的功能解决方案。我只想在算法方面增加2美分。

相关问题