paizaオンラインハッカソン6に参加してみた(六村リオミッション, Perl, PHP, Ruby, Python)

注意: この記事は1年以上前に掲載されたものです。情報が古い場合がありますのでお気を付け下さい。

paizaオンラインハッカソン6に参加してみた(緑川つばめミッション, Perl, PHP, Ruby, Python)に続いて、今回は六村リオミッションをPerl, PHP, Ruby, Pythonで書いてみた。

回答例

Perl

[code lang=”perl”]use strict;
use warnings;

package Coffee; {
sub new() {
my $class = shift;
my $self = {
water => 0.0,
powder => 0.0,
};
bless $self, $class;
return $self;
}

sub addWater {
my $self = shift;
my $quantity = $_[0];
$self->{water} += $quantity;
}

sub addPowder {
my $self = shift;
my $quantity = $_[0];
$self->{powder} += $quantity;
}

sub getTotal {
my $self = shift;
return $self->{powder} + $self->{water};
}

sub taste {
my $self = shift;
my $quantity = $_[0];
my $total = $self->getTotal;
$self->{powder} -= $quantity * $self->{powder} / $total;
$self->{water} -= $quantity * $self->{water} / $total;
}

sub getConsentration {
my $self = shift;
my $asPercent = $_[0];
return ($self->{powder} / $self->getTotal) * ($asPercent ? 100.0 : 1.0);
}
}

my $coffee = Coffee->new();
my $str = <STDIN>;
chomp($str);
my $acts = $str + 0;
for my $cnt (1…$acts) {
my $actLine = <STDIN>;
chomp($actLine);
my @actArr = split(" ", $actLine);
my $actType = $actArr[0];
my $quantity = $actArr[1];
if ($actType == 1) {
$coffee->addWater($quantity);
}elsif ($actType == 2) {
$coffee->addPowder($quantity);
}elsif ($actType == 3) {
$coffee->taste($quantity);
}
}

printf("%d\n", $coffee->getConsentration(1));[/code]

PHP

[code lang=”php”]<?php
class Coffee {
private $_water = 0.0;
private $_powder = 0.0;
public function addWater($quantity) {
$this->_water += $quantity;
}
public function addPowder($quantity) {
$this->_powder += $quantity;
}
public function getTotal() {
return $this->_water + $this->_powder;
}
public function taste($quantity) {
$total = $this->getTotal();
$this->_water -= $quantity * $this->_water / $total;
$this->_powder -= $quantity * $this->_powder / $total;
}
public function getConsentration($asPercent) {
return ($this->_powder / $this->getTotal()) * ($asPercent ? 100.0 : 1.0);
}
}
$coffee = new Coffee();
$acts = (int)trim(fgets(STDIN));
for ($count = 0; $count < $acts; $count++) {
$arr = split(" ", trim(fgets(STDIN)));
$actType = (int)$arr[0];
$quantity = (int)$arr[1];
switch ($actType) {
case 1:
$coffee->addWater($quantity);
break;
case 2:
$coffee->addPowder($quantity);
break;
case 3:
$coffee->taste($quantity);
break;
}
}
print((int)$coffee->getConsentration(true));
?>[/code]

Ruby

[code lang=”ruby”]class Coffee
def initialize
@water = 0.0
@powder = 0.0
end

def addWater(quantity)
@water += quantity
end

def addPowder(quantity)
@powder += quantity
end

def getTotal
return @water + @powder
end

def taste(quantity)
total = getTotal
@water -= quantity * @water / total
@powder -= quantity * @powder / total
end

def getConsentration(asPercent)
return (@powder / getTotal) * (asPercent ? 100.0 : 1.0)
end
end

coffee = Coffee.new()

gets.to_i.times {
arr = gets.split(" ")
actType = arr[0].to_i
quantity = arr[1].to_f
if actType == 1 then
coffee.addWater(quantity)
elsif actType == 2 then
coffee.addPowder(quantity)
elsif actType == 3 then
coffee.taste(quantity)
end
}
puts coffee.getConsentration(true).to_i[/code]

Python (2.7系)

[code lang=”python”]class Coffee:
def __init__(self):
self.water = 0.0
self.powder = 0.0

def addWater(self, quantity):
self.water += quantity

def addPowder(self, quantity):
self.powder += quantity

def getTotal(self):
return self.powder + self.water

def taste(self, quantity):
total = self.getTotal()
self.water -= quantity * self.water / total
self.powder -= quantity * self.powder / total

def getConsentration(self, asPercent):
return (self.powder / self.getTotal()) * (100.0 if asPercent else 1.0)

coffee = Coffee()

for idx in range(0, int(raw_input().strip())):
arr = raw_input().strip().split(" ")
actType = int(arr[0])
quantity = float(arr[1])
if actType == 1:
coffee.addWater(quantity)
elif actType == 2:
coffee.addPowder(quantity)
elif actType == 3:
coffee.taste(quantity)

print(int(coffee.getConsentration(True)))[/code]

解説

六村リオミッションにおいては、今回もクラスベースのオブジェクト指向の方法を採用して解法を作成してみた。注意すべき点としては味見の際にあらかじめ合計値を持っておくべき点だけだろう 1 。PHP及びRuby、Pythonについては、C++系のクラスベースのオブジェクト指向プログラミングの手法が使えるため、C++やJava、C#のいずれかがわかれば、それぞれの言語の記法になれればそれほど問題にはならないだろう。C++やJavaと最も近いという意味ではPHP、RubyとPythonは記述のフォーマットやメソッドの違いこそあるもののかなり似通った記述になった。

なお、Python 2.7系については、インスタンスメソッドを定義する際には必ず最初の引数にselfを入れなければならない点は要注意である。

ただし、Perlについてはオブジェクト指向プログラミングのやり方がC++及びJavaの系統とは大きく異なる点で要注意である。メソッド定義に引数を入れる方式ではなく、@_の配列より引数を取得するという方法なのと、自分自身の参照についても必ずshiftを使って変数に持たせなければならない点などが挙げられる。また、インスタンス変数は実質的には連想配列のキーとなっている模様である。いずれにしても、C++系の言語のやり方とはかなり毛色が異なるため、かなり戸惑うだろう。

最後に

今回はPerl、PHP、Ruby、Perlで、なおかつオブジェクト指向プログラミングを採用して六村リオミッションにチャレンジしたが、Perlを除けばかなり似通っていて一つでもわかれば他の言語でもそれほど違和感なく使えるようになっていた。一方、オブジェクト指向プログラミングを行う際においては、Perlはかなり独特な記法をする必要があり、その点でかなり戸惑う点で大きく違っていた。

次は、霧島京子ミッションの回答例と解説を挙げてみたい。

ウェブマスター。本ブログでITを中心にいろいろな情報や意見などを提供しています。ご用の方はコメントかコンタクトフォームにて。
  1. 仮にその都度getTotalメソッドを叩いた場合、粉あるいは湯の減算した処理が影響して計算結果がおかしくなる []