Tag Archives: Perl - Page 3

二分探索の処理の様子を細かく見てみる

二分探索の仕組みを詳しく見てみようと思う。サンプルコードはPerlで書いているがCやRuby、Javaなどほかの言語も似たようなものだと思う。

サンプルコード

#!/usr/bin/perl -w

# パラメータ
my $left = 0; my $right = 100; my $target = 140;
my @a; # 初期化

# 0~100までの数字を二倍しながら配列@aに追加
foreach my $i ($left..$right) {push(@a,$i*2);}

# 配列@aのリファレンスとその他引数を添えて二分探索関数を実行する
print &binary_search (@a , $left , $right , $target);

sub binary_search{
	# 配列@aのリファレンスと引数の受け取り
	my ($a , $left , $right , $target) = @_;
	# リファレンス$aを使い配列@aを読み込む
	my @a = @{$a};
	while($left <= $right){
		my $mid = int(($left + $right) / 2);
		if($a[$mid] == $target){
			return $mid;
		}elsif($a[$mid] < $target){
			$left = $mid + 1;
		}else{
			$right = $mid - 1;
		}
	}
	return -1;
}

変数や条件式の動きを追ってみると次のようになっていることが分かる。

$left $right $mid if($a[$mid] == $target)
0 100 (0 + 100) / 2 = 50 100 < 140 → 50 + 1 ($left)
51 100 (51 + 100) / 2 = 75 150 > 140 → 75 – 1 ($right)
51 74 (51 + 74) / 2 = 62 126 < 140 → 62 + 1 ($left)
63 74 (63 + 74) / 2 = 68 137 < 140 → 68 + 1 ($left)
69 74 (69 + 74) / 2 = 71 143 > 140 → 71 – 1 ($right)
69 70 (69 + 70) / 2 = 69 139 > 140 → 69 + 1 ($right)
70 70 (70 + 70) / 2 = 74 140 == 140 → END

二分探索の仕組みも分かったがPerlのリファレンスについても勉強になった。
一石二鳥ですね~

Twitter フォロワー同期(フォロー専用)Bot Perl 作成編

とりあえずさっきのプログラムを書きなおして完全にフォロワーさんを同期するプログラムを書きました。
Botみたいで(処理してるのはBotですが・・・)味気ないけど仕方ないですねwwww

#!/usr/bin/perl
use utf8;
use strict;
use warnings;

# モジュール使用宣言
use Array::Diff;
use Data::Dumper;
use Net::Twitter;
use YAML::Tiny;
use Encode;
use FindBin;

# 現在のパスから見て設定ファイルを読み込み
my $config = (YAML::Tiny->read($FindBin::Bin . '/config.yml'))->[0];
# OAuth認証
my $twitter = Net::Twitter->new(
     traits => ['API::REST', 'OAuth'],
     consumer_key => $config->{'consumer_key'},
     consumer_secret => $config->{'consumer_secret'}
);
$twitter->access_token($config->{'access_token'});
$twitter->access_token_secret($config->{'access_token_secret'});
# 認証失敗時の処理
die('Auth failed:'.$config->{'username'}) unless ( $twitter->authorized ) ;

# ユーザー名を含むユーザー情報を取得
my $cr = $twitter->verify_credentials;
my $own_id = $cr->{id};

my $nextc = -1; # paging default.
my @following_id_list; # outgo

# APIの仕様?から一度に100人までしか取得できないから0が返ってくるまでdoブロックをループ
do{
	# パラメータcursorは前回取得したフォローイングまでの番号が入っている
	my $following_list = $twitter->friends_ids({ id=>$own_id, cursor => $nextc });
	$nextc = $following_list->{next_cursor};
	# 配列からフォローイングのidを取得
	foreach my $id (@{ $following_list->{ids} }){
		push(@following_id_list, $id); # 後で比較するためにフォローイングを配列に保管
	}
}while($nextc!=0);
# 文字昇順でソート
@following_id_list = sort @following_id_list; 

$nextc = -1;
my @followers_id_list; # income

# APIの仕様?から一度に100人までしか取得できないから0が返ってくるまでdoブロックをループ
do{
	# パラメータcursorは前回取得したフォロワーまでの番号が入っている
	my $followers_list = $twitter->followers_ids({ id=>$own_id, cursor => $nextc });	
	$nextc = $followers_list->{next_cursor};
	# 配列からフォロワーのidを取得
	foreach my $id (@{ $followers_list->{ids} }){
		push(@followers_id_list, $id); # 後で比較するためにフォロワーを配列に保管
	}
}while($nextc!=0);
# 文字昇順でソート
@followers_id_list = sort @followers_id_list; 

# 差分を取得(フォローイング)
my $diff_following = Array::Diff->diff(@following_id_list, @followers_id_list);

