Project Euler (Problem 1,2,3,4,5)
概要
Project Euler の問題をすこ~しだけ解いてみたのでその解答を残してみる。解答の値は、「プロジェクトオイラーの解答」と一致するので正解のはずです。
ただこのコード、数学力のない文系が書いているのでいろいろよろしくないと思う。
そして数学力があればおそらく高速化、っていうか Problem 3 とかおそらく秒殺するアルゴリズムとかあるはずです。。。
今回 C++, Perl, JavaScript で解答を書いていて、書いたコードは Perl 5.8.8, node.js v0.10.25, g++ 4.6.3 で動作確認できています。
どうでもいいけど、私の開発環境って結構レガシー(node.js を除くと)な環境だな・・・バージョンを改めて確認すると・・・まぁサーバーの Perl はしっかり 5.12 にしているけどな!
Problem 1
C++
// Problem 1
// http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%201
#include <iostream>
using namespace std;
inline bool is3or5(int const n)
{
return ((n%3)==0 || (n%5)==0);
}
int main(int argc, char* argv[])
{
int ans = 0;
for (int i = 0; i < 1000; ++i) {
ans += i*(static_cast<int>(is3or5(i)));
}
cout << ans << endl;
return (0);
}
Perl
use strict;
use warnings;
use utf8;
# Problem 1
# http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%201
# 3か5の倍数になっている数かを判定
sub is3or5 {
my @param = @_;
unless (defined($param[0])) {
print "param is not set.\n";
return (0);
}
# 3の倍数である数ならば、3で割ったあまりは0である。
if (($param[0] % 3) == 0) {
# print $param[0] . "\n";
return (1);
}
elsif (($param[0] % 5) == 0) {
# print $param[0] . "\n";
return (1);
}
return (0);
}
my $ans = 0;
for (my $i = 0; $i < 1000; $i++) {
if (is3or5($i)) {
$ans += $i;
}
}
print $ans . "\n";
JavaScript
// Problem 1
// http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%201
// 3 か 5 の倍数か否かを判定
function is3or5(p) {
if ((p % 3) == 0) {
return (1);
}
else if ((p % 5) == 0) {
return (1);
}
return (0);
}
var ans = 0;
for (var i = 0; i < 1000; i++) {
if (is3or5(i)) {
ans += i;
}
}
console.log(ans);
Problem 2
C++
// Problem 2
// http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%202
#include <iostream>
using namespace std;
inline bool IsEvenNumber(int const n)
{
return ((n%2)==0);
}
int main(int argc, char* argv[])
{
int a = 1, b = 0, c = 0;
int ans = 0;
while (a < 4000000) {
c = b;
b = a;
a = b + c;
ans += a * static_cast<int>(IsEvenNumber(a));
}
cout << ans << endl;
return (0);
}
Perl
use strict;
use warnings;
use utf8;
# Problem 2
# http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%202
# 渡された数が偶数であるか判定する。
sub isEvenNumber {
if (($_[0] % 2) == 0) {
return (1);
}
return (0);
}
# フィボナッチ数列を求める。
my $a = 1;
my $b = 0;
my $c = 0;
my $ans = 0;
while ($a < 4000000) {
$c = $b;
$b = $a;
$a = $b + $c;
# print $a . " ";
if (isEvenNumber($a)) {
# print "ADD : ${a}\n";
$ans += $a;
}
}
print "\n\n";
print "The Answer is ${ans}.\n";
JavaScript
// Problem 2
// http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%202
// 渡された数が偶数であるか判定する。
function isEvenNumber(n) {
if ((n % 2) == 0) {
return (1);
}
return (0);
}
// フィボナッチ数列を求める。
var a = 1, b = 0, c = 0;
var ans = 0;
while (a < 4000000) {
c = b;
b = a;
a = b + c;
if (isEvenNumber(a)) {
ans += a;
}
}
console.log(ans);
Problem 3
C++
// Problem 3
// http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%203
// 注意、auto 型を型推論として使用しているので、コンパイルオプションに下記を指定する必要がある。( GCC 4.6 )
// g++ problem3.cpp -std=c++0x
#include <iostream>
#include <vector>
using namespace std;
// 素数の配列を取得する。
vector<__int64> GetPrimeNumber(__int64 max)
{
vector<__int64> tmp;
tmp.push_back(1);
tmp.push_back(2);
for (__int64 i = 0; i < max; ++i) {
bool flag = false;
for (auto itr = tmp.begin(); itr != tmp.end(); ++itr) {
if (*itr == 1) {
continue;
}
if ((i % *itr) == 0) {
flag = true;
break;
}
}
if (!flag) {
tmp.push_back(i);
}
}
return (tmp);
}
int main(int argc, char* argv[])
{
vector<__int64> list;
cout << "startup..." << endl;
list = GetPrimeNumber(600851475143);
cout << "check..." << endl;
__int64 x = 600851475143;
__int64 ans = 0;
bool flag = true;
while (flag) {
flag = false;
for (auto itr = list.begin(); itr != list.end(); ++itr) {
if (*itr == 0 || *itr == 1) {
continue;
}
if ((x % *itr) == 0) {
flag = true;
x /= *itr;
if (*itr > ans) {
ans = *itr;
}
}
}
}
cout << ans << endl;
return (0);
}
Perl
use strict;
use warnings;
use utf8;
# Problem 3
# http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%203
my @listPrimeNumber = ();
sub SetupPrimeNumberList {
my $max = $_[0];
push (@listPrimeNumber, 1);
push (@listPrimeNumber, 2);
for (my $i = 0; $i < $max; $i++) {
my $flag = 0;
foreach my $n (@listPrimeNumber) {
if ($n == 1) {
# 1 はスキップ
next;
}
if (($i % $n) == 0) {
$flag = 1;
last;
}
}
if ($flag == 0) {
push(@listPrimeNumber, $i);
}
}
}
print "Startup...\n";
SetupPrimeNumberList(10000);
#foreach my $n (@listPrimeNumber) {
# print $n . "\n";
#}
print "Checking...\n";
my $x = 600851475143;
my $ans = 0;
while (1) {
my $flag = 0;
foreach my $n (@listPrimeNumber) {
if ($n == 0 or $n == 1) {
next;
}
if (($x % $n) == 0) {
$flag = 1;
# print $n . "\n";
$x /= $n;
if ($n > $ans) {
$ans = $n;
}
}
}
# 素数になるまで切り詰めた。
if ($flag == 0) {
last;
}
}
print "Answer : ${ans}\n";
JavaScript
// Problem 3
// http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%203
function GetPrimeNumber(max)
{
var tmp = [];
tmp.push(1);
tmp.push(2);
for (var i = 0; i < max; ++i) {
var flag = false;
for (var j = 0; j < tmp.length; ++j) {
if (tmp[j] == 1) {
if (i == 1) {
flag = true;
break;
}
continue;
}
if ((i % tmp[j]) == 0) {
flag = true;
break;
}
}
if (!flag) {
tmp.push(i);
}
}
return (tmp);
}
var list = [];
console.log("startup...");
list = GetPrimeNumber(600851475143);
console.log("checking...");
var x = 600851475143;
var ans = 0;
var flag = true;
while (flag) {
flag = false;
for (var i = 0; i < list.length; ++i) {
if (list[i] == 0 || list[i] == 1) {
continue;
}
if ((x % list[i]) == 0) {
flag = true;
x /= list[i];
if (list[i] > ans) {
ans = list[i];
}
}
}
}
console.log(ans);
Problem 4
C++
// Problem 4
// http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%204
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
// 3x3 は max 6 桁
bool IsLoopNumber(int const n)
{
int len = 0;
char buf[0xFF];
sprintf(buf, "%d", n);
len = strlen(buf);
/* if (buf[0] != buf[len-1]) {
return (false);
}
if (len < 4) {
// この時点で頭と尻尾の一致を確認した。
// 2 桁 もしくは 3 桁の回文数
// 次は n < 6, n < 8 で判定する。
return (true);
}*/
// 上記を一般化
for (int i = 0; i < len / 2; ++i) {
if (buf[i] != buf[len-(1+i)]) {
return (false);
}
if (len < (i+1)*2 + 2) {
return (true);
}
}
return (true);
}
int main(int argc, char* argv[])
{
int ans = 0;
for (int x = 100; x < 1000; ++x) {
for (int y = 100; y < 1000; ++y) {
int n = x*y;
if (IsLoopNumber(n)) {
// cout << n << ":" << x << "," << y << endl;
if (n > ans) {
ans = n;
}
}
}
}
cout << ans << endl;
return (0);
}
Problem 5
C++
// Problem 5
// http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%205
#include <iostream>
using namespace std;
bool IsOk(int const n)
{
const int max = 20;
for (int i = 1; i <= max; ++i) {
if ((n%i) != 0) {
return (false);
}
}
return (true);
}
int main(int argc, char* argv[])
{
int ans = 1;
while (true) {
if (IsOk(ans)) {
break;
}
++ans;
}
cout << ans << endl;
return (0);
}
Perl
use strict;
use warnings;
use utf8;
# Problem 5
# http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%205
sub isOk {
my @param = @_;
unless (defined($param[0])) {
die("Parameter is not set.");
}
my $max = 20;
for (my $i = 1; $i <= $max; $i++) {
if (($param[0] % $i) != 0) {
return (0);
}
}
return (1);
}
my $ans = 1;
while (1) {
if (isOk($ans)) {
last;
}
$ans++;
}
print $ans . "\n";
JavaScript
// Problem 5
// http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%205
// 判定はこれで済ます。数学的美意識を持ちたくとも、私には数学的知識が不足しているのだ・・・
function IsOk(n) {
var max = 20;
for (var i = 1; i <= max; i++) {
if ((n%i) != 0) {
return (false);
}
}
return (true);
}
var ans = 0;
for (var i = 1; i < 1000000000; ++i) {
if (IsOk(i)) {
if (i < ans || ans == 0) {
// 最小値を取得。
ans = i;
}
}
}
if (ans == 0) {
console.log("Not found...");
}
else {
console.log(ans);
}
感想
やはり、数学力がないとコンピューターに無駄な計算をさせてしまう。Problem 3 の GetPrimeNumber(600851475143); これをそのままやると相当時間かかる、っていうか1日じゃ終わらないと思う。
ただ、GetPrimeNumber(10000); でも解答と同じ値は出るんだ・・・これを回答とするのは、相当グレーだとは思うが、私の実力的には仕方ない。書かないことには実力は伸びない。たとえあれなコードでも書かないことには始まらないと思いました。言い訳ですはい。
Problem 4 は回文数を数学的に処理する良い方法が思いつかなかったので、C++ で C言語的に文字列処理で解決してみたが、うーん。スマートだとは言えないよなぁっていう。Problem 4 に関してはおそらく Perl は正規表現、JavaScript でもうまくやれば行けるとは思うのだけど、ちょっと書き起こすエネルギーがわかなかったです・・・
以上