sironekotoroの日記

Perl で楽をしたい

Perl入学式in東京 #4 復習 その1

まずは第3回の復習問題 score.plの復習。リファレンスを初めてあつかったときはこれ解くのに3日くらいかかったけど、2時間くらいで解けるように。

やはり鬼門は問4。ハッシュリファレンスの中に配列を入れる、ってところで???となる。というか、問題文を良く読むと、keyに所属で、そこに配列のリファレンスとして名前を入れる?って感じになるので、前回作ったやつは間違いか・・・

# 4.所属ごとのperlスコアが60人以上の人の名前を格納する
my $highscore;

for my $foo (@people) {
    if ( $foo->{perl} >= 60 ) {
        push @{ $highscore->{ $foo->{affiliation} } }, $foo->{name};
    }
}

サブルーチンの練習問題

  • 2つの引数の和を計算するaddと同様に, 2つの引数の差を計算するmin, 積を計算するmul, 商を計算するdivというサブルーチンを作ってみよう.
  • これらのサブルーチンが正しく実装できているか(与えた2つの引数に対して, 適切な値を返すか)を確認するコードを書いてみよう.
use strict;
use warnings;

sub add {
    my ($fst , $snd) = @_;
    return ($fst + $snd); 
}

sub min {
    my ($fst , $snd) = @_;
    return ($fst - $snd); 
}

sub mul {
    my ($fst , $snd) = @_;
    return ($fst * $snd); 
}

sub div {
    my ($fst , $snd) = @_;
    return ($fst / $snd); 
}

if (add(2,3) == 5){
    print "add test ok\n"
}else{
    print "add test ng\n"
}

if (min(2,3) == -1){
    print "min test ok\n"
}else{
    print "min test ng\n"
}

if (mul(2,3) == 6){
    print "min test ok\n"
}else{
    print "min test ng\n"
}

if (mul(6,3) == 2){
    print "div test ok\n"
}else{
    print "div test ng\n"
}

my $foo = 9;
my $bar = 3;

print "$foo + $bar = " . add($foo,$bar) . "\n";
print "$foo - $bar = " . min($foo,$bar) . "\n";
print "$foo * $bar = " . mul($foo,$bar) . "\n";
print "$foo / $bar = " . div($foo,$bar) . "\n";

サブルーチンとリファレンスの練習問題

配列とハッシュをそれぞれ1つずつ定義してから, 第1引数に配列のリファレンス, 第2引数にハッシュのリファレンスを受け取り, その中身を出力する(for文などを利用して...), output_array_and_hashというサブルーチンを書いてみよう

use strict;
use warnings;

my @array = qw/ 1 2 3 4 5/;
my %hash = ( dog => 'woo', cat => 'nyaa', cow => 'moo') ;

sub output_array_and_hash{
    my ($fst , $snd )=@_;
    print "array is \n";
    for my $i (@$fst){
        print " $i\n";
    }

    print "hash is \n";
    for my $bar(keys %$snd){
        print " $bar is $hash{$bar}\n";
    }
}

output_array_and_hash(\@array , \%hash);

サブルーチンの引数に配列やハッシュを使うときはリファレンス化しておく必要がある、と。

正規表現+サブルーチンの練習問題

use strict;
use warnings;

sub perl_checker{
    my $str = shift;
    if ($str =~ /[Pp]erl/){
        print "Perl Monger!\n";
    }else{
        print "No Perl Monger\n"
    }
}

perl_checker("Learning Perl 5th Edition");

perl_checker("Enjoy Ruby");

正規表現とリファレンス

このような配列のリファレンスを受け取り, リファレンスに格納された文字列について, 「loves」の後に記述されている好きな食べ物の単語を正規表現で取得し, 「papix -> meat」, 「moznion -> sushi」のように表示するサブルーチン, love_foodを書いてみよう.

use strict;
use warnings;

my @words = ( 'papix loves meat!', 'moznion loves sushi!' );

sub love_food {
    my $str = shift;
    for my $i (@$str) {

        if ( $i =~ /(.+?) loves (.+?)!/ ) {
            print "$1 -> $2\n";
        }
    }

}

love_food( \@words );

置換

この$strに格納された文字列を, 置換を利用して, 「moznion loves perl」に書き換えるようなコードを書いてみましょう.

use strict;
use warnings;

my $str = 'moznion loves ruby';

$str =~ s/ruby/perl/;

print $str;

練習問題

while (chomp($input = )) {
...
}

上記のコードは, 標準入力から入力された文字列を, ひたすら$inputに代入するコードである. このコードの...の部分を, 次の条件を満たすように書き換えてみよう.

  • 文字列が0の場合, ループを抜ける(lastを使って...).
  • 文字列がperlないしPerlを含む場合, 「Find Perl!」と表示する.
  • 文字列に大文字小文字問わず, pythonの文字列が含まれる場合, 「Find Python!」と表示する.
  • 文字列にperlないしrubyないしpythonが含まれる場合, 「Love Programming!」と表示する.
  • 文字列の先頭にpapixがある場合, 「Find papix!」と表示する.
  • 文字列にHelloが含まれる場合, その後に続く単語xxxxを使って「Hello! xxxx!」と表示する.
    • 例えば, 文字列に「Hello moznion」が含まれる場合, 「Hello! moznion!」と表示すればOKです.
use strict;
use warnings;

while ( chomp( my $input = <STDIN> ) ) {
    if ( $input eq 0 ) {
        last;
    }
    elsif ( $input =~ /[Pp]erl/ ) {
        print "Find Perl!\n";
    }
    elsif ( $input =~ /python/i ) {
        print "Find Python\n";
    }

    if ( $input =~ /perl|ruby|python/ ) {
        print "Love Programming\n";
    }

    if ( $input =~ /^papix/ ) {
        print "Find papix!\n";
    }

    if ( $input =~ /([Hh]ello) (\w*)/) {
        print "$1! $2!\n";

    }
}