# 差分を取得(フォロワー)
my $diff_followers = Array::Diff->diff(@followers_id_list, @following_id_list);

# リムった人をリム返し
foreach my $delid_following (@{ $diff_following->{deleted} }){
	$twitter->destroy_friend($delid_following);
}

# フォローした人をフォロー返し
foreach my $delid_followers (@{ $diff_followers->{deleted} }){
	$twitter->create_friend($delid_followers);
}

うん。書いてて思った。今まで差分取るとかループで比較するだけじゃんとか思ってたけどData::Dumperって結構便利だなw 今度機会があったら使ってみようかな?

Twitter フォロワー同期(リム専用)Bot Perl 解析編

自動でフォローされたらフォローし返すプログラムを書きたいけどNet::Twitterの使い方がわからなかったのでとりあえずフォロワー同期(リム専用)Botのソースをマニュアルを読みながら適当に解析してコメント打ちました。

マニュアル:Net::Twitter(英語)
参考にさせて頂いたソース:■[メモ]Twitterで自動フォロー削除

#!/usr/bin/perl
use utf8;
use strict;
use warnings;

# モジュール使用宣言
use Array::Diff;
use Data::Dumper;
use Net::Twitter;
use YAML::Tiny;
use Encode;
use FindBin;

# 現在のパスから見て設定ファイルを読み込み
my $config = (YAML::Tiny->read($FindBin::Bin . '/config.yml'))->[0];
# OAuth認証
my $twitter = Net::Twitter->new(
     traits => ['API::REST', 'OAuth'],
     consumer_key => $config->{'consumer_key'},
     consumer_secret => $config->{'consumer_secret'}
);
$twitter->access_token($config->{'access_token'});
$twitter->access_token_secret($config->{'access_token_secret'});
# 認証失敗時の処理
die('Auth failed:'.$config->{'username'}) unless ( $twitter->authorized ) ;

# ユーザー名を含むユーザー情報を取得
my $cr = $twitter->verify_credentials;
my $own_id = $cr->{id};

my $nextc = -1; # paging default.
my @following_id_list; # outgo

# APIの仕様?から一度に100人までしか取得できないから0が返ってくるまでdoブロックをループ
do{
	# cursorは前回取得したフォローイングまでの番号が入っている
	my $following_list = $twitter->friends_ids({ id=>$own_id, cursor => $nextc });
	$nextc = $following_list->{next_cursor};
	# 配列からフォローイングのidを取得
	foreach my $id (@{ $following_list->{ids} }){
		push(@following_id_list, $id); # 後で比較するためにフォローイングを配列に保管
	}
}while($nextc!=0);
# 文字昇順でソート
@following_id_list = sort @following_id_list; 

$nextc = -1;
my @followers_id_list; # income
do{
	# cursorは前回取得したフォロワーまでの番号が入っている
	my $followers_list = $twitter->followers_ids({ id=>$own_id, cursor => $nextc });	
	$nextc = $followers_list->{next_cursor};
	# 配列からフォロワーのidを取得
	foreach my $id (@{ $followers_list->{ids} }){
		push(@followers_id_list, $id); # 後で比較するためにフォロワーを配列に保管
	}
}while($nextc!=0);
# 文字昇順でソート
@followers_id_list = sort @followers_id_list; 

# 差分を取得
my $diff = Array::Diff->diff(@following_id_list, @followers_id_list);

# リムった人をリム返し
foreach my $delid (@{ $diff->{deleted} }){
	$twitter->destroy_friend($delid);
}

だいたい構造がわかったのでちゃちゃっと書き足しましょうか^^

ぴくぴくダウンローダ インストーラ付き 公開 β01.00

Pixivの画像を寝ている合間もひたすらダウンロードするソフトです。

インストール画面

動作画面

Download
こちらのダウンロードページよりダウンロードをお願い致します。

pixivの画像を寝ている間にどんどんダウンロードするソフト ぴくぴくダウンローダ GUI 公開


画像では東方タグを含みなおかつブックマーク数が3人以上ある画像を収集しております。

Download
こちらのダウンロードページよりダウンロードをお願い致します。

疲れてReadMe.txtを書く気力がありませんでしたので同封してませんが”ぴくぴくダウンローダ.exe”をダブルクリックして起動させ(少し時間がかかります)
ツール(T)の設定をクリックし、”わたしを読んでね(pget).txt”を読みながら設定してしまえばあとは好きなキーワードや絵師さんの画像を好きなだけ収集できます。

元はCUIなので後ろのプロンプトは消さないようにお願いします。(黒い画面の奴が本体です)
中断するときはプログラムをとじてください。(詳しい事は下に書きますが、仕様です)

ここからは分かるひとだけ・・・つか、もはやひとりごと
今回のWindowsでのPerl/Tkを利用したGUIプログラミングはとてつもなく面倒でした・・・やはりWindowsでの開発はPerlでは向かない事を改めて実感しましたね。
内部処理がUTF8なのでオプションを受け取る時もShift-jisからUTF8へデコード、system()使うときはUTF8からShift-jisへ・・・あげくに、UTF8はフラグがあるのでますます分かりづらい。もはや変数内の文字コードと格闘する状態になってました。
そして、forkで作った子プロセスを何故かkillできない。。。PIDが違うので多分エミュレータの問題なのでしょうね。よって中止ボタンの作成は今回行なっておりません。(気が向けば今後作るかも)

後日気が向けばもう少しヘルプ(H)等を改善します。

PerlはUNIXならすごく便利なんですけどね・・・今回のプログラムで何か色々なものを学んだ気がします。Rubyに移行するかな・・・

Pixiv 画像 ダウンロード ぴくぴくダウンローダ Ver α 03.00 公開

昨日公開したPixivダウンローダではタグ検索にヒットすれば無差別的にダウンロードしていました
そして、放置していたらとてつもない容量になったのでPixivサーバにも負荷をかけないようにブックマーク数を制限して人気の画像だけ収集する機能をつけました。

そもそもたくさん画像あったら欲しい画像を探すのも大変だし・・・

Download
こちらのダウンロードページよりダウンロードをお願い致します。

そろそろGUIを付けるかな?

Pixiv画像ダウンローダ ぴくぴくダウンローダ 公開

まぁ、あのままじゃ何か凄い中途半端だったので新しく検索して画像を保存できる機能と重複を防いでPixiv鯖に負荷を掛けないようにする機能を追加しました。
GUIはまだ対応してません。今後気が向いたら対応するかも。

まぁそんな感じで置いておきます。

Download
こちらのダウンロードページよりダウンロードをお願い致します。

うん。まだまだ開発せねば・・・色々と分かったw
ポチっとエンター押すだけで画像を巡回してとってきてしまうのでフォルダーの中が画像でいっぱいになります。。。
枚数ごとにフォルダー分けしたいね。。。このままではよろしくない。

もう一つ、このソフトBotに近い性質があるのでバッチで纏めてWindowsのスケージューラーに登録すればお気に入りの絵師さんの新しい画像を定期的にダウンロードさせることが可能かと思います。

Mac OSX 10.6 Perl/Tk インストール

普通にcpanよりtkをインストールしたところmake testに失敗して下記のように止まってしまい困っていたところ解決方法を見つけたのでメモしておく。
SREZIC/Tk-804.029.tar.gz : make_test NO

ソースを書き換える為cpanのディレクトリへ移動する
$ cd /Users/orbit/.cpan/build/Tk-804.029-VTDuvi/
$ vi myConfig
my $ftinc = Ift(“/usr/include”,”/usr/local/include”,“/sw/include”,$X11INC||());

$ vi PNG/Makefile.PL
if (1)
{
Tk::MMutil::TkExtMakefile(
NAME => ‘Tk::PNG’,
VERSION_FROM => ‘PNG.pm’,
XS_VERSION => $Tk::Config::VERSION,
dist => { COMPRESS => ‘gzip -f9’, SUFFIX => ‘.gz’ },
OBJECT => ‘$(O_FILES)’,
INC => ‘-I/sw/include‘,
LIBS => [‘-L/sw/lib -lpng -lz -lm’],
);
}

$ perl Makefile.PL XFT=1
$ make
$ sudo make install

参考元:Mac OS X 10.6でのPerl(5.10)モジュールのインストール

Mac OSX 10.6 Perl 正規表現が動かない バックスラッシュの書き方

MacでPerlを使っていて非常に疑問だったのが何故か正規表現が正しく動作しない問題だったのですがWindowsと違ってMacでは¥マークが実はバックスラッシュと扱いが同じではなく¥を記述しても正常に動作しません。

バックスラッシュを実際に記述したい場合は下記のような入力を行う必要があります。
optionキー(alt) +

まだ試していませんがCやJavaなどの他の言語にも影響があるかもしれません。

超簡易版 フィボナッチ数列 Perl言語

C,Javaときたら普段から慣れ親しんでるPerlを出さない訳にはいかない為書いてみた。
書いて思う事は、やはり素晴らしい言語であるということ。
最も必要最低限で意志を伝えやすい。

#!/usr/bin/perl
# 初期値を設定
$x = "0";
$y = "1";
# 値の入力を求める
$input = <STDIN>;
for($i = $input;$i > 0;$i--){
    $z = $x + $y; # 今の値を出す
    $y = $x;      # 前の値を代入→次のループで2回前の値になる
    $x = $z;      # 今の値を代入→次のループで1回前の値になる
}
print $z;  # 最後の値を表示