paizaオンラインハッカソン6に参加してみた(緑川つばめミッション, Perl, PHP, Ruby, Python)及びpaizaオンラインハッカソン6に参加してみた(六村リオミッション, Perl, PHP, Ruby, Python)に続き、今回は霧島京子ミッションをPerl、PHP、Ruby、Pythonで記述してみた場合の回答例を挙げてみたい。
回答例
Perl
[code lang=”perl”]use strict;
use warnings;
use constant {
CURRENT => 0,
FINISHED => 1,
DEAD => 2,
};
my $str = <STDIN>;
chomp($str);
my $numOfCells = $str + 0;
my $goal = $numOfCells – 1;
$str = <STDIN>;
chomp($str);
my @cells = split(" ", $str);
$str = <STDIN>;
chomp($str);
my $acts = $str + 0;
for my $act (1…$acts) {
$str = <STDIN>;
chomp($str);
my $actNum = $str + 0;
my @moveLog = ();
my $state = CURRENT;
while ($state == CURRENT) {
if ($actNum == $goal) {
$state = FINISHED;
}elsif($actNum < 1 || $goal < $actNum) {
$state = DEAD;
}else{
my $moves = $cells[$actNum] + 0;
if ($moves == 0) {
$state = DEAD;
}else{
$actNum += $moves;
foreach my $movedNum (@moveLog) {
if ($actNum == $movedNum) {
$state = DEAD;
last;
}
}
if ($state != DEAD) {
@moveLog = (@moveLog, $actNum);
}
}
}
}
print ($state == FINISHED ? "Yes\n" : "No\n");
}[/code]
PHP
[code lang=”php”]<?php
$numOfCells = (int)fgets(STDIN);
$goal = $numOfCells – 1;
$cells = split(" ", trim(fgets(STDIN)));
const CURRENT = 0;
const FINISHED = 1;
const DEAD = 3;
$acts = (int)fgets(STDIN);
for ($act = 0; $act < $acts; $act++) {
$actNum = (int)fgets(STDIN);
$moveLog = array();
$status = CURRENT;
while ($status == CURRENT) {
if ($actNum == $goal) {
$status = FINISHED;
}elseif($actNum < 1 || $goal < $actNum) {
$status = DEAD;
}else{
$moves = (int)$cells[$actNum];
if ($moves == 0) {
$status = DEAD;
}else{
$actNum += $moves;
foreach ($moveLog as $movedNum) {
if ($actNum == $movedNum) {
$status = DEAD;
break;
}
}
if ($status != DEAD) {
$moveLog[] = $actNum;
}
}
}
}
print($status == FINISHED ? "Yes\n" : "No\n");
}
?>[/code]
Ruby
[code lang=”ruby”]numOfCells = gets.to_i
goal = numOfCells – 1
cells = gets.strip.split(" ")
CURRENT = 0
FINISHED = 1
DEAD = 2
gets.to_i.times {
actNum = gets.to_i
moveLog = Array.new
status = CURRENT
while status == CURRENT do
if actNum == goal then
status = FINISHED
elsif actNum < 1 || goal < actNum then
status = DEAD
else
moves = cells[actNum].to_i
if moves == 0 then
status = DEAD
else
actNum += moves
moveLog.each {|movedNum|
if actNum == movedNum then
status = DEAD
break
end
}
if status != DEAD then
moveLog.push(actNum)
end
end
end
end
puts status == FINISHED ? "Yes" : "No"
}[/code]
Python 2.x系
[code lang=”python”]numOfCells = int(raw_input())
goal = numOfCells – 1
cells = raw_input().strip().split(" ")
CURRENT = 0
FINISHED = 1
DEAD = 2
for idx in range(0, int(raw_input())):
actNum = int(raw_input())
moveLog = []
status = CURRENT
while status == CURRENT:
if actNum == goal:
status = FINISHED
elif actNum < 1 or goal < actNum:
status = DEAD
else:
moves = int(cells[actNum])
if moves == 0:
status = DEAD
else:
actNum += moves
for movedNum in moveLog:
if actNum == movedNum:
status = DEAD
break
if status != DEAD
moveLog.append(actNum)
print ("Yes" if status == FINISHED else "No")[/code]
解説
今回も先立つC言語、C++、C#、Javaと同じく、シミュレーション形式をベースに行ってみた。出目数を元にゴールまで到着できればYes、スタート地点に戻った、ゴール時点を超えた、あるいはこれ以上進めない、もしくは無限ループ状態に入ったことが明らかな場合はNoと出力するという方式である。ちなみに、すごろくのマスに配列を使っている関係上、ゴールはマスの数-1とする点がミソである ((多くの言語では配列のインデックス値は0始まりとなっている)) 。
Perl及びPHPは鉤括弧「{…}」、Rubyでは一部を除き「do/thenなど…end」でブロックを定義しているが、Pythonではタブがブロックの区切りとなっている。そのためか、簡潔さではPythonに軍配があがるということになるのだろうか。
定数を定義する際、Perlではconstant、PHPではdefineまたはconst ((constは古いバージョンでは使えない)) 、Rubyでは大文字で始まる変数名の変数が定数として扱える。Pythonでは定数自体は無いが、C言語系統の#defineあるいはJavaの定数などの影響を受けてからか、全て大文字のスネークケースの変数を擬似的に定数として扱う慣習がある。
最後に
ここまでPOH6の回答例をC言語、C++、C#、Java、Perl、PHP、Ruby、Pythonで掲載してみたが、どういう風に書いていけばいいのか参考にしていただけただろうか?
今回の3つの問題については、ある程度のプログラミングが理解できれば問題なく解答できるので、ぜひチャレンジてみると良いだろう。
ウェブマスター。本ブログでITを中心にいろいろな情報や意見などを提供しています。主にスマートフォン向けアプリやウェブアプリの開発を携わっています。ご用の方はコメントかコンタクトフォームにて。