Perl Collatz猜想-迭代而非递归

Perl Collatz猜想-迭代而非递归,perl,loops,for-loop,recursion,iteration,Perl,Loops,For Loop,Recursion,Iteration,我正在研究一些用于学习的东西,我已经使用递归解决了这些问题。如果您看到下面的内容,我将使用@和$使的保持活动状态 #!/usr/bin/env perl sub collatz { my ($num, $count) = @_; $count++; if ($num == 1) { return $count; } elsif ($num % 2 == 0) { return collatz($num/2, $count);

我正在研究一些用于学习的东西,我已经使用递归解决了这些问题。如果您看到下面的内容,我将使用
@
$
使
保持活动状态

#!/usr/bin/env perl

sub collatz {
    my ($num, $count) = @_;
    $count++;
    if ($num == 1) {
        return $count;
    } elsif ($num % 2 == 0) {
        return collatz($num/2, $count);
    } else {
        return collatz($num*3 + 1, $count);
    }
}


my $max = 0;
my $saved = 0;

for (1..1000) {
    my $length = collatz($_, 0);
    print "Num: " . $_ . " Length: " . $length . "\n";
    if ($length > $max) {
        $max = $length;
        $saved = $_;
    }
}

print "The longest sequence starts with " . $saved . "\n";
我试图用迭代代替递归,但我想不出如何解决这个问题。我不是在寻找问题中的代码,我只是想得到一些关于如何解决这个问题以获得相同结果的提示/提示

我怀疑我需要使用
while
until
字段

任何帮助都将不胜感激,同样,我不想要确切的答案


更新

这是我的第二次尝试,这给了我一个错误

Can't return outside a subroutine at answer2.pl line 38.


考虑添加在while中满足条件时返回的逻辑

扰流板:

我的$iter=0; 而($num!=1){#做事;$iter++}


只需对
使用
,而
循环的结束条件是数字==1

扰流板:

基本上你有,这是很好的和简单的消除

您不必调用collatz来生成序列中的下一步,只需将变量更改到位并循环回顶部即可

以最粗糙的形式,这将是

sub collatz2 {
  my ($num, $count) = @_;

NEXT:
  $count++;

  if ($num == 1) {
    return $count;
  }
  elsif ($num % 2 == 0) {
    $num = $num / 2;
  }
  else {
    $num = $num * 3 + 1;
  }

  goto NEXT;
}
但它应该写得更漂亮

我最终得到了这个

sub collatz {
  my ($num) = @_;
  my $count = 1;
  while ($num > 1) {
    $num = $num % 2 ? $num * 3 + 1 : $num / 2;
    ++$count;
  }
  $count;
}

使用
while
until
循环。这就是我的想法,但我一直在努力思考如何在逻辑上也这样做以获取长度。@user3076141:
虽然
循环是最好的,但退出条件只在每次迭代开始时测试。从一个无休止的循环开始并添加一个
last if condition
语句以在适当的位置退出总是比较容易的。然后,您可能能够转换代码以将该出口点移到顶部,并且您已经将其转换为一个
while
,这很有帮助,所以我有这个。这给了我一个错误“不能在answer2.pl第38行的子例程之外返回。”我的$number=0;我的$counter=0;while($number!=1000){$counter++;if($number==1){return$counter;}elsif($number%2==0){return($number/2,$counter);}else{return($number*3+1,$counter);}$number++;}打印“number”$号码。“柜台”$柜台“\n”@user3076141请尝试用该代码更新您的问题。@user3076141提示,while子句不应是您希望完成的迭代次数,并且在不使用子例程时不使用return。在任何情况下,如果这是在一个子例程中,您只需要一个return语句。@user3076141将其与while语句放在一起的更好方法是,期望无限次迭代,直到您得到所需的
$number
@Gabs00:我不知道降价中有隐藏的扰流板机制。谢谢@是的,我想知道。但是我认为我的最终版本是OP不太可能自己构造的,如果用它将破坏者放到一边,很明显它是被复制的,上面的不是给出了我在递归示例中已经得到的东西吗?以上内容仍然需要某种形式的for来完成任务,对吗?@user3076141:是的,我已经消除了递归,它位于
collatz
子例程中。不再有递归了。循环的
不是递归。我想你想得太多了!哦,我明白了!我对递归实际上是什么有一个错误的理解,所以是的。对子例程使用相同的函数,并使用新的子例程(不包括子例程),使其效率更高。@user3076141:是的,使其效率略高,因为它在每次迭代时不使用新的堆栈帧和一对新的变量
$num
$count
。看看。你需要
my$steps=1
来匹配OP的计数。我选择匹配wikipedia文章中关于算法的更符合逻辑的实际步骤数。考虑到OP最终只担心最大长度的数字,我觉得这是一个公平的决定。
sub collatz2 {
  my ($num, $count) = @_;

NEXT:
  $count++;

  if ($num == 1) {
    return $count;
  }
  elsif ($num % 2 == 0) {
    $num = $num / 2;
  }
  else {
    $num = $num * 3 + 1;
  }

  goto NEXT;
}
sub collatz {
  my ($num) = @_;
  my $count = 1;
  while ($num > 1) {
    $num = $num % 2 ? $num * 3 + 1 : $num / 2;
    ++$count;
  }
  $count;
}