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