流行りの「1時間以内に解けなければプログラマ失格となってしまう5つの問題が話題に」を会社の勉強会でやりました。
勉強会ではgistに挙げるルールだったのですが、私的にはQiitaがホームグラウンドなので、こっちにも挙げておきます。
解くのは、問題4をなめていて、70分かかり、さらにバグを見つけて結局80分かかってしまいました。
先週が問題解き、今週が答え合わせだったので、ついでに1週間でCodeGolf的ワンライナーも作ってみました。
問題1
問題1
package Question1;
use strict;
use warnings;
sub for_type {
my @args = @_;
my $sum = 0;
for (my $i=0;$i < @args;$i++) {
$sum += $args[$i];
}
return $sum;
}
sub while_type {
my @args = @_;
my $sum = 0;
while (@args) {
$sum += shift(@args);
}
return $sum;
}
sub recursion_type {
my @args = @_;
return @args ? shift(@args) + recursion_type(@args) : 0;
}
1;
問題1のCodeGolf
perl -e'$a+=$_ for@ARGV;warn$a' 1 2 3 4
perl -e'$a+=pop while@ARGV;warn$a' 1 2 3 4
perl -e'sub a{@_?pop()+a(@_):0};warn a(@ARGV)' 1 2 3 4
問題2
問題2
package Question2;
use strict;
use warnings;
sub list_add {
my ($l1,$l2) = @_;
my @ret;
my $len = @{$l1} > @{$l2} ? @{$l1} : @{$l2};
for (my $i =0; $i < $len; $i++) {
push(@ret,$l1->[$i]) if ($i<@{$l1});
push(@ret,$l2->[$i]) if ($i<@{$l2});
}
return @ret;
}
1;
問題2のCodeGolf
perl -e'@a=map{[split(/,/,$_)]}@ARGV;@b=@{$a[0]};@c=@{$a[1]};$l=@b>@c?@b:@c;for(0..$l-1){push(@d,$b[$_])if(@b>$_);push(@d,$c[$_])if(@c>$_)}print@d' 1,2,3,4 a,b,c,d,e,f,g
問題3
bigint使ってるけどなんかうまく動かない...でもとりあえずロジックはあってるはず
問題3
package Question3;
use strict;
use warnings;
use bigint;
sub fibonacci {
my $now = 0;
my @ret = (0,1);
for (my $i = 0; $i < 99; $i++) {
push(@ret,$ret[$i]+$ret[$i+1]);
}
return @ret;
}
1;
問題3のCodeGolf
perl -Mbigint -e'$r[$_]=$_<2?$_:$r[$_-2]+$r[$_-1]for(0..99);warn join",",@r'
問題4
正直これが一番悩みました、他のメンバーは5の方が難しいと言ってましたが、これってもっと簡単なやり方あるんですか?
簡単にワンライナーにできるよ、と言われましたが、正直私版のこれのワンライナーは単に長い版を文字削っただけです...
問題4
package Question4;
use strict;
use warnings;
sub kanounasaidai {
my @args = map { $_ ."" } @_;
my @list;
for (my $i=0;$i<@args;$i++) {
for (my $j=0;$j<@args;$j++) {
next if ($i == $j);
push(@list,[$i,$j,$args[$i].$args[$j]]);
}
}
@list = sort { $b->[2] cmp $a->[2] } @list;
return $list[0]->[2] if (@args == 2);
my $res = $list[0];
my $k = -1;
return kanounasaidai($res->[2],grep {$k++; $k != $res->[0] && $k != $res->[1]} @args);
}
問題4のCodeGolf
perl -e'sub k{@z=map{$_.""}@_;my @l;for $i.$#z){for $j(0..$#z){next if($i==$j);push(@l,[$i,$j,$z[$i].$z[$j]])}}@l=sort{$b->[2]cmp$a->[2]}@l;return $l[0]->[2] if(@z==2);$r=$l[0];$k=-1;return k($r->[2],grep{$k++;$k!=$r->[0]&&$k!=$r->[1]}@z)}warn k(@ARGV)' 9 956 978 56
問題5
一番難しいとみんな言ってたけど、5分でできましたが(ただバグあったけど)...
eval禁止縛りとかしてるから難しいのかなと思ったら、普通にみんなeval使ってたし
問題5
package Question5;
use strict;
use warnings;
sub recursive {
my $now = shift;
my @list = @_;
my @ret;
if ($now == 1) {
@ret = ('1','-1');
} else {
foreach my $l (@list) {
push(@ret,$l."+$now");
push(@ret,$l."-$now");
push(@ret,$l."$now");
}
}
return $now == 9 ? @ret : recursive($now+1,@ret);
}
sub answer {
my @pattern = recursive(1);
my @ans = grep {eval($_) == 100} @pattern;
print join("\n",@ans);
}
1;
問題5のCodeGolf
perl -e 'sub r{$n=shift;my@r=$n==1?("1","-1"):map{($_."+$n",$_."-$n",$_.$n)}@_;$n==9?@r:r($n+1,@r)}@p=r(1);@a=grep{eval($_)==100}@p;warn join("\n",@a)'