调整我的代码来解决难题

时间:2011-11-10 13:15:19

标签: performance perl puzzle

5只猴子分享桃子,他们不能平均分配。因此第一只猴子倾倒1个桃子,桃子的总数可以除以5,第一只猴子就是他的一部分。

然后是第二只猴子,-1桃子,可以除以5并且参与其中。 直到第五只猴子完成所有步骤。可能还剩下一些桃子。

给出满足这种条件的最小桃子数量。

perl code 1:

#!/usr/bin/perl -w
for $n (0..10000){      #this is basic idea but code is too messy !
    if( ($n-1) % 5 == 0 ){
     $remain = 4/5 * ($n -1 );
         if( ($remain - 1) % 5 == 0){
           $remain = 4/5 * ($remain -1 );
           if( ($remain - 1) % 5 == 0){
               $remain = 4/5 * ($remain -1 );
               if( ($remain - 1) % 5 == 0){
                   $remain = 4/5 * ($remain -1 );
                   if( ($remain - 1) % 5 == 0){
                      $remain = 4/5 * ($remain -1 );
                      print "remain: $remain original: $n\n";
                   }
               }
            }
          }
     }
 }

perl code 2:

sub doit($){
    ($n) = @_;
    if( ($n - 1) % 5 ==0 ){ #if can be distributed by 5 monkey
       $n = ($n - 1) * 4/5;  #commit distribute
       return $n;
    }else{
       return -1;  #fail
    }
}

for $n (0..10000){   #restriction
    $r = $n;    #"recursively" find solution
    $o = $n;    #backup n
    $count = 0;
    for ($i = 0; $i < 5; $i++){  #assume there is 5 monkey, it can be changed
       $r = doit($r);
    if($r == -1){   #skip once fail
        last;
    }
    $count++;
    }
    if($count == 5){ # if pass 5 test, then you found the number !
       print "now ".$r."\n";
       print "origin ".$o."\n";
    }
}

我正在考虑削减一些代码。但感觉很难。有人可以帮忙吗?

3 个答案:

答案 0 :(得分:1)

首先,您确实应该在脚本顶部使用strictwarnings pragma。您的$n用法特别令人担忧。将来,如果您使用my声明变量但使用相同的名称,则表明它们将代表相同的数量,而不必担心它们可能会发生碰撞。

无论如何,这里有一个稍微抛光,更重要的是strictwarnings安全版本:

#!/usr/bin/env perl

use strict;
use warnings;

sub doit {
    my ($n) = @_;
    if( ($n - 1) % 5 ==0 ){ #if can be distributed by 5 monkey
       $n = ($n - 1) * 4/5;  #commit distribute
       return $n;
    } else {
       return undef;  #fail
    }
}

OUTER: for my $n (0..10000){   #restriction
    my $r = $n;    #"recursively" find solution
    for (1..5){  #assume there is 5 monkey, it can be changed
       $r = doit($r);
       next OUTER unless defined $r;
    }
    # if code gets here, then it passed 5 test, then you found the number !
    print "now: $r\torigin: $n\n";
}

现在,如果你真的想要玩得开心(不要在生产中使用它,首先是可读性!):

#!/usr/bin/env perl

use strict;
use warnings;

OUTER: for my $n (0..10000){ 
    my $r = $n;
    $r = ($r - 1) % 5 ? next OUTER : 4/5 * ($r - 1) for (1..5);
    print "now: $r\torigin: $n\n";
}

甚至打高尔夫球:

for(0..10000){$r=$n=$_;map$r*=--$r%5?next:4/5,1..5;print"now: $r\torigin: $n\n"}

答案 1 :(得分:1)

考虑这个解决方案:

sub share {
  ($_[0] - 1) % 5 == 0 ? ($_[0]-1)/5*4 : die "unable to share";
}

for my $i (1..10000) {
  eval {
    share(share(share(share(share($i)))));
  };
  unless ($@) {
    print "solution: $i\n";
    last;
  }
}

我确信其中潜伏着一个单子。

答案 2 :(得分:0)

我并非100%确定我理解你的问题,但不是寻找答案,而是从最后一只猴子开始。他可以采取的最小桃子是1,即使可能有一些剩下的,为了得到最小值,假设剩下0。现在,计算出第二只猴子看到的桃子数量,等等。

如果从最后一只猴子开始,就没有必要循环

 # set numPeaches to what the last monkey had
 $numPeaches = 1;

 # then, figure out how many the second to last monkey had, and add to numPeaches

 # and, so on ...

 # until you get to the first monkey
相关问题