Collat​​z猜想 - 迭代而不是递归

时间:2014-05-19 20:47:46

标签: perl loops for-loop recursion iteration

我正在为学习目的而努力,我已经使用递归解决了Collatz。如果您在下面看到我使用@_$_来保持for活着。

#!/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";

我正在尝试使用迭代而不是递归,但我想不出如何解决这个问题。我不是在问题中的代码之后,我只是想要一些关于如何解决这个问题的提示/提示以获得相同的结果。

我怀疑我需要使用whileuntil字段。

任何帮助将不胜感激,我再也不想要确切的答案。


更新

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

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

my $number  = 0;
my $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++;
}

print "number" . $number . "counter" . $counter . "\n";

3 个答案:

答案 0 :(得分:0)

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

扰流:

  

我的$ iter = 0;  while($ num!= 1){#do stuff; $ iter ++}

答案 1 :(得分:0)

只需使用forwhile循环,其结束条件为您的数字== 1.

剧透:

  

 use strict;
 use warnings;
 
 my $max_num = 0;
 my $max_steps = 0;
 
 for my $num (1..1000) {
     my $steps = 0;
     for (my $i = $num; $i != 1; $steps++) {
         $i = $i % 2 ? 3 * $i + 1 : $i / 2;
     }
 
     print "Num: " . $num . " Length: " . $steps . "\n";
     if ($steps > $max_steps) {
         $max_num = $num;
         $max_steps = $steps;
     }
 }
 
 print "The longest sequence starts with " . $max_num . "\n";

答案 2 :(得分:0)

基本上你有tail recursion,这很容易消除。

而不是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;
}