blog/content/post/2007/12/26/2007-12-26-00000712.md

26 KiB
Raw Blame History

title author date url wordtwit_post_info categories
はじめて実用的な目的でPerlを用いた kazu634 2007-12-26 /2007/12/26/_764/
O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:3527;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}
diary
Perl

 現在私は予備校の寮でパートとして働いている。そこでは、退寮日を寮生全体に尋ね、その日時と部屋番号、そして寮費の納入方式一括or二回or月払いに応じて一月に引き落とされる金額が決定される。そこで私は、これをPerlで計算させようと決意した。四月からはこれぐらいできないといけないだろうし。今ならいっぱい失敗することもできるしね。プログラミングの初歩をかじったことのある人による、Perl体験日記。


計算方法の分析

B棟

寮費の支払い方式 1/16-1/31 2/1-2/15 2/16-2/29 3/1-3/15
一括 (12月)光熱費+概算光熱費(10,000) (12月)光熱費+概算光熱費(10,000) (12月)光熱費+概算光熱費(20,000) (12月)光熱費+概算光熱費(30,000)+3月分寮費(2,300×日数)
二回 (12月)光熱費+概算光熱費(10,000) (12月)光熱費+概算光熱費(10,000) (12月)光熱費+概算光熱費(20,000) (12月)光熱費+概算光熱費(30,000)+3月分寮費(2,300×日数)
月払い (12月)光熱費+概算光熱費(10,000) (12月)光熱費+概算光熱費(10,000)+2月分寮費(66,300) (12月)光熱費+概算光熱費(20,000)+概算光熱費(66,300) (12月)光熱費+概算光熱費(30,000)+2月分寮費(66,300)+3月分寮費(2,300×日数)

C棟

寮費の支払い方式 1/16-1/31 2/1-2/15 2/16-2/29 3/1-3/15
一括 (12月)光熱費+概算光熱費(20,000) (12月)光熱費+概算光熱費(20,000) (12月)光熱費+概算光熱費(30,000) (12月)光熱費+概算光熱費(40,000)+3月分寮費(2,900×日数)
二回 (12月)光熱費+概算光熱費(20,000) (12月)光熱費+概算光熱費(20,000) (12月)光熱費+概算光熱費(30,000) (12月)光熱費+概算光熱費(40,000)+3月分寮費(2,900×日数)
月払い (12月)光熱費+概算光熱費(20,000) (12月)光熱費+概算光熱費(20,000)+2月分寮費(84,700) (12月)光熱費+概算光熱費(30,000)+概算光熱費(84,700) (12月)光熱費+概算光熱費(40,000)+2月分寮費(84,700)+3月分寮費(2,900×日数)
  • わかったこと
    • 一括と二回は計算方法が同じ
    • 一括と二回は1/16-2/15までは計算方法が同じ

必要になるもの

 計算方法の分析ができたので、次は引き落とし金額を求めるのに必要となるデータについて考えた。基本的には、

  • 必要なもの
    • B棟なのかC棟なのか
    • 部屋番号(後で個人を特定するために)
    • 退寮日
    • 12月分光熱費

ということが判明。『新版Perl言語プログラミングレッスン入門編』を参考にCSVからデータを吸い上げる方法がわかる。だがここで、退寮日の記述方式が「月/日」という形式だと現状の自分の手には余ると判断。「退寮日」を「退寮する月」と「退寮する日」に分割することでこの問題の回避をはかった。従って、用意するCSVには

  1. CSVファイル
    1. 部屋番号
    2. 退寮する月
    3. 退寮日
    4. 12月分光熱費

という構成にすることにした。このデータはExcelを使えば簡単に作れるだろうから、後はPerlで計算する部分を作る。*1

はまった部分

  • foreach構文の$_の部分→$_に格納されるのってカウンタじゃなくて、配列の具体的な値なのですね。。。
  • 初歩的だけど、elseifじゃなかったんだ。。。elsif
  • Cygwin上のchompはうまく動かない改行コードとか文字コードの違いかな

できたもの

use strict;
use warnings;
# temp.csv を開く。存在しなければ、スクリプトを終了する
open (FILE, 'temp.csv') or die "$!";
while (my $line = <FILE>) {
# 一行ずつ読み込んで、@dataに格納する
my @data = split(/,/, $line);
# temp.csvの構造は
# 棟,部屋番号,支払い方法,退寮する月,退寮する日,12月分光熱費
# ちなみに支払い方法:
# 1 : 一括払い 2 : 二回払い 3 : 月払い
# だから、
# @data[0] --> 棟 // @data[1] --> 部屋番号 // @data[2] --> 支払い方法
# @data[3] --> 退寮する月 // @data[4] --> 退寮する日
# @data[5] --> 光熱費
# B棟の人の場合
if ($data[] eq "B"){
print $data[] . $data[1] . ",";
# 一括と二回は同じ計算式なので、
# ここでは同じものとして扱う
if ($data[2] == 1 || $data[2] == 2){
# 1/162/15のとき
if (($data[3] == 1 && $data[4] >= 16) || ($data[3] == 2 && $data[4] <= 15)) {
# 支払う金額は、「10,000 + 12月分光熱費」
print 10000 + $data[5] . "\n";
# 2/162/29のとき
} elsif ($data[3] == 2 && $data[4] <= 29) {
# 支払う金額は、「20,000 + 12月分光熱費」
print 20000 + $data[5] . "\n";
# 3/13/15のとき
} elsif ($data[3] == 3 && $data[4] <=15) {
# 支払う金額は、「30,000 + 12月分光熱費 + 3月分寮費」
print 30000 + $data[5] + (2300 * $data[4]) . "\n";
} else {
print "data out of range!\n";
}
# 月払いの時
} elsif ($data[2] ==3) {
# 1/161/31の時
if ($data[3] == 1 && $data[4] <= 31) {
# 支払う金額は、「10,000 + 12月分光熱費」
print 10000 + $data[5] . "\n";
# 2/12/15のとき
} elsif ($data[3] == 2 && $data[4] <= 15) {
# 支払う金額、「10,000 + 66300 + 12月分光熱費」
print 10000 + 66300 + $data[5] . "\n";
# 2/162/29のとき
} elsif ($data[3] == 2 && $data[4] <= 29) {
# 支払う金額は、「20,000 + 66,300 + 12月分光熱費」
print 20000 + 66300 + $data[5] . "\n";
# 3/13/15のとき
} elsif ($data[3] == 3 && $data[4] <= 15){
# 支払う金額は、
#「30,000 + 66,300 + 3月分寮費(2300 * 日数) + 12月分光熱費」
print 30000 + 66300 + (2300 * $data[4]) + $data[5] . "\n";
} else {
print "data out of range!\n";
}
}
}
# C棟の人の場合
if ($data[] eq "C"){
print $data[] . $data[1] . ",";
# 一括と二回は同じ計算式なので、
# ここでは同じものとして扱う
if ($data[2] == 1 || $data[2] == 2){
# 1/162/15のとき
if (($data[3] == 1 && $data[4] >= 16) || ($data[3] == 2 && $data[4] <= 15)) {
# 支払う金額は、「20,000 + 12月分光熱費」
print 20000 + $data[5] . "\n";
# 2/162/29のとき
} elsif ($data[3] == 2 && $data[4] <= 29) {
# 支払う金額は、「30,000 + 12月分光熱費」
print 30000 + $data[5] . "\n";
# 3/13/15のとき
} elsif ($data[3] == 3 && $data[4] <=15) {
# 支払う金額は、「40,000 + 12月分光熱費 + 3月分寮費」
print 40000 + $data[5] + (2900 * $data[4]) . "\n";
} else {
print "data out of range!\n";
}
# 月払いの時
} elsif ($data[2] ==3) {
# 1/161/31の時
if ($data[3] == 1 && $data[4] <= 31) {
# 支払う金額は、「20,000 + 12月分光熱費」
print 20000 + $data[5] . "\n";
# 2/12/15のとき
} elsif ($data[3] == 2 && $data[4] <= 15) {
# 支払う金額、「20,000 + 84700 + 12月分光熱費」
print 20000 + 84700 + $data[5] . "\n";
# 2/162/29のとき
} elsif ($data[3] == 2 && $data[4] <= 29) {
# 支払う金額は、「30,000 + 84,700 + 12月分光熱費」
print 30000 + 84700 + $data[5] . "\n";
# 3/13/15のとき
} elsif ($data[3] == 3 && $data[4] <= 15){
# 支払う金額は、
#「40,000 + 84,700 + 3月分寮費(2900 * 日数) + 12月分光熱費」
print 40000 + 84700 + (2900 * $data[4]) + $data[5] . "\n";
} else {
print "data out of range!\n";
}
}
}
}
close(FILE);

今後の課題

  • もっとPerlに慣れて早く書けるようになる
  • こういう形で整形するのは便利と言うことがわかったから、もっと勉強してみたい

こんなのを見つけた:

*1「Excelですべて作ってしまえば」という声もあるけれど、何十もの括弧で区切られる数式をいちいちやるのが面倒くさかったりして