2012年7月22日日曜日

Project Euler-Problem22をgroovyで解いてみる

問題

http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2022

問題を解いたプログラム

1行にすべての値が書かれているとは思わなかった・・・
def alphaRange = 'A'..'Z'
def index = 0
println new File('names.txt').readLines().join(",").split(",").sort().inject(0) {result, line ->
  result + line.split(",").sort().inject(0) {lineTotal, element ->
    lineTotal + (element.inject(0) {elementTotal, chr ->
      elementTotal + alphaRange.indexOf(chr) + 1
    } * (++index))
  }
}

Java7のNIO2-Pathクラス

Java7のNIO2の勉強し始めたので、まずはPathクラスあたりを。

Path path = Paths.get("./test.txt");
System.out.println("path.toString() = " + path.toString());
System.out.println("path.getFileName() = " + path.getFileName());
// 不要な「.」や「\」なんかを取り除いてくれる。
System.out.println("path.normalize() = " + path.normalize());
// 絶対パスかどうか
System.out.println("path.isAbsolute() = " + path.isAbsolute());
// 絶対パスに変換
System.out.println("path.toAbsolutePath() = " + path.toAbsolutePath());
// 不要なものを取り除いて絶対パスに
System.out.println("path.normalize().toAbsolutePath() = " + path.normalize().toAbsolutePath());

実行結果
path.toString() = .\test.txt
path.getFileName() = test.txt
path.normalize() = test.txt
path.isAbsolute() = false
path.toAbsolutePath() = C:\work\test\.\test.txt
path.normalize().toAbsolutePath() = C:\work\test\test.txt

2012年7月21日土曜日

Project Euler-Problem21をgroovyで解いてみる

問題

d(n)をnの真の約数の和と定義する。(真の約数とはn以外の約数のことである。)
もし、d(a) = b かつ d(b) = a (a ≠ b)を満たすとき、aとbは友愛数(親和数)であるという。

例えば、220の約数は1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110なのでd(220) = 284である。
また、284の約数は1, 2, 4, 71, 142なのでd(284) = 220である。

それでは10000未満の友愛数の合計を求めよ。

問題を解いたプログラム

def getSumAliquot(def num) {
  (1..(num / 2)).findAll {num % it == 0}.sum()
}

println((1..<10000).sum {
  def aliquot = getSumAliquot(it)
  it != aliquot && it == getSumAliquot(aliquot) ? aliquot : 0
})

2012年7月16日月曜日

Project Euler-Problem19をgroovyで解いてみる

問題

次の情報が与えられている。

1900年1月1日は月曜日である。
9月、4月、6月、11月は30日まであり、2月を除く他の月は31日まである。
2月は28日まであるが、うるう年のときは29日である。
うるう年は西暦が4で割り切れる年に起こる。しかし、西暦が400で割り切れず100で割り切れる年はうるう年でない。
20世紀(1901年1月1日から2000年12月31日)で月の初めが日曜日になるのは何回あるか。

問題を解いたプログラム

def current = Calendar.getInstance()
current.set(1901, 1, 1)

def end = Calendar.getInstance()
end.set(2000, 12, 31)

int sundayCount = 0
while (current <= end) {
  if (current.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
    sundayCount++
  }
  current.set(Calendar.MONTH, current.get(Calendar.MONTH) + 1)
}
println "sundayCount = ${sundayCount}"

Project Euler-Problem20をgroovyで解いてみる

問題

n × (n - 1) × ... × 3 × 2 × 1 を n! と表す。

100! の各桁の数字の合計を求めよ。。

問題を解いたプログラム

Problem16と同じような構造です。
def ret = (new BigInteger(100)..new BigInteger(1)).inject(new BigInteger(1)) {num1, num2 ->
  num1.multiply(num2)
}.toString().collect{Integer.valueOf(it)}.sum()

println "ret = ${ret}"


解けない問題が増えてきた

2012年7月14日土曜日

Project Euler-Problem16をgroovyで解いてみる

問題

15 = 32768 であり、これの各数字の合計は 3 + 2 + 7 + 6 + 8 = 26 となる。

同様にして、21000 の各数字の合計を求めよ。

問題を解いたプログラム

クロージャがあるから簡単にかけてますが、JavaのAPIを使っているだけです。
import java.text.DecimalFormat

def format = new DecimalFormat("#")
println format.format(new BigInteger(2).pow(1000)).collect {Integer.valueOf(it)}.sum()

7/16:足し込むところを、collectionのsum関数を使うように変更。

2012年7月13日金曜日

[Oracle]pl/sqlの変数宣言

PL/SQLの変数宣言のまとめ

変数

declare
  -- 初期値なしで変数宣言
  v1 char(1);
  -- 初期値ありで変数宣言
  v2 varchar2(100) default 'ほげ';
  -- 他の変数の型で変数宣言
  v3 v2%type default 'ふが';
begin
  dbms_output.put_line(v1);
  dbms_output.put_line(v2);
  dbms_output.put_line(v3);
end;
/

定数

declare
  const_name constant varchar2(100) not null default '定数';
begin
  dbms_output.put_line(const_name);
end;
/

------------------------------
-- 実行結果
------------------------------
定数

PL/SQLプロシージャが正常に完了しました。

定数値を変更しようとすると例外が発生します。
-- 定数値を変更するステートメントを追加した場合
const_name := '書き換え';

------------------------------
-- 実行結果
------------------------------
行5でエラーが発生しました。:
ORA-06550: 行5、列3:
PLS-00363: 式CONST_NAMEは割当てターゲットとして使用できません。
ORA-06550: 行5、列3:
PL/SQL: Statement ignored

NULL不可変数

declare
  -- not nullを属性をつけることで、nullの代入がNGとなる。
  v1 char(1) not null default '1';
begin
  dbms_output.put_line(v1);
end;
/

procedureでnull不可の変数に「null」を代入しようとするとコンパイルエラーとなる
create or replace procedure hoge
is
  -- 初期値なしで変数宣言
  v1 char(1) not null default '1';
  v2 char(1);
begin
  v1 := null;
end;
/

LINE/COL ERROR
-------- -----------------------------------------------------------------
7/3      PL/SQL: Statement ignored
7/9      PLS-00382: 式の型が正しくありません。

procedureでnull不可の変数に別の変数の値を代入した場合、実行時エラーとなる
  1  create or replace procedure hoge
  2  is
  3    -- 初期値なしで変数宣言
  4    v1 char(1) not null default '1';
  5    v2 char(1);
  6  begin
  7    v1 := v2;
  8* end;
16:50:25 SQL> /

プロシージャが作成されました。

経過: 00:00:00.01
16:50:26 SQL> exec hoge
BEGIN hoge; END;

*
行1でエラーが発生しました。:
ORA-06502: PL/SQL: 数値または値のエラーが発生しました
ORA-06512: "HOGE", 行7
ORA-06512: 行1

2012年7月8日日曜日

[Oracle]PL/SQLでの数値計算はPLS_INTEGER(サブタイプ含む)を使用する

「PL/SQL言語リファレンス」によると、PL/SQLでの数値計算はNUMBERを使用するより、PLS_INTEGER(またはそのサブタイプ)を使用したほうが高速に処理できるようです。詳細は、以下のドキュメントに記述されています。

PLS_INTEGERおよびBINARY_INTEGERデータ型

また、上記のドキュメントによるとNULLが許容されずに計算時にオーバーフローが起こり得ない数値の場合には、PLS_INTEGERのサブタイプの「SIMPLE_INTEGER」を使用するほうがより高速なようです。

SIMPLE_INTEGERの詳細
PLS_INTEGERのSIMPLE_INTEGERサブタイプ

今まで、PLS_INTEGERを使うようにしてきたけど、用途によってはSIMPLE_INTEGERも検討しないと。