「初めての Perl」勉強3日目

ハッシュが出てきた。なんとなく分かる。半分くらい。問題を解くのに時間がかかるのは思考構造の問題な気がする。慣れか?

第五章 ハッシュ

練習問題1

名前を入力して、その人の姓を表示するプログラムを書いてください。

#!/usr/local/bin/perl -w

use strict;

my $input = <STDIN>;
chomp $input;

my %name = (
    "fred" => "flintstone",
    "barney" => "rubble",
    "wilma" => "flintstone",
);

print "$input $name{$input}\n";

chomp 関数の使い方について id:vkgtaro さんと協議

最初は

my $input = chomp($input = <STDIN>);

って書いて怒られたんで id:vkgtaro さんに聞いてみたら、簡潔な書き方として1行では無理ってことになった。

my $input;
chomp($input = <STDIN>);

もしくは

my $input = <STDIN>;
chomp $input;

たぶんこの辺は好みの問題。前者は id:vkgtaro さんの。後者は自分の。難しい><

練習問題2

一連の単語をファイルの終わりになるまで読み込んで、各単語が何回出現したかを表示するプログラムを書いてください。余力がある人は、単語を ASCII コードの昇順にソートして表示してください。

なんとなく分かった気がしたけど、コードに起こせなかったので回答を見ました><

#!/usr/local/bin/perl -w

use strict;

my (@words, %count, $word);

@words = <STDIN>;
chomp @words;

foreach $word (@words) {
    $count{$word} += 1;
}

foreach $word (sort keys %count) {
    print "$word = $count{$word}\n";
}

途中の

$count{$word} += 1

のところをやるのは分かってたんだけど、全体が分からなかった。むしろ入力が分からなかった。

@words = <STDIN>;

これは気付かなかった。確かにリストに入れればいいわけだ。個人的にはここが重要だと思った。

第六章 入出力の基本

UNIX の知識がないと分からないかも。cat コマンドがどんなものか知らんかったw(使ったことないし)

練習問題1

cat のような振る舞いをするプログラムを書いてください。ただし、このプログラムは、出力を逆順に行います。このプログラムに tac と言う名前を付けたとして、./tac fred barney betty として起動すると、まず最初に betty の内容が最後の行から先頭に向かって表示され、次に barney と fred が、同様に最後から先頭に向かって表示されます。

#!/usr/local/bin/perl -w

@ING = @ARGV;

@ING = reverse @ING;

foreach (@ING) {
    print <>;
}

こうでいいはず?

練習問題2

文字列のリストを1行に1個ずつ別々に読み込んで、その文字列を20文字幅のカラムに右寄せで表示するプログラムを書いてください。出力が正しいカラムに合っていることを確認するために、目盛り付きの「物差し」も出力してください。

#!/usr/local/bin/perl -w

@list = <STDIN>;
chomp @list;

print "1234567890"x 10 ,"\n";

foreach $n (@list) {
    printf "%20s\n", $n;
}

「物差し」がキモイ気もするけどいっかw

練習問題3

問題2のプログラムを改造して、ユーザがカラムの幅を指定できるようにしてください。例えば、30と hellow と good-bye を入力すると、30文字幅のカラムに右寄せで表示されます。
長い幅を指定された時には、それに合わせて定規も伸びるようにした人は、追加点を差し上げましょう。

これって必ず最初にカラムの幅を入れるって条件付きなのだろうか?
じゃないと例えば hellow, 30, good-bye の順で入力して、この中からカラム幅となる30を取り出すのは無理じゃないか?

とりあえず最初に入力する値がカラム幅ってことで作ってみた。

#!/usr/local/bin/perl -w

my @list = <STDIN>;
chomp @list;

my $sum = shift(@list);

print "1234567890"x 10 ,"\n";

foreach $n (@list) {
    printf "%${sum}s\n", $n;
}

ちなみに「物差し」まで変化させるのはこうなるのかな

#!/usr/local/bin/perl -w

my @list = <STDIN>;
chomp @list;

my $sum = shift(@list);

if ($sum > 100) {
    print "1234567890"x ($sum / 8) ,"\n";
}
else {
    print "1234567890"x 10 ,"\n";
}

foreach $n (@list) {
    printf "%${sum}s\n", $n;
}

$sum の 1/8 なのはテキトー。それくらいでいいと思ったから